blob: fb07e5edb2af0c87d32dc1d4bf9c89dc437f737a [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 Moolenaar33570922005-01-25 22:26:29 +0000126 * Array to hold the hashtab with variables local to each sourced script.
127 * Each item holds a variable (nameless) that points to the dict_T.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000128 */
Bram Moolenaar33570922005-01-25 22:26:29 +0000129typedef struct
130{
131 dictitem_T sv_var;
132 dict_T sv_dict;
133} scriptvar_T;
134
135static garray_T ga_scripts = {0, 0, sizeof(scriptvar_T), 4, NULL};
136#define SCRIPT_SV(id) (((scriptvar_T *)ga_scripts.ga_data)[(id) - 1])
137#define SCRIPT_VARS(id) (SCRIPT_SV(id).sv_dict.dv_hashtab)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000138
139static int echo_attr = 0; /* attributes used for ":echo" */
140
Bram Moolenaar9ef486d2005-01-17 22:23:00 +0000141/* Values for trans_function_name() argument: */
142#define TFN_INT 1 /* internal function name OK */
143#define TFN_QUIET 2 /* no error messages */
144
Bram Moolenaar071d4272004-06-13 20:20:40 +0000145/*
146 * Structure to hold info for a user function.
147 */
148typedef struct ufunc ufunc_T;
149
150struct ufunc
151{
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000152 int uf_varargs; /* variable nr of arguments */
153 int uf_flags;
154 int uf_calls; /* nr of active calls */
155 garray_T uf_args; /* arguments */
156 garray_T uf_lines; /* function lines */
Bram Moolenaar05159a02005-02-26 23:04:13 +0000157#ifdef FEAT_PROFILE
158 int uf_profiling; /* TRUE when func is being profiled */
159 /* profiling the function as a whole */
160 int uf_tm_count; /* nr of calls */
161 proftime_T uf_tm_total; /* time spend in function + children */
162 proftime_T uf_tm_self; /* time spend in function itself */
163 proftime_T uf_tm_start; /* time at function call */
164 proftime_T uf_tm_children; /* time spent in children this call */
165 /* profiling the function per line */
166 int *uf_tml_count; /* nr of times line was executed */
167 proftime_T *uf_tml_total; /* time spend in a line + children */
168 proftime_T *uf_tml_self; /* time spend in a line itself */
169 proftime_T uf_tml_start; /* start time for current line */
170 proftime_T uf_tml_children; /* time spent in children for this line */
171 proftime_T uf_tml_wait; /* start wait time for current line */
172 int uf_tml_idx; /* index of line being timed; -1 if none */
173 int uf_tml_execed; /* line being timed was executed */
174#endif
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000175 scid_T uf_script_ID; /* ID of script where function was defined,
Bram Moolenaar071d4272004-06-13 20:20:40 +0000176 used for s: variables */
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000177 int uf_refcount; /* for numbered function: reference count */
178 char_u uf_name[1]; /* name of function (actually longer); can
179 start with <SNR>123_ (<SNR> is K_SPECIAL
180 KS_EXTRA KE_SNR) */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000181};
182
183/* function flags */
184#define FC_ABORT 1 /* abort function on error */
185#define FC_RANGE 2 /* function accepts range */
Bram Moolenaare9a41262005-01-15 22:18:47 +0000186#define FC_DICT 4 /* Dict function, uses "self" */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000187
188/*
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000189 * All user-defined functions are found in this hash table.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000190 */
Bram Moolenaar4debb442005-06-01 21:57:40 +0000191static hashtab_T func_hashtab;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000192
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000193/* From user function to hashitem and back. */
194static ufunc_T dumuf;
195#define UF2HIKEY(fp) ((fp)->uf_name)
196#define HIKEY2UF(p) ((ufunc_T *)(p - (dumuf.uf_name - (char_u *)&dumuf)))
197#define HI2UF(hi) HIKEY2UF((hi)->hi_key)
198
199#define FUNCARG(fp, j) ((char_u **)(fp->uf_args.ga_data))[j]
200#define FUNCLINE(fp, j) ((char_u **)(fp->uf_lines.ga_data))[j]
Bram Moolenaar071d4272004-06-13 20:20:40 +0000201
Bram Moolenaar33570922005-01-25 22:26:29 +0000202#define MAX_FUNC_ARGS 20 /* maximum number of function arguments */
203#define VAR_SHORT_LEN 20 /* short variable name length */
204#define FIXVAR_CNT 12 /* number of fixed variables */
205
Bram Moolenaar071d4272004-06-13 20:20:40 +0000206/* structure to hold info for a function that is currently being executed. */
Bram Moolenaar33570922005-01-25 22:26:29 +0000207typedef struct funccall_S
Bram Moolenaar071d4272004-06-13 20:20:40 +0000208{
209 ufunc_T *func; /* function being called */
210 int linenr; /* next line to be executed */
211 int returned; /* ":return" used */
Bram Moolenaar33570922005-01-25 22:26:29 +0000212 struct /* fixed variables for arguments */
213 {
214 dictitem_T var; /* variable (without room for name) */
215 char_u room[VAR_SHORT_LEN]; /* room for the name */
216 } fixvar[FIXVAR_CNT];
217 dict_T l_vars; /* l: local function variables */
218 dictitem_T l_vars_var; /* variable for l: scope */
219 dict_T l_avars; /* a: argument variables */
220 dictitem_T l_avars_var; /* variable for a: scope */
221 list_T l_varlist; /* list for a:000 */
222 listitem_T l_listitems[MAX_FUNC_ARGS]; /* listitems for a:000 */
223 typval_T *rettv; /* return value */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000224 linenr_T breakpoint; /* next line with breakpoint or zero */
225 int dbg_tick; /* debug_tick when breakpoint was set */
226 int level; /* top nesting level of executed function */
Bram Moolenaar05159a02005-02-26 23:04:13 +0000227#ifdef FEAT_PROFILE
228 proftime_T prof_child; /* time spent in a child */
229#endif
Bram Moolenaar33570922005-01-25 22:26:29 +0000230} funccall_T;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000231
232/*
Bram Moolenaar3d60ec22005-01-05 22:19:46 +0000233 * Info used by a ":for" loop.
234 */
Bram Moolenaar33570922005-01-25 22:26:29 +0000235typedef struct
Bram Moolenaar3d60ec22005-01-05 22:19:46 +0000236{
237 int fi_semicolon; /* TRUE if ending in '; var]' */
238 int fi_varcount; /* nr of variables in the list */
Bram Moolenaar33570922005-01-25 22:26:29 +0000239 listwatch_T fi_lw; /* keep an eye on the item used. */
240 list_T *fi_list; /* list being used */
241} forinfo_T;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +0000242
Bram Moolenaar3d60ec22005-01-05 22:19:46 +0000243/*
Bram Moolenaar9ef486d2005-01-17 22:23:00 +0000244 * Struct used by trans_function_name()
245 */
246typedef struct
247{
Bram Moolenaar33570922005-01-25 22:26:29 +0000248 dict_T *fd_dict; /* Dictionary used */
Bram Moolenaar532c7802005-01-27 14:44:31 +0000249 char_u *fd_newkey; /* new key in "dict" in allocated memory */
Bram Moolenaar33570922005-01-25 22:26:29 +0000250 dictitem_T *fd_di; /* Dictionary item used */
251} funcdict_T;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +0000252
Bram Moolenaara7043832005-01-21 11:56:39 +0000253
254/*
Bram Moolenaar33570922005-01-25 22:26:29 +0000255 * Array to hold the value of v: variables.
256 * The value is in a dictitem, so that it can also be used in the v: scope.
257 * The reason to use this table anyway is for very quick access to the
258 * variables with the VV_ defines.
259 */
260#include "version.h"
261
262/* values for vv_flags: */
263#define VV_COMPAT 1 /* compatible, also used without "v:" */
264#define VV_RO 2 /* read-only */
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +0000265#define VV_RO_SBX 4 /* read-only in the sandbox */
Bram Moolenaar33570922005-01-25 22:26:29 +0000266
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +0000267#define VV_NAME(s, t) s, {{t}}, {0}
Bram Moolenaar33570922005-01-25 22:26:29 +0000268
269static struct vimvar
270{
271 char *vv_name; /* name of variable, without v: */
Bram Moolenaar33570922005-01-25 22:26:29 +0000272 dictitem_T vv_di; /* value and name for key */
273 char vv_filler[16]; /* space for LONGEST name below!!! */
274 char vv_flags; /* VV_COMPAT, VV_RO, VV_RO_SBX */
275} vimvars[VV_LEN] =
276{
277 /*
278 * The order here must match the VV_ defines in vim.h!
279 * Initializing a union does not work, leave tv.vval empty to get zero's.
280 */
281 {VV_NAME("count", VAR_NUMBER), VV_COMPAT+VV_RO},
282 {VV_NAME("count1", VAR_NUMBER), VV_RO},
283 {VV_NAME("prevcount", VAR_NUMBER), VV_RO},
284 {VV_NAME("errmsg", VAR_STRING), VV_COMPAT},
285 {VV_NAME("warningmsg", VAR_STRING), 0},
286 {VV_NAME("statusmsg", VAR_STRING), 0},
287 {VV_NAME("shell_error", VAR_NUMBER), VV_COMPAT+VV_RO},
288 {VV_NAME("this_session", VAR_STRING), VV_COMPAT},
289 {VV_NAME("version", VAR_NUMBER), VV_COMPAT+VV_RO},
290 {VV_NAME("lnum", VAR_NUMBER), VV_RO_SBX},
291 {VV_NAME("termresponse", VAR_STRING), VV_RO},
292 {VV_NAME("fname", VAR_STRING), VV_RO},
293 {VV_NAME("lang", VAR_STRING), VV_RO},
294 {VV_NAME("lc_time", VAR_STRING), VV_RO},
295 {VV_NAME("ctype", VAR_STRING), VV_RO},
296 {VV_NAME("charconvert_from", VAR_STRING), VV_RO},
297 {VV_NAME("charconvert_to", VAR_STRING), VV_RO},
298 {VV_NAME("fname_in", VAR_STRING), VV_RO},
299 {VV_NAME("fname_out", VAR_STRING), VV_RO},
300 {VV_NAME("fname_new", VAR_STRING), VV_RO},
301 {VV_NAME("fname_diff", VAR_STRING), VV_RO},
302 {VV_NAME("cmdarg", VAR_STRING), VV_RO},
303 {VV_NAME("foldstart", VAR_NUMBER), VV_RO_SBX},
304 {VV_NAME("foldend", VAR_NUMBER), VV_RO_SBX},
305 {VV_NAME("folddashes", VAR_STRING), VV_RO_SBX},
306 {VV_NAME("foldlevel", VAR_NUMBER), VV_RO_SBX},
307 {VV_NAME("progname", VAR_STRING), VV_RO},
308 {VV_NAME("servername", VAR_STRING), VV_RO},
309 {VV_NAME("dying", VAR_NUMBER), VV_RO},
310 {VV_NAME("exception", VAR_STRING), VV_RO},
311 {VV_NAME("throwpoint", VAR_STRING), VV_RO},
312 {VV_NAME("register", VAR_STRING), VV_RO},
313 {VV_NAME("cmdbang", VAR_NUMBER), VV_RO},
314 {VV_NAME("insertmode", VAR_STRING), VV_RO},
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +0000315 {VV_NAME("val", VAR_UNKNOWN), VV_RO},
316 {VV_NAME("key", VAR_UNKNOWN), VV_RO},
Bram Moolenaar05159a02005-02-26 23:04:13 +0000317 {VV_NAME("profiling", VAR_NUMBER), VV_RO},
Bram Moolenaar19a09a12005-03-04 23:39:37 +0000318 {VV_NAME("fcs_reason", VAR_STRING), VV_RO},
319 {VV_NAME("fcs_choice", VAR_STRING), 0},
Bram Moolenaare2ac10d2005-03-07 23:26:06 +0000320 {VV_NAME("beval_bufnr", VAR_NUMBER), VV_RO},
321 {VV_NAME("beval_winnr", VAR_NUMBER), VV_RO},
322 {VV_NAME("beval_lnum", VAR_NUMBER), VV_RO},
323 {VV_NAME("beval_col", VAR_NUMBER), VV_RO},
324 {VV_NAME("beval_text", VAR_STRING), VV_RO},
Bram Moolenaar33570922005-01-25 22:26:29 +0000325};
326
327/* shorthand */
328#define vv_type vv_di.di_tv.v_type
329#define vv_nr vv_di.di_tv.vval.v_number
330#define vv_str vv_di.di_tv.vval.v_string
331#define vv_tv vv_di.di_tv
332
333/*
334 * The v: variables are stored in dictionary "vimvardict".
335 * "vimvars_var" is the variable that is used for the "l:" scope.
336 */
337static dict_T vimvardict;
338static dictitem_T vimvars_var;
339#define vimvarht vimvardict.dv_hashtab
340
341static int eval0 __ARGS((char_u *arg, typval_T *rettv, char_u **nextcmd, int evaluate));
342static int eval1 __ARGS((char_u **arg, typval_T *rettv, int evaluate));
343static int eval2 __ARGS((char_u **arg, typval_T *rettv, int evaluate));
344static int eval3 __ARGS((char_u **arg, typval_T *rettv, int evaluate));
345static int eval4 __ARGS((char_u **arg, typval_T *rettv, int evaluate));
346static int eval5 __ARGS((char_u **arg, typval_T *rettv, int evaluate));
347static int eval6 __ARGS((char_u **arg, typval_T *rettv, int evaluate));
348static int eval7 __ARGS((char_u **arg, typval_T *rettv, int evaluate));
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +0000349static int eval_index __ARGS((char_u **arg, typval_T *rettv, int evaluate, int verbose));
Bram Moolenaar33570922005-01-25 22:26:29 +0000350static int get_option_tv __ARGS((char_u **arg, typval_T *rettv, int evaluate));
351static int get_string_tv __ARGS((char_u **arg, typval_T *rettv, int evaluate));
352static int get_lit_string_tv __ARGS((char_u **arg, typval_T *rettv, int evaluate));
353static int get_list_tv __ARGS((char_u **arg, typval_T *rettv, int evaluate));
354static list_T *list_alloc __ARGS((void));
355static void list_unref __ARGS((list_T *l));
356static void list_free __ARGS((list_T *l));
357static listitem_T *listitem_alloc __ARGS((void));
358static void listitem_free __ARGS((listitem_T *item));
359static void listitem_remove __ARGS((list_T *l, listitem_T *item));
360static long list_len __ARGS((list_T *l));
361static int list_equal __ARGS((list_T *l1, list_T *l2, int ic));
362static int dict_equal __ARGS((dict_T *d1, dict_T *d2, int ic));
363static int tv_equal __ARGS((typval_T *tv1, typval_T *tv2, int ic));
364static int string_isa_number __ARGS((char_u *s));
365static listitem_T *list_find __ARGS((list_T *l, long n));
366static long list_idx_of_item __ARGS((list_T *l, listitem_T *item));
Bram Moolenaar33570922005-01-25 22:26:29 +0000367static void list_append __ARGS((list_T *l, listitem_T *item));
368static int list_append_tv __ARGS((list_T *l, typval_T *tv));
369static int list_insert_tv __ARGS((list_T *l, typval_T *tv, listitem_T *item));
370static int list_extend __ARGS((list_T *l1, list_T *l2, listitem_T *bef));
371static int list_concat __ARGS((list_T *l1, list_T *l2, typval_T *tv));
Bram Moolenaar81bf7082005-02-12 14:31:42 +0000372static list_T *list_copy __ARGS((list_T *orig, int deep, int copyID));
Bram Moolenaar33570922005-01-25 22:26:29 +0000373static void list_remove __ARGS((list_T *l, listitem_T *item, listitem_T *item2));
374static char_u *list2string __ARGS((typval_T *tv));
Bram Moolenaar81bf7082005-02-12 14:31:42 +0000375static int list_join __ARGS((garray_T *gap, list_T *l, char_u *sep, int echo));
Bram Moolenaar33570922005-01-25 22:26:29 +0000376
Bram Moolenaar33570922005-01-25 22:26:29 +0000377static void dict_unref __ARGS((dict_T *d));
378static void dict_free __ARGS((dict_T *d));
379static dictitem_T *dictitem_alloc __ARGS((char_u *key));
380static dictitem_T *dictitem_copy __ARGS((dictitem_T *org));
381static void dictitem_remove __ARGS((dict_T *dict, dictitem_T *item));
382static void dictitem_free __ARGS((dictitem_T *item));
Bram Moolenaar81bf7082005-02-12 14:31:42 +0000383static dict_T *dict_copy __ARGS((dict_T *orig, int deep, int copyID));
Bram Moolenaar33570922005-01-25 22:26:29 +0000384static int dict_add __ARGS((dict_T *d, dictitem_T *item));
385static long dict_len __ARGS((dict_T *d));
386static dictitem_T *dict_find __ARGS((dict_T *d, char_u *key, int len));
387static char_u *dict2string __ARGS((typval_T *tv));
388static int get_dict_tv __ARGS((char_u **arg, typval_T *rettv, int evaluate));
389
390static char_u *echo_string __ARGS((typval_T *tv, char_u **tofree, char_u *numbuf));
391static char_u *tv2string __ARGS((typval_T *tv, char_u **tofree, char_u *numbuf));
392static char_u *string_quote __ARGS((char_u *str, int function));
393static int get_env_tv __ARGS((char_u **arg, typval_T *rettv, int evaluate));
394static int find_internal_func __ARGS((char_u *name));
395static char_u *deref_func_name __ARGS((char_u *name, int *lenp));
396static 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));
397static 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 +0000398static void emsg_funcname __ARGS((char *msg, char_u *name));
Bram Moolenaar33570922005-01-25 22:26:29 +0000399
400static void f_add __ARGS((typval_T *argvars, typval_T *rettv));
401static void f_append __ARGS((typval_T *argvars, typval_T *rettv));
402static void f_argc __ARGS((typval_T *argvars, typval_T *rettv));
403static void f_argidx __ARGS((typval_T *argvars, typval_T *rettv));
404static void f_argv __ARGS((typval_T *argvars, typval_T *rettv));
405static void f_browse __ARGS((typval_T *argvars, typval_T *rettv));
406static void f_browsedir __ARGS((typval_T *argvars, typval_T *rettv));
407static void f_bufexists __ARGS((typval_T *argvars, typval_T *rettv));
408static void f_buflisted __ARGS((typval_T *argvars, typval_T *rettv));
409static void f_bufloaded __ARGS((typval_T *argvars, typval_T *rettv));
410static void f_bufname __ARGS((typval_T *argvars, typval_T *rettv));
411static void f_bufnr __ARGS((typval_T *argvars, typval_T *rettv));
412static void f_bufwinnr __ARGS((typval_T *argvars, typval_T *rettv));
413static void f_byte2line __ARGS((typval_T *argvars, typval_T *rettv));
414static void f_byteidx __ARGS((typval_T *argvars, typval_T *rettv));
415static void f_call __ARGS((typval_T *argvars, typval_T *rettv));
416static void f_char2nr __ARGS((typval_T *argvars, typval_T *rettv));
417static void f_cindent __ARGS((typval_T *argvars, typval_T *rettv));
418static void f_col __ARGS((typval_T *argvars, typval_T *rettv));
419static void f_confirm __ARGS((typval_T *argvars, typval_T *rettv));
420static void f_copy __ARGS((typval_T *argvars, typval_T *rettv));
421static void f_count __ARGS((typval_T *argvars, typval_T *rettv));
422static void f_cscope_connection __ARGS((typval_T *argvars, typval_T *rettv));
423static void f_cursor __ARGS((typval_T *argsvars, typval_T *rettv));
424static void f_deepcopy __ARGS((typval_T *argvars, typval_T *rettv));
425static void f_delete __ARGS((typval_T *argvars, typval_T *rettv));
426static void f_did_filetype __ARGS((typval_T *argvars, typval_T *rettv));
427static void f_diff_filler __ARGS((typval_T *argvars, typval_T *rettv));
428static void f_diff_hlID __ARGS((typval_T *argvars, typval_T *rettv));
429static void f_empty __ARGS((typval_T *argvars, typval_T *rettv));
430static void f_escape __ARGS((typval_T *argvars, typval_T *rettv));
431static void f_eval __ARGS((typval_T *argvars, typval_T *rettv));
432static void f_eventhandler __ARGS((typval_T *argvars, typval_T *rettv));
433static void f_executable __ARGS((typval_T *argvars, typval_T *rettv));
434static void f_exists __ARGS((typval_T *argvars, typval_T *rettv));
435static void f_expand __ARGS((typval_T *argvars, typval_T *rettv));
436static void f_extend __ARGS((typval_T *argvars, typval_T *rettv));
437static void f_filereadable __ARGS((typval_T *argvars, typval_T *rettv));
438static void f_filewritable __ARGS((typval_T *argvars, typval_T *rettv));
439static void f_filter __ARGS((typval_T *argvars, typval_T *rettv));
440static void f_finddir __ARGS((typval_T *argvars, typval_T *rettv));
441static void f_findfile __ARGS((typval_T *argvars, typval_T *rettv));
442static void f_fnamemodify __ARGS((typval_T *argvars, typval_T *rettv));
443static void f_foldclosed __ARGS((typval_T *argvars, typval_T *rettv));
444static void f_foldclosedend __ARGS((typval_T *argvars, typval_T *rettv));
445static void f_foldlevel __ARGS((typval_T *argvars, typval_T *rettv));
446static void f_foldtext __ARGS((typval_T *argvars, typval_T *rettv));
447static void f_foldtextresult __ARGS((typval_T *argvars, typval_T *rettv));
448static void f_foreground __ARGS((typval_T *argvars, typval_T *rettv));
449static void f_function __ARGS((typval_T *argvars, typval_T *rettv));
450static void f_get __ARGS((typval_T *argvars, typval_T *rettv));
451static void f_getbufvar __ARGS((typval_T *argvars, typval_T *rettv));
452static void f_getchar __ARGS((typval_T *argvars, typval_T *rettv));
453static void f_getcharmod __ARGS((typval_T *argvars, typval_T *rettv));
454static void f_getcmdline __ARGS((typval_T *argvars, typval_T *rettv));
455static void f_getcmdpos __ARGS((typval_T *argvars, typval_T *rettv));
456static void f_getcwd __ARGS((typval_T *argvars, typval_T *rettv));
457static void f_getfontname __ARGS((typval_T *argvars, typval_T *rettv));
458static void f_getfperm __ARGS((typval_T *argvars, typval_T *rettv));
459static void f_getfsize __ARGS((typval_T *argvars, typval_T *rettv));
460static void f_getftime __ARGS((typval_T *argvars, typval_T *rettv));
461static void f_getftype __ARGS((typval_T *argvars, typval_T *rettv));
462static void f_getline __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar2641f772005-03-25 21:58:17 +0000463static void f_getqflist __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar33570922005-01-25 22:26:29 +0000464static void f_getreg __ARGS((typval_T *argvars, typval_T *rettv));
465static void f_getregtype __ARGS((typval_T *argvars, typval_T *rettv));
466static void f_getwinposx __ARGS((typval_T *argvars, typval_T *rettv));
467static void f_getwinposy __ARGS((typval_T *argvars, typval_T *rettv));
468static void f_getwinvar __ARGS((typval_T *argvars, typval_T *rettv));
469static void f_glob __ARGS((typval_T *argvars, typval_T *rettv));
470static void f_globpath __ARGS((typval_T *argvars, typval_T *rettv));
471static void f_has __ARGS((typval_T *argvars, typval_T *rettv));
472static void f_has_key __ARGS((typval_T *argvars, typval_T *rettv));
473static void f_hasmapto __ARGS((typval_T *argvars, typval_T *rettv));
474static void f_histadd __ARGS((typval_T *argvars, typval_T *rettv));
475static void f_histdel __ARGS((typval_T *argvars, typval_T *rettv));
476static void f_histget __ARGS((typval_T *argvars, typval_T *rettv));
477static void f_histnr __ARGS((typval_T *argvars, typval_T *rettv));
478static void f_hlID __ARGS((typval_T *argvars, typval_T *rettv));
479static void f_hlexists __ARGS((typval_T *argvars, typval_T *rettv));
480static void f_hostname __ARGS((typval_T *argvars, typval_T *rettv));
481static void f_iconv __ARGS((typval_T *argvars, typval_T *rettv));
482static void f_indent __ARGS((typval_T *argvars, typval_T *rettv));
483static void f_index __ARGS((typval_T *argvars, typval_T *rettv));
484static void f_input __ARGS((typval_T *argvars, typval_T *rettv));
485static void f_inputdialog __ARGS((typval_T *argvars, typval_T *rettv));
486static void f_inputrestore __ARGS((typval_T *argvars, typval_T *rettv));
487static void f_inputsave __ARGS((typval_T *argvars, typval_T *rettv));
488static void f_inputsecret __ARGS((typval_T *argvars, typval_T *rettv));
489static void f_insert __ARGS((typval_T *argvars, typval_T *rettv));
490static void f_isdirectory __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar2e6aff32005-01-31 19:25:36 +0000491static void f_islocked __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar33570922005-01-25 22:26:29 +0000492static void f_items __ARGS((typval_T *argvars, typval_T *rettv));
493static void f_join __ARGS((typval_T *argvars, typval_T *rettv));
494static void f_keys __ARGS((typval_T *argvars, typval_T *rettv));
495static void f_last_buffer_nr __ARGS((typval_T *argvars, typval_T *rettv));
496static void f_len __ARGS((typval_T *argvars, typval_T *rettv));
497static void f_libcall __ARGS((typval_T *argvars, typval_T *rettv));
498static void f_libcallnr __ARGS((typval_T *argvars, typval_T *rettv));
499static void f_line __ARGS((typval_T *argvars, typval_T *rettv));
500static void f_line2byte __ARGS((typval_T *argvars, typval_T *rettv));
501static void f_lispindent __ARGS((typval_T *argvars, typval_T *rettv));
502static void f_localtime __ARGS((typval_T *argvars, typval_T *rettv));
503static void f_map __ARGS((typval_T *argvars, typval_T *rettv));
504static void f_maparg __ARGS((typval_T *argvars, typval_T *rettv));
505static void f_mapcheck __ARGS((typval_T *argvars, typval_T *rettv));
506static void f_match __ARGS((typval_T *argvars, typval_T *rettv));
507static void f_matchend __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +0000508static void f_matchlist __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar33570922005-01-25 22:26:29 +0000509static void f_matchstr __ARGS((typval_T *argvars, typval_T *rettv));
510static void f_max __ARGS((typval_T *argvars, typval_T *rettv));
511static void f_min __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000512#ifdef vim_mkdir
513static void f_mkdir __ARGS((typval_T *argvars, typval_T *rettv));
514#endif
Bram Moolenaar33570922005-01-25 22:26:29 +0000515static void f_mode __ARGS((typval_T *argvars, typval_T *rettv));
516static void f_nextnonblank __ARGS((typval_T *argvars, typval_T *rettv));
517static void f_nr2char __ARGS((typval_T *argvars, typval_T *rettv));
518static void f_prevnonblank __ARGS((typval_T *argvars, typval_T *rettv));
519static void f_range __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +0000520static void f_readfile __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar33570922005-01-25 22:26:29 +0000521static void f_remote_expr __ARGS((typval_T *argvars, typval_T *rettv));
522static void f_remote_foreground __ARGS((typval_T *argvars, typval_T *rettv));
523static void f_remote_peek __ARGS((typval_T *argvars, typval_T *rettv));
524static void f_remote_read __ARGS((typval_T *argvars, typval_T *rettv));
525static void f_remote_send __ARGS((typval_T *argvars, typval_T *rettv));
526static void f_remove __ARGS((typval_T *argvars, typval_T *rettv));
527static void f_rename __ARGS((typval_T *argvars, typval_T *rettv));
528static void f_repeat __ARGS((typval_T *argvars, typval_T *rettv));
529static void f_resolve __ARGS((typval_T *argvars, typval_T *rettv));
530static void f_reverse __ARGS((typval_T *argvars, typval_T *rettv));
531static void f_search __ARGS((typval_T *argvars, typval_T *rettv));
532static void f_searchpair __ARGS((typval_T *argvars, typval_T *rettv));
533static void f_server2client __ARGS((typval_T *argvars, typval_T *rettv));
534static void f_serverlist __ARGS((typval_T *argvars, typval_T *rettv));
535static void f_setbufvar __ARGS((typval_T *argvars, typval_T *rettv));
536static void f_setcmdpos __ARGS((typval_T *argvars, typval_T *rettv));
537static void f_setline __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar2641f772005-03-25 21:58:17 +0000538static void f_setqflist __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar33570922005-01-25 22:26:29 +0000539static void f_setreg __ARGS((typval_T *argvars, typval_T *rettv));
540static void f_setwinvar __ARGS((typval_T *argvars, typval_T *rettv));
541static void f_simplify __ARGS((typval_T *argvars, typval_T *rettv));
542static void f_sort __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaard857f0e2005-06-21 22:37:39 +0000543static void f_spellbadword __ARGS((typval_T *argvars, typval_T *rettv));
544static void f_spellsuggest __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar33570922005-01-25 22:26:29 +0000545static void f_split __ARGS((typval_T *argvars, typval_T *rettv));
546#ifdef HAVE_STRFTIME
547static void f_strftime __ARGS((typval_T *argvars, typval_T *rettv));
548#endif
549static void f_stridx __ARGS((typval_T *argvars, typval_T *rettv));
550static void f_string __ARGS((typval_T *argvars, typval_T *rettv));
551static void f_strlen __ARGS((typval_T *argvars, typval_T *rettv));
552static void f_strpart __ARGS((typval_T *argvars, typval_T *rettv));
553static void f_strridx __ARGS((typval_T *argvars, typval_T *rettv));
554static void f_strtrans __ARGS((typval_T *argvars, typval_T *rettv));
555static void f_submatch __ARGS((typval_T *argvars, typval_T *rettv));
556static void f_substitute __ARGS((typval_T *argvars, typval_T *rettv));
557static void f_synID __ARGS((typval_T *argvars, typval_T *rettv));
558static void f_synIDattr __ARGS((typval_T *argvars, typval_T *rettv));
559static void f_synIDtrans __ARGS((typval_T *argvars, typval_T *rettv));
560static void f_system __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar19a09a12005-03-04 23:39:37 +0000561static void f_taglist __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar33570922005-01-25 22:26:29 +0000562static void f_tempname __ARGS((typval_T *argvars, typval_T *rettv));
563static void f_tolower __ARGS((typval_T *argvars, typval_T *rettv));
564static void f_toupper __ARGS((typval_T *argvars, typval_T *rettv));
565static void f_tr __ARGS((typval_T *argvars, typval_T *rettv));
566static void f_type __ARGS((typval_T *argvars, typval_T *rettv));
567static void f_values __ARGS((typval_T *argvars, typval_T *rettv));
568static void f_virtcol __ARGS((typval_T *argvars, typval_T *rettv));
569static void f_visualmode __ARGS((typval_T *argvars, typval_T *rettv));
570static void f_winbufnr __ARGS((typval_T *argvars, typval_T *rettv));
571static void f_wincol __ARGS((typval_T *argvars, typval_T *rettv));
572static void f_winheight __ARGS((typval_T *argvars, typval_T *rettv));
573static void f_winline __ARGS((typval_T *argvars, typval_T *rettv));
574static void f_winnr __ARGS((typval_T *argvars, typval_T *rettv));
575static void f_winrestcmd __ARGS((typval_T *argvars, typval_T *rettv));
576static void f_winwidth __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +0000577static void f_writefile __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar33570922005-01-25 22:26:29 +0000578
579static win_T *find_win_by_nr __ARGS((typval_T *vp));
580static pos_T *var2fpos __ARGS((typval_T *varp, int lnum));
581static int get_env_len __ARGS((char_u **arg));
582static int get_id_len __ARGS((char_u **arg));
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +0000583static int get_name_len __ARGS((char_u **arg, char_u **alias, int evaluate, int verbose));
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +0000584static char_u *find_name_end __ARGS((char_u *arg, char_u **expr_start, char_u **expr_end, int flags));
585#define FNE_INCL_BR 1 /* find_name_end(): include [] in name */
586#define FNE_CHECK_START 2 /* find_name_end(): check name starts with
587 valid character */
Bram Moolenaar33570922005-01-25 22:26:29 +0000588static int eval_isnamec __ARGS((int c));
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +0000589static int eval_isnamec1 __ARGS((int c));
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +0000590static int get_var_tv __ARGS((char_u *name, int len, typval_T *rettv, int verbose));
591static int handle_subscript __ARGS((char_u **arg, typval_T *rettv, int evaluate, int verbose));
Bram Moolenaar33570922005-01-25 22:26:29 +0000592static typval_T *alloc_tv __ARGS((void));
593static typval_T *alloc_string_tv __ARGS((char_u *string));
594static void free_tv __ARGS((typval_T *varp));
595static void clear_tv __ARGS((typval_T *varp));
596static void init_tv __ARGS((typval_T *varp));
597static long get_tv_number __ARGS((typval_T *varp));
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +0000598static long get_tv_number_chk __ARGS((typval_T *varp, int *denote));
Bram Moolenaar33570922005-01-25 22:26:29 +0000599static linenr_T get_tv_lnum __ARGS((typval_T *argvars));
600static char_u *get_tv_string __ARGS((typval_T *varp));
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +0000601static char_u *get_tv_string_chk __ARGS((typval_T *varp));
Bram Moolenaar33570922005-01-25 22:26:29 +0000602static char_u *get_tv_string_buf __ARGS((typval_T *varp, char_u *buf));
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +0000603static char_u *get_tv_string_buf_chk __ARGS((typval_T *varp, char_u *buf));
Bram Moolenaar33570922005-01-25 22:26:29 +0000604static dictitem_T *find_var __ARGS((char_u *name, hashtab_T **htp));
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000605static dictitem_T *find_var_in_ht __ARGS((hashtab_T *ht, char_u *varname, int writing));
Bram Moolenaar33570922005-01-25 22:26:29 +0000606static hashtab_T *find_var_ht __ARGS((char_u *name, char_u **varname));
607static void vars_clear_ext __ARGS((hashtab_T *ht, int free_val));
608static void delete_var __ARGS((hashtab_T *ht, hashitem_T *hi));
609static void list_one_var __ARGS((dictitem_T *v, char_u *prefix));
610static void list_one_var_a __ARGS((char_u *prefix, char_u *name, int type, char_u *string));
611static void set_var __ARGS((char_u *name, typval_T *varp, int copy));
612static int var_check_ro __ARGS((int flags, char_u *name));
Bram Moolenaar2e6aff32005-01-31 19:25:36 +0000613static int tv_check_lock __ARGS((int lock, char_u *name));
Bram Moolenaar33570922005-01-25 22:26:29 +0000614static void copy_tv __ARGS((typval_T *from, typval_T *to));
Bram Moolenaar81bf7082005-02-12 14:31:42 +0000615static int item_copy __ARGS((typval_T *from, typval_T *to, int deep, int copyID));
Bram Moolenaar33570922005-01-25 22:26:29 +0000616static char_u *find_option_end __ARGS((char_u **arg, int *opt_flags));
617static char_u *trans_function_name __ARGS((char_u **pp, int skip, int flags, funcdict_T *fd));
618static int eval_fname_script __ARGS((char_u *p));
619static int eval_fname_sid __ARGS((char_u *p));
620static void list_func_head __ARGS((ufunc_T *fp, int indent));
621static void cat_func_name __ARGS((char_u *buf, ufunc_T *fp));
622static ufunc_T *find_func __ARGS((char_u *name));
623static int function_exists __ARGS((char_u *name));
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +0000624static int builtin_function __ARGS((char_u *name));
Bram Moolenaar05159a02005-02-26 23:04:13 +0000625#ifdef FEAT_PROFILE
626static void func_do_profile __ARGS((ufunc_T *fp));
Bram Moolenaar73830342005-02-28 22:48:19 +0000627static void prof_sort_list __ARGS((FILE *fd, ufunc_T **sorttab, int st_len, char *title, int prefer_self));
628static void prof_func_line __ARGS((FILE *fd, int count, proftime_T *total, proftime_T *self, int prefer_self));
629static int
630# ifdef __BORLANDC__
631 _RTLENTRYF
632# endif
633 prof_total_cmp __ARGS((const void *s1, const void *s2));
634static int
635# ifdef __BORLANDC__
636 _RTLENTRYF
637# endif
638 prof_self_cmp __ARGS((const void *s1, const void *s2));
Bram Moolenaar05159a02005-02-26 23:04:13 +0000639#endif
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000640static int script_autoload __ARGS((char_u *name));
641static char_u *autoload_name __ARGS((char_u *name));
Bram Moolenaar33570922005-01-25 22:26:29 +0000642static void func_free __ARGS((ufunc_T *fp));
643static void func_unref __ARGS((char_u *name));
644static void func_ref __ARGS((char_u *name));
645static 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));
646static void add_nr_var __ARGS((dict_T *dp, dictitem_T *v, char *name, varnumber_T nr));
647
648static char_u * make_expanded_name __ARGS((char_u *in_start, char_u *expr_start, char_u *expr_end, char_u *in_end));
649
650static int ex_let_vars __ARGS((char_u *arg, typval_T *tv, int copy, int semicolon, int var_count, char_u *nextchars));
651static char_u *skip_var_list __ARGS((char_u *arg, int *var_count, int *semicolon));
652static char_u *skip_var_one __ARGS((char_u *arg));
653static void list_hashtable_vars __ARGS((hashtab_T *ht, char_u *prefix, int empty));
654static void list_glob_vars __ARGS((void));
655static void list_buf_vars __ARGS((void));
656static void list_win_vars __ARGS((void));
657static void list_vim_vars __ARGS((void));
658static char_u *list_arg_vars __ARGS((exarg_T *eap, char_u *arg));
659static char_u *ex_let_one __ARGS((char_u *arg, typval_T *tv, int copy, char_u *endchars, char_u *op));
660static int check_changedtick __ARGS((char_u *arg));
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +0000661static 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 +0000662static void clear_lval __ARGS((lval_T *lp));
663static void set_var_lval __ARGS((lval_T *lp, char_u *endp, typval_T *rettv, int copy, char_u *op));
664static int tv_op __ARGS((typval_T *tv1, typval_T *tv2, char_u *op));
665static void list_add_watch __ARGS((list_T *l, listwatch_T *lw));
666static void list_rem_watch __ARGS((list_T *l, listwatch_T *lwrem));
667static void list_fix_watch __ARGS((list_T *l, listitem_T *item));
Bram Moolenaar2e6aff32005-01-31 19:25:36 +0000668static void ex_unletlock __ARGS((exarg_T *eap, char_u *argstart, int deep));
Bram Moolenaar33570922005-01-25 22:26:29 +0000669static int do_unlet_var __ARGS((lval_T *lp, char_u *name_end, int forceit));
Bram Moolenaar2e6aff32005-01-31 19:25:36 +0000670static int do_lock_var __ARGS((lval_T *lp, char_u *name_end, int deep, int lock));
671static void item_lock __ARGS((typval_T *tv, int deep, int lock));
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000672static int tv_islocked __ARGS((typval_T *tv));
Bram Moolenaar33570922005-01-25 22:26:29 +0000673
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +0000674/* Character used as separated in autoload function/variable names. */
675#define AUTOLOAD_CHAR '#'
676
Bram Moolenaar33570922005-01-25 22:26:29 +0000677/*
678 * Initialize the global and v: variables.
Bram Moolenaara7043832005-01-21 11:56:39 +0000679 */
680 void
681eval_init()
682{
Bram Moolenaar33570922005-01-25 22:26:29 +0000683 int i;
684 struct vimvar *p;
685
686 init_var_dict(&globvardict, &globvars_var);
687 init_var_dict(&vimvardict, &vimvars_var);
Bram Moolenaar532c7802005-01-27 14:44:31 +0000688 hash_init(&compat_hashtab);
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000689 hash_init(&func_hashtab);
Bram Moolenaar33570922005-01-25 22:26:29 +0000690
691 for (i = 0; i < VV_LEN; ++i)
692 {
693 p = &vimvars[i];
694 STRCPY(p->vv_di.di_key, p->vv_name);
695 if (p->vv_flags & VV_RO)
696 p->vv_di.di_flags = DI_FLAGS_RO | DI_FLAGS_FIX;
697 else if (p->vv_flags & VV_RO_SBX)
698 p->vv_di.di_flags = DI_FLAGS_RO_SBX | DI_FLAGS_FIX;
699 else
700 p->vv_di.di_flags = DI_FLAGS_FIX;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +0000701
702 /* add to v: scope dict, unless the value is not always available */
703 if (p->vv_type != VAR_UNKNOWN)
704 hash_add(&vimvarht, p->vv_di.di_key);
Bram Moolenaar33570922005-01-25 22:26:29 +0000705 if (p->vv_flags & VV_COMPAT)
Bram Moolenaar532c7802005-01-27 14:44:31 +0000706 /* add to compat scope dict */
707 hash_add(&compat_hashtab, p->vv_di.di_key);
Bram Moolenaar33570922005-01-25 22:26:29 +0000708 }
Bram Moolenaara7043832005-01-21 11:56:39 +0000709}
710
Bram Moolenaar9ef486d2005-01-17 22:23:00 +0000711/*
Bram Moolenaar071d4272004-06-13 20:20:40 +0000712 * Return the name of the executed function.
713 */
714 char_u *
715func_name(cookie)
716 void *cookie;
717{
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000718 return ((funccall_T *)cookie)->func->uf_name;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000719}
720
721/*
722 * Return the address holding the next breakpoint line for a funccall cookie.
723 */
724 linenr_T *
725func_breakpoint(cookie)
726 void *cookie;
727{
Bram Moolenaar33570922005-01-25 22:26:29 +0000728 return &((funccall_T *)cookie)->breakpoint;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000729}
730
731/*
732 * Return the address holding the debug tick for a funccall cookie.
733 */
734 int *
735func_dbg_tick(cookie)
736 void *cookie;
737{
Bram Moolenaar33570922005-01-25 22:26:29 +0000738 return &((funccall_T *)cookie)->dbg_tick;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000739}
740
741/*
742 * Return the nesting level for a funccall cookie.
743 */
744 int
745func_level(cookie)
746 void *cookie;
747{
Bram Moolenaar33570922005-01-25 22:26:29 +0000748 return ((funccall_T *)cookie)->level;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000749}
750
751/* pointer to funccal for currently active function */
Bram Moolenaar33570922005-01-25 22:26:29 +0000752funccall_T *current_funccal = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000753
754/*
755 * Return TRUE when a function was ended by a ":return" command.
756 */
757 int
758current_func_returned()
759{
760 return current_funccal->returned;
761}
762
763
764/*
Bram Moolenaar071d4272004-06-13 20:20:40 +0000765 * Set an internal variable to a string value. Creates the variable if it does
766 * not already exist.
767 */
768 void
769set_internal_string_var(name, value)
770 char_u *name;
771 char_u *value;
772{
Bram Moolenaar49cd9572005-01-03 21:06:01 +0000773 char_u *val;
Bram Moolenaar33570922005-01-25 22:26:29 +0000774 typval_T *tvp;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000775
776 val = vim_strsave(value);
777 if (val != NULL)
778 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000779 tvp = alloc_string_tv(val);
Bram Moolenaar49cd9572005-01-03 21:06:01 +0000780 if (tvp != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000781 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +0000782 set_var(name, tvp, FALSE);
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000783 free_tv(tvp);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000784 }
785 }
786}
787
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000788static lval_T *redir_lval = NULL;
789static char_u *redir_endp = NULL;
790static char_u *redir_varname = NULL;
791
792/*
793 * Start recording command output to a variable
794 * Returns OK if successfully completed the setup. FAIL otherwise.
795 */
796 int
797var_redir_start(name, append)
798 char_u *name;
799 int append; /* append to an existing variable */
800{
801 int save_emsg;
802 int err;
803 typval_T tv;
804
805 /* Make sure a valid variable name is specified */
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +0000806 if (!eval_isnamec1(*name))
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000807 {
808 EMSG(_(e_invarg));
809 return FAIL;
810 }
811
812 redir_varname = vim_strsave(name);
813 if (redir_varname == NULL)
814 return FAIL;
815
816 redir_lval = (lval_T *)alloc_clear((unsigned)sizeof(lval_T));
817 if (redir_lval == NULL)
818 {
819 var_redir_stop();
820 return FAIL;
821 }
822
823 /* Parse the variable name (can be a dict or list entry). */
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +0000824 redir_endp = get_lval(redir_varname, NULL, redir_lval, FALSE, FALSE, FALSE,
825 FNE_CHECK_START);
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000826 if (redir_endp == NULL || redir_lval->ll_name == NULL || *redir_endp != NUL)
827 {
828 if (redir_endp != NULL && *redir_endp != NUL)
829 /* Trailing characters are present after the variable name */
830 EMSG(_(e_trailing));
831 else
832 EMSG(_(e_invarg));
833 var_redir_stop();
834 return FAIL;
835 }
836
837 /* check if we can write to the variable: set it to or append an empty
838 * string */
839 save_emsg = did_emsg;
840 did_emsg = FALSE;
841 tv.v_type = VAR_STRING;
842 tv.vval.v_string = (char_u *)"";
843 if (append)
844 set_var_lval(redir_lval, redir_endp, &tv, TRUE, (char_u *)".");
845 else
846 set_var_lval(redir_lval, redir_endp, &tv, TRUE, (char_u *)"=");
847 err = did_emsg;
848 did_emsg += save_emsg;
849 if (err)
850 {
851 var_redir_stop();
852 return FAIL;
853 }
854 if (redir_lval->ll_newkey != NULL)
855 {
856 /* Dictionary item was created, don't do it again. */
857 vim_free(redir_lval->ll_newkey);
858 redir_lval->ll_newkey = NULL;
859 }
860
861 return OK;
862}
863
864/*
865 * Append "value[len]" to the variable set by var_redir_start().
866 */
867 void
868var_redir_str(value, len)
869 char_u *value;
870 int len;
871{
872 char_u *val;
873 typval_T tv;
874 int save_emsg;
875 int err;
876
877 if (redir_lval == NULL)
878 return;
879
880 if (len == -1)
881 /* Append the entire string */
882 val = vim_strsave(value);
883 else
884 /* Append only the specified number of characters */
885 val = vim_strnsave(value, len);
886 if (val == NULL)
887 return;
888
889 tv.v_type = VAR_STRING;
890 tv.vval.v_string = val;
891
892 save_emsg = did_emsg;
893 did_emsg = FALSE;
894 set_var_lval(redir_lval, redir_endp, &tv, FALSE, (char_u *)".");
895 err = did_emsg;
896 did_emsg += save_emsg;
897 if (err)
898 var_redir_stop();
899
900 vim_free(tv.vval.v_string);
901}
902
903/*
904 * Stop redirecting command output to a variable.
905 */
906 void
907var_redir_stop()
908{
909 if (redir_lval != NULL)
910 {
911 clear_lval(redir_lval);
912 vim_free(redir_lval);
913 redir_lval = NULL;
914 }
915 vim_free(redir_varname);
916 redir_varname = NULL;
917}
918
Bram Moolenaar071d4272004-06-13 20:20:40 +0000919# if defined(FEAT_MBYTE) || defined(PROTO)
920 int
921eval_charconvert(enc_from, enc_to, fname_from, fname_to)
922 char_u *enc_from;
923 char_u *enc_to;
924 char_u *fname_from;
925 char_u *fname_to;
926{
927 int err = FALSE;
928
929 set_vim_var_string(VV_CC_FROM, enc_from, -1);
930 set_vim_var_string(VV_CC_TO, enc_to, -1);
931 set_vim_var_string(VV_FNAME_IN, fname_from, -1);
932 set_vim_var_string(VV_FNAME_OUT, fname_to, -1);
933 if (eval_to_bool(p_ccv, &err, NULL, FALSE))
934 err = TRUE;
935 set_vim_var_string(VV_CC_FROM, NULL, -1);
936 set_vim_var_string(VV_CC_TO, NULL, -1);
937 set_vim_var_string(VV_FNAME_IN, NULL, -1);
938 set_vim_var_string(VV_FNAME_OUT, NULL, -1);
939
940 if (err)
941 return FAIL;
942 return OK;
943}
944# endif
945
946# if defined(FEAT_POSTSCRIPT) || defined(PROTO)
947 int
948eval_printexpr(fname, args)
949 char_u *fname;
950 char_u *args;
951{
952 int err = FALSE;
953
954 set_vim_var_string(VV_FNAME_IN, fname, -1);
955 set_vim_var_string(VV_CMDARG, args, -1);
956 if (eval_to_bool(p_pexpr, &err, NULL, FALSE))
957 err = TRUE;
958 set_vim_var_string(VV_FNAME_IN, NULL, -1);
959 set_vim_var_string(VV_CMDARG, NULL, -1);
960
961 if (err)
962 {
963 mch_remove(fname);
964 return FAIL;
965 }
966 return OK;
967}
968# endif
969
970# if defined(FEAT_DIFF) || defined(PROTO)
971 void
972eval_diff(origfile, newfile, outfile)
973 char_u *origfile;
974 char_u *newfile;
975 char_u *outfile;
976{
977 int err = FALSE;
978
979 set_vim_var_string(VV_FNAME_IN, origfile, -1);
980 set_vim_var_string(VV_FNAME_NEW, newfile, -1);
981 set_vim_var_string(VV_FNAME_OUT, outfile, -1);
982 (void)eval_to_bool(p_dex, &err, NULL, FALSE);
983 set_vim_var_string(VV_FNAME_IN, NULL, -1);
984 set_vim_var_string(VV_FNAME_NEW, NULL, -1);
985 set_vim_var_string(VV_FNAME_OUT, NULL, -1);
986}
987
988 void
989eval_patch(origfile, difffile, outfile)
990 char_u *origfile;
991 char_u *difffile;
992 char_u *outfile;
993{
994 int err;
995
996 set_vim_var_string(VV_FNAME_IN, origfile, -1);
997 set_vim_var_string(VV_FNAME_DIFF, difffile, -1);
998 set_vim_var_string(VV_FNAME_OUT, outfile, -1);
999 (void)eval_to_bool(p_pex, &err, NULL, FALSE);
1000 set_vim_var_string(VV_FNAME_IN, NULL, -1);
1001 set_vim_var_string(VV_FNAME_DIFF, NULL, -1);
1002 set_vim_var_string(VV_FNAME_OUT, NULL, -1);
1003}
1004# endif
1005
1006/*
1007 * Top level evaluation function, returning a boolean.
1008 * Sets "error" to TRUE if there was an error.
1009 * Return TRUE or FALSE.
1010 */
1011 int
1012eval_to_bool(arg, error, nextcmd, skip)
1013 char_u *arg;
1014 int *error;
1015 char_u **nextcmd;
1016 int skip; /* only parse, don't execute */
1017{
Bram Moolenaar33570922005-01-25 22:26:29 +00001018 typval_T tv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001019 int retval = FALSE;
1020
1021 if (skip)
1022 ++emsg_skip;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001023 if (eval0(arg, &tv, nextcmd, !skip) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001024 *error = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001025 else
1026 {
1027 *error = FALSE;
1028 if (!skip)
1029 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00001030 retval = (get_tv_number_chk(&tv, error) != 0);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001031 clear_tv(&tv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001032 }
1033 }
1034 if (skip)
1035 --emsg_skip;
1036
1037 return retval;
1038}
1039
1040/*
1041 * Top level evaluation function, returning a string. If "skip" is TRUE,
1042 * only parsing to "nextcmd" is done, without reporting errors. Return
1043 * pointer to allocated memory, or NULL for failure or when "skip" is TRUE.
1044 */
1045 char_u *
1046eval_to_string_skip(arg, nextcmd, skip)
1047 char_u *arg;
1048 char_u **nextcmd;
1049 int skip; /* only parse, don't execute */
1050{
Bram Moolenaar33570922005-01-25 22:26:29 +00001051 typval_T tv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001052 char_u *retval;
1053
1054 if (skip)
1055 ++emsg_skip;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001056 if (eval0(arg, &tv, nextcmd, !skip) == FAIL || skip)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001057 retval = NULL;
1058 else
1059 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001060 retval = vim_strsave(get_tv_string(&tv));
1061 clear_tv(&tv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001062 }
1063 if (skip)
1064 --emsg_skip;
1065
1066 return retval;
1067}
1068
1069/*
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001070 * Skip over an expression at "*pp".
1071 * Return FAIL for an error, OK otherwise.
1072 */
1073 int
1074skip_expr(pp)
1075 char_u **pp;
1076{
Bram Moolenaar33570922005-01-25 22:26:29 +00001077 typval_T rettv;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001078
1079 *pp = skipwhite(*pp);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001080 return eval1(pp, &rettv, FALSE);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001081}
1082
1083/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00001084 * Top level evaluation function, returning a string.
1085 * Return pointer to allocated memory, or NULL for failure.
1086 */
1087 char_u *
1088eval_to_string(arg, nextcmd)
1089 char_u *arg;
1090 char_u **nextcmd;
1091{
Bram Moolenaar33570922005-01-25 22:26:29 +00001092 typval_T tv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001093 char_u *retval;
1094
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001095 if (eval0(arg, &tv, nextcmd, TRUE) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001096 retval = NULL;
1097 else
1098 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001099 retval = vim_strsave(get_tv_string(&tv));
1100 clear_tv(&tv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001101 }
1102
1103 return retval;
1104}
1105
1106/*
1107 * Call eval_to_string() with "sandbox" set and not using local variables.
1108 */
1109 char_u *
1110eval_to_string_safe(arg, nextcmd)
1111 char_u *arg;
1112 char_u **nextcmd;
1113{
1114 char_u *retval;
1115 void *save_funccalp;
1116
1117 save_funccalp = save_funccal();
1118 ++sandbox;
1119 retval = eval_to_string(arg, nextcmd);
1120 --sandbox;
1121 restore_funccal(save_funccalp);
1122 return retval;
1123}
1124
Bram Moolenaar071d4272004-06-13 20:20:40 +00001125/*
1126 * Top level evaluation function, returning a number.
1127 * Evaluates "expr" silently.
1128 * Returns -1 for an error.
1129 */
1130 int
1131eval_to_number(expr)
1132 char_u *expr;
1133{
Bram Moolenaar33570922005-01-25 22:26:29 +00001134 typval_T rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001135 int retval;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00001136 char_u *p = skipwhite(expr);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001137
1138 ++emsg_off;
1139
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001140 if (eval1(&p, &rettv, TRUE) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001141 retval = -1;
1142 else
1143 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00001144 retval = get_tv_number_chk(&rettv, NULL);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001145 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001146 }
1147 --emsg_off;
1148
1149 return retval;
1150}
1151
1152#if (defined(FEAT_USR_CMDS) && defined(FEAT_CMDL_COMPL)) || defined(PROTO)
1153/*
1154 * Call some vimL function and return the result as a string
1155 * Uses argv[argc] for the function arguments.
1156 */
1157 char_u *
1158call_vim_function(func, argc, argv, safe)
1159 char_u *func;
1160 int argc;
1161 char_u **argv;
1162 int safe; /* use the sandbox */
1163{
1164 char_u *retval = NULL;
Bram Moolenaar33570922005-01-25 22:26:29 +00001165 typval_T rettv;
1166 typval_T *argvars;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001167 long n;
1168 int len;
1169 int i;
1170 int doesrange;
1171 void *save_funccalp = NULL;
1172
Bram Moolenaar33570922005-01-25 22:26:29 +00001173 argvars = (typval_T *)alloc((unsigned)(argc * sizeof(typval_T)));
Bram Moolenaar071d4272004-06-13 20:20:40 +00001174 if (argvars == NULL)
1175 return NULL;
1176
1177 for (i = 0; i < argc; i++)
1178 {
Bram Moolenaarcfbc5ee2004-07-02 15:38:35 +00001179 /* Pass a NULL or empty argument as an empty string */
1180 if (argv[i] == NULL || *argv[i] == NUL)
1181 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +00001182 argvars[i].v_type = VAR_STRING;
1183 argvars[i].vval.v_string = (char_u *)"";
Bram Moolenaarcfbc5ee2004-07-02 15:38:35 +00001184 continue;
1185 }
1186
Bram Moolenaar071d4272004-06-13 20:20:40 +00001187 /* Recognize a number argument, the others must be strings. */
1188 vim_str2nr(argv[i], NULL, &len, TRUE, TRUE, &n, NULL);
1189 if (len != 0 && len == (int)STRLEN(argv[i]))
1190 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +00001191 argvars[i].v_type = VAR_NUMBER;
1192 argvars[i].vval.v_number = n;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001193 }
1194 else
1195 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +00001196 argvars[i].v_type = VAR_STRING;
1197 argvars[i].vval.v_string = argv[i];
Bram Moolenaar071d4272004-06-13 20:20:40 +00001198 }
1199 }
1200
1201 if (safe)
1202 {
1203 save_funccalp = save_funccal();
1204 ++sandbox;
1205 }
1206
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001207 rettv.v_type = VAR_UNKNOWN; /* clear_tv() uses this */
1208 if (call_func(func, (int)STRLEN(func), &rettv, argc, argvars,
Bram Moolenaar071d4272004-06-13 20:20:40 +00001209 curwin->w_cursor.lnum, curwin->w_cursor.lnum,
Bram Moolenaare9a41262005-01-15 22:18:47 +00001210 &doesrange, TRUE, NULL) == OK)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001211 retval = vim_strsave(get_tv_string(&rettv));
Bram Moolenaar071d4272004-06-13 20:20:40 +00001212
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001213 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001214 vim_free(argvars);
1215
1216 if (safe)
1217 {
1218 --sandbox;
1219 restore_funccal(save_funccalp);
1220 }
1221 return retval;
1222}
1223#endif
1224
1225/*
1226 * Save the current function call pointer, and set it to NULL.
1227 * Used when executing autocommands and for ":source".
1228 */
1229 void *
1230save_funccal()
1231{
Bram Moolenaar05159a02005-02-26 23:04:13 +00001232 funccall_T *fc = current_funccal;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001233
Bram Moolenaar071d4272004-06-13 20:20:40 +00001234 current_funccal = NULL;
1235 return (void *)fc;
1236}
1237
1238 void
Bram Moolenaar05159a02005-02-26 23:04:13 +00001239restore_funccal(vfc)
1240 void *vfc;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001241{
Bram Moolenaar05159a02005-02-26 23:04:13 +00001242 funccall_T *fc = (funccall_T *)vfc;
1243
1244 current_funccal = fc;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001245}
1246
Bram Moolenaar05159a02005-02-26 23:04:13 +00001247#if defined(FEAT_PROFILE) || defined(PROTO)
1248/*
1249 * Prepare profiling for entering a child or something else that is not
1250 * counted for the script/function itself.
1251 * Should always be called in pair with prof_child_exit().
1252 */
1253 void
1254prof_child_enter(tm)
1255 proftime_T *tm; /* place to store waittime */
1256{
1257 funccall_T *fc = current_funccal;
1258
1259 if (fc != NULL && fc->func->uf_profiling)
1260 profile_start(&fc->prof_child);
1261 script_prof_save(tm);
1262}
1263
1264/*
1265 * Take care of time spent in a child.
1266 * Should always be called after prof_child_enter().
1267 */
1268 void
1269prof_child_exit(tm)
1270 proftime_T *tm; /* where waittime was stored */
1271{
1272 funccall_T *fc = current_funccal;
1273
1274 if (fc != NULL && fc->func->uf_profiling)
1275 {
1276 profile_end(&fc->prof_child);
1277 profile_sub_wait(tm, &fc->prof_child); /* don't count waiting time */
1278 profile_add(&fc->func->uf_tm_children, &fc->prof_child);
1279 profile_add(&fc->func->uf_tml_children, &fc->prof_child);
1280 }
1281 script_prof_restore(tm);
1282}
1283#endif
1284
1285
Bram Moolenaar071d4272004-06-13 20:20:40 +00001286#ifdef FEAT_FOLDING
1287/*
1288 * Evaluate 'foldexpr'. Returns the foldlevel, and any character preceding
1289 * it in "*cp". Doesn't give error messages.
1290 */
1291 int
1292eval_foldexpr(arg, cp)
1293 char_u *arg;
1294 int *cp;
1295{
Bram Moolenaar33570922005-01-25 22:26:29 +00001296 typval_T tv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001297 int retval;
1298 char_u *s;
1299
1300 ++emsg_off;
1301 ++sandbox;
1302 *cp = NUL;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001303 if (eval0(arg, &tv, NULL, TRUE) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001304 retval = 0;
1305 else
1306 {
1307 /* If the result is a number, just return the number. */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001308 if (tv.v_type == VAR_NUMBER)
1309 retval = tv.vval.v_number;
Bram Moolenaar758711c2005-02-02 23:11:38 +00001310 else if (tv.v_type != VAR_STRING || tv.vval.v_string == NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001311 retval = 0;
1312 else
1313 {
1314 /* If the result is a string, check if there is a non-digit before
1315 * the number. */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001316 s = tv.vval.v_string;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001317 if (!VIM_ISDIGIT(*s) && *s != '-')
1318 *cp = *s++;
1319 retval = atol((char *)s);
1320 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001321 clear_tv(&tv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001322 }
1323 --emsg_off;
1324 --sandbox;
1325
1326 return retval;
1327}
1328#endif
1329
Bram Moolenaar071d4272004-06-13 20:20:40 +00001330/*
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001331 * ":let" list all variable values
1332 * ":let var1 var2" list variable values
1333 * ":let var = expr" assignment command.
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001334 * ":let var += expr" assignment command.
1335 * ":let var -= expr" assignment command.
1336 * ":let var .= expr" assignment command.
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001337 * ":let [var1, var2] = expr" unpack list.
Bram Moolenaar071d4272004-06-13 20:20:40 +00001338 */
1339 void
1340ex_let(eap)
1341 exarg_T *eap;
1342{
1343 char_u *arg = eap->arg;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001344 char_u *expr = NULL;
Bram Moolenaar33570922005-01-25 22:26:29 +00001345 typval_T rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001346 int i;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001347 int var_count = 0;
1348 int semicolon = 0;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001349 char_u op[2];
Bram Moolenaar071d4272004-06-13 20:20:40 +00001350
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001351 expr = skip_var_list(arg, &var_count, &semicolon);
1352 if (expr == NULL)
1353 return;
1354 expr = vim_strchr(expr, '=');
1355 if (expr == NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001356 {
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00001357 /*
1358 * ":let" without "=": list variables
1359 */
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001360 if (*arg == '[')
1361 EMSG(_(e_invarg));
1362 else if (!ends_excmd(*arg))
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001363 /* ":let var1 var2" */
1364 arg = list_arg_vars(eap, arg);
1365 else if (!eap->skip)
Bram Moolenaara7043832005-01-21 11:56:39 +00001366 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001367 /* ":let" */
Bram Moolenaara7043832005-01-21 11:56:39 +00001368 list_glob_vars();
1369 list_buf_vars();
1370 list_win_vars();
1371 list_vim_vars();
1372 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001373 eap->nextcmd = check_nextcmd(arg);
1374 }
1375 else
1376 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001377 op[0] = '=';
1378 op[1] = NUL;
1379 if (expr > arg)
1380 {
1381 if (vim_strchr((char_u *)"+-.", expr[-1]) != NULL)
1382 op[0] = expr[-1]; /* +=, -= or .= */
1383 }
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001384 expr = skipwhite(expr + 1);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001385
Bram Moolenaar071d4272004-06-13 20:20:40 +00001386 if (eap->skip)
1387 ++emsg_skip;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001388 i = eval0(expr, &rettv, &eap->nextcmd, !eap->skip);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001389 if (eap->skip)
1390 {
1391 if (i != FAIL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001392 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001393 --emsg_skip;
1394 }
1395 else if (i != FAIL)
1396 {
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001397 (void)ex_let_vars(eap->arg, &rettv, FALSE, semicolon, var_count,
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001398 op);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001399 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001400 }
1401 }
1402}
1403
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001404/*
1405 * Assign the typevalue "tv" to the variable or variables at "arg_start".
1406 * Handles both "var" with any type and "[var, var; var]" with a list type.
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001407 * When "nextchars" is not NULL it points to a string with characters that
1408 * must appear after the variable(s). Use "+", "-" or "." for add, subtract
1409 * or concatenate.
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001410 * Returns OK or FAIL;
1411 */
1412 static int
1413ex_let_vars(arg_start, tv, copy, semicolon, var_count, nextchars)
1414 char_u *arg_start;
Bram Moolenaar33570922005-01-25 22:26:29 +00001415 typval_T *tv;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001416 int copy; /* copy values from "tv", don't move */
1417 int semicolon; /* from skip_var_list() */
1418 int var_count; /* from skip_var_list() */
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001419 char_u *nextchars;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001420{
1421 char_u *arg = arg_start;
Bram Moolenaar33570922005-01-25 22:26:29 +00001422 list_T *l;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001423 int i;
Bram Moolenaar33570922005-01-25 22:26:29 +00001424 listitem_T *item;
1425 typval_T ltv;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001426
1427 if (*arg != '[')
1428 {
1429 /*
1430 * ":let var = expr" or ":for var in list"
1431 */
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001432 if (ex_let_one(arg, tv, copy, nextchars, nextchars) == NULL)
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001433 return FAIL;
1434 return OK;
1435 }
1436
1437 /*
1438 * ":let [v1, v2] = list" or ":for [v1, v2] in listlist"
1439 */
Bram Moolenaar758711c2005-02-02 23:11:38 +00001440 if (tv->v_type != VAR_LIST || (l = tv->vval.v_list) == NULL)
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001441 {
1442 EMSG(_(e_listreq));
1443 return FAIL;
1444 }
1445
1446 i = list_len(l);
1447 if (semicolon == 0 && var_count < i)
1448 {
Bram Moolenaare49b69a2005-01-08 16:11:57 +00001449 EMSG(_("E687: Less targets than List items"));
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001450 return FAIL;
1451 }
1452 if (var_count - semicolon > i)
1453 {
Bram Moolenaare49b69a2005-01-08 16:11:57 +00001454 EMSG(_("E688: More targets than List items"));
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001455 return FAIL;
1456 }
1457
1458 item = l->lv_first;
1459 while (*arg != ']')
1460 {
1461 arg = skipwhite(arg + 1);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001462 arg = ex_let_one(arg, &item->li_tv, TRUE, (char_u *)",;]", nextchars);
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001463 item = item->li_next;
1464 if (arg == NULL)
1465 return FAIL;
1466
1467 arg = skipwhite(arg);
1468 if (*arg == ';')
1469 {
1470 /* Put the rest of the list (may be empty) in the var after ';'.
1471 * Create a new list for this. */
1472 l = list_alloc();
1473 if (l == NULL)
1474 return FAIL;
1475 while (item != NULL)
1476 {
1477 list_append_tv(l, &item->li_tv);
1478 item = item->li_next;
1479 }
1480
1481 ltv.v_type = VAR_LIST;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00001482 ltv.v_lock = 0;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001483 ltv.vval.v_list = l;
1484 l->lv_refcount = 1;
1485
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001486 arg = ex_let_one(skipwhite(arg + 1), &ltv, FALSE,
1487 (char_u *)"]", nextchars);
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001488 clear_tv(&ltv);
1489 if (arg == NULL)
1490 return FAIL;
1491 break;
1492 }
1493 else if (*arg != ',' && *arg != ']')
1494 {
1495 EMSG2(_(e_intern2), "ex_let_vars()");
1496 return FAIL;
1497 }
1498 }
1499
1500 return OK;
1501}
1502
1503/*
1504 * Skip over assignable variable "var" or list of variables "[var, var]".
1505 * Used for ":let varvar = expr" and ":for varvar in expr".
1506 * For "[var, var]" increment "*var_count" for each variable.
1507 * for "[var, var; var]" set "semicolon".
1508 * Return NULL for an error.
1509 */
1510 static char_u *
1511skip_var_list(arg, var_count, semicolon)
1512 char_u *arg;
1513 int *var_count;
1514 int *semicolon;
1515{
1516 char_u *p, *s;
1517
1518 if (*arg == '[')
1519 {
1520 /* "[var, var]": find the matching ']'. */
1521 p = arg;
1522 while (1)
1523 {
1524 p = skipwhite(p + 1); /* skip whites after '[', ';' or ',' */
1525 s = skip_var_one(p);
1526 if (s == p)
1527 {
1528 EMSG2(_(e_invarg2), p);
1529 return NULL;
1530 }
1531 ++*var_count;
1532
1533 p = skipwhite(s);
1534 if (*p == ']')
1535 break;
1536 else if (*p == ';')
1537 {
1538 if (*semicolon == 1)
1539 {
1540 EMSG(_("Double ; in list of variables"));
1541 return NULL;
1542 }
1543 *semicolon = 1;
1544 }
1545 else if (*p != ',')
1546 {
1547 EMSG2(_(e_invarg2), p);
1548 return NULL;
1549 }
1550 }
1551 return p + 1;
1552 }
1553 else
1554 return skip_var_one(arg);
1555}
1556
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001557/*
Bram Moolenaar92124a32005-06-17 22:03:40 +00001558 * Skip one (assignable) variable name, includig @r, $VAR, &option, d.key,
1559 * l[idx].
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001560 */
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001561 static char_u *
1562skip_var_one(arg)
1563 char_u *arg;
1564{
Bram Moolenaar92124a32005-06-17 22:03:40 +00001565 if (*arg == '@' && arg[1] != NUL)
1566 return arg + 2;
1567 return find_name_end(*arg == '$' || *arg == '&' ? arg + 1 : arg,
1568 NULL, NULL, FNE_INCL_BR | FNE_CHECK_START);
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001569}
1570
Bram Moolenaara7043832005-01-21 11:56:39 +00001571/*
Bram Moolenaar33570922005-01-25 22:26:29 +00001572 * List variables for hashtab "ht" with prefix "prefix".
1573 * If "empty" is TRUE also list NULL strings as empty strings.
Bram Moolenaara7043832005-01-21 11:56:39 +00001574 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001575 static void
Bram Moolenaar33570922005-01-25 22:26:29 +00001576list_hashtable_vars(ht, prefix, empty)
1577 hashtab_T *ht;
Bram Moolenaara7043832005-01-21 11:56:39 +00001578 char_u *prefix;
Bram Moolenaar33570922005-01-25 22:26:29 +00001579 int empty;
Bram Moolenaara7043832005-01-21 11:56:39 +00001580{
Bram Moolenaar33570922005-01-25 22:26:29 +00001581 hashitem_T *hi;
1582 dictitem_T *di;
Bram Moolenaara7043832005-01-21 11:56:39 +00001583 int todo;
1584
1585 todo = ht->ht_used;
1586 for (hi = ht->ht_array; todo > 0 && !got_int; ++hi)
1587 {
1588 if (!HASHITEM_EMPTY(hi))
1589 {
1590 --todo;
Bram Moolenaar33570922005-01-25 22:26:29 +00001591 di = HI2DI(hi);
1592 if (empty || di->di_tv.v_type != VAR_STRING
1593 || di->di_tv.vval.v_string != NULL)
1594 list_one_var(di, prefix);
Bram Moolenaara7043832005-01-21 11:56:39 +00001595 }
1596 }
1597}
1598
1599/*
1600 * List global variables.
1601 */
1602 static void
1603list_glob_vars()
1604{
Bram Moolenaar33570922005-01-25 22:26:29 +00001605 list_hashtable_vars(&globvarht, (char_u *)"", TRUE);
Bram Moolenaara7043832005-01-21 11:56:39 +00001606}
1607
1608/*
1609 * List buffer variables.
1610 */
1611 static void
1612list_buf_vars()
1613{
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001614 char_u numbuf[NUMBUFLEN];
1615
Bram Moolenaar33570922005-01-25 22:26:29 +00001616 list_hashtable_vars(&curbuf->b_vars.dv_hashtab, (char_u *)"b:", TRUE);
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001617
1618 sprintf((char *)numbuf, "%ld", (long)curbuf->b_changedtick);
1619 list_one_var_a((char_u *)"b:", (char_u *)"changedtick", VAR_NUMBER, numbuf);
Bram Moolenaara7043832005-01-21 11:56:39 +00001620}
1621
1622/*
1623 * List window variables.
1624 */
1625 static void
1626list_win_vars()
1627{
Bram Moolenaar33570922005-01-25 22:26:29 +00001628 list_hashtable_vars(&curwin->w_vars.dv_hashtab, (char_u *)"w:", TRUE);
Bram Moolenaara7043832005-01-21 11:56:39 +00001629}
1630
1631/*
1632 * List Vim variables.
1633 */
1634 static void
1635list_vim_vars()
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001636{
Bram Moolenaar33570922005-01-25 22:26:29 +00001637 list_hashtable_vars(&vimvarht, (char_u *)"v:", FALSE);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001638}
1639
1640/*
1641 * List variables in "arg".
1642 */
1643 static char_u *
1644list_arg_vars(eap, arg)
1645 exarg_T *eap;
1646 char_u *arg;
1647{
1648 int error = FALSE;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001649 int len;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001650 char_u *name;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001651 char_u *name_start;
1652 char_u *arg_subsc;
1653 char_u *tofree;
1654 typval_T tv;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001655
1656 while (!ends_excmd(*arg) && !got_int)
1657 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001658 if (error || eap->skip)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001659 {
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +00001660 arg = find_name_end(arg, NULL, NULL, FNE_INCL_BR | FNE_CHECK_START);
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001661 if (!vim_iswhite(*arg) && !ends_excmd(*arg))
1662 {
1663 emsg_severe = TRUE;
1664 EMSG(_(e_trailing));
1665 break;
1666 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001667 }
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001668 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001669 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001670 /* get_name_len() takes care of expanding curly braces */
1671 name_start = name = arg;
1672 len = get_name_len(&arg, &tofree, TRUE, TRUE);
1673 if (len <= 0)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001674 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001675 /* This is mainly to keep test 49 working: when expanding
1676 * curly braces fails overrule the exception error message. */
1677 if (len < 0 && !aborting())
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001678 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001679 emsg_severe = TRUE;
1680 EMSG2(_(e_invarg2), arg);
1681 break;
1682 }
1683 error = TRUE;
1684 }
1685 else
1686 {
1687 if (tofree != NULL)
1688 name = tofree;
1689 if (get_var_tv(name, len, &tv, TRUE) == FAIL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001690 error = TRUE;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001691 else
1692 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001693 /* handle d.key, l[idx], f(expr) */
1694 arg_subsc = arg;
1695 if (handle_subscript(&arg, &tv, TRUE, TRUE) == FAIL)
Bram Moolenaara7043832005-01-21 11:56:39 +00001696 error = TRUE;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001697 else
Bram Moolenaara7043832005-01-21 11:56:39 +00001698 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001699 if (arg == arg_subsc && len == 2 && name[1] == ':')
Bram Moolenaara7043832005-01-21 11:56:39 +00001700 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001701 switch (*name)
Bram Moolenaara7043832005-01-21 11:56:39 +00001702 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001703 case 'g': list_glob_vars(); break;
1704 case 'b': list_buf_vars(); break;
1705 case 'w': list_win_vars(); break;
1706 case 'v': list_vim_vars(); break;
1707 default:
1708 EMSG2(_("E738: Can't list variables for %s"), name);
Bram Moolenaara7043832005-01-21 11:56:39 +00001709 }
Bram Moolenaara7043832005-01-21 11:56:39 +00001710 }
1711 else
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001712 {
1713 char_u numbuf[NUMBUFLEN];
1714 char_u *tf;
1715 int c;
1716 char_u *s;
1717
1718 s = echo_string(&tv, &tf, numbuf);
1719 c = *arg;
1720 *arg = NUL;
1721 list_one_var_a((char_u *)"",
1722 arg == arg_subsc ? name : name_start,
1723 tv.v_type, s == NULL ? (char_u *)"" : s);
1724 *arg = c;
1725 vim_free(tf);
1726 }
1727 clear_tv(&tv);
Bram Moolenaara7043832005-01-21 11:56:39 +00001728 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001729 }
1730 }
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001731
1732 vim_free(tofree);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001733 }
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001734
1735 arg = skipwhite(arg);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001736 }
1737
1738 return arg;
1739}
1740
1741/*
1742 * Set one item of ":let var = expr" or ":let [v1, v2] = list" to its value.
1743 * Returns a pointer to the char just after the var name.
1744 * Returns NULL if there is an error.
1745 */
1746 static char_u *
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001747ex_let_one(arg, tv, copy, endchars, op)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001748 char_u *arg; /* points to variable name */
Bram Moolenaar33570922005-01-25 22:26:29 +00001749 typval_T *tv; /* value to assign to variable */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001750 int copy; /* copy value from "tv" */
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001751 char_u *endchars; /* valid chars after variable name or NULL */
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001752 char_u *op; /* "+", "-", "." or NULL*/
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001753{
1754 int c1;
1755 char_u *name;
1756 char_u *p;
1757 char_u *arg_end = NULL;
1758 int len;
1759 int opt_flags;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001760 char_u *tofree = NULL;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001761
1762 /*
1763 * ":let $VAR = expr": Set environment variable.
1764 */
1765 if (*arg == '$')
1766 {
1767 /* Find the end of the name. */
1768 ++arg;
1769 name = arg;
1770 len = get_env_len(&arg);
1771 if (len == 0)
1772 EMSG2(_(e_invarg2), name - 1);
1773 else
1774 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001775 if (op != NULL && (*op == '+' || *op == '-'))
1776 EMSG2(_(e_letwrong), op);
1777 else if (endchars != NULL
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001778 && vim_strchr(endchars, *skipwhite(arg)) == NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001779 EMSG(_(e_letunexp));
1780 else
1781 {
1782 c1 = name[len];
1783 name[len] = NUL;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00001784 p = get_tv_string_chk(tv);
1785 if (p != NULL && op != NULL && *op == '.')
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001786 {
1787 int mustfree = FALSE;
1788 char_u *s = vim_getenv(name, &mustfree);
1789
1790 if (s != NULL)
1791 {
1792 p = tofree = concat_str(s, p);
1793 if (mustfree)
1794 vim_free(s);
1795 }
1796 }
1797 if (p != NULL)
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00001798 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001799 vim_setenv(name, p);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00001800 if (STRICMP(name, "HOME") == 0)
1801 init_homedir();
1802 else if (didset_vim && STRICMP(name, "VIM") == 0)
1803 didset_vim = FALSE;
1804 else if (didset_vimruntime
1805 && STRICMP(name, "VIMRUNTIME") == 0)
1806 didset_vimruntime = FALSE;
1807 arg_end = arg;
1808 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001809 name[len] = c1;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001810 vim_free(tofree);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001811 }
1812 }
1813 }
1814
1815 /*
1816 * ":let &option = expr": Set option value.
1817 * ":let &l:option = expr": Set local option value.
1818 * ":let &g:option = expr": Set global option value.
1819 */
1820 else if (*arg == '&')
1821 {
1822 /* Find the end of the name. */
1823 p = find_option_end(&arg, &opt_flags);
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001824 if (p == NULL || (endchars != NULL
1825 && vim_strchr(endchars, *skipwhite(p)) == NULL))
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001826 EMSG(_(e_letunexp));
1827 else
1828 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001829 long n;
1830 int opt_type;
1831 long numval;
1832 char_u *stringval = NULL;
1833 char_u *s;
1834
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001835 c1 = *p;
1836 *p = NUL;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001837
1838 n = get_tv_number(tv);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00001839 s = get_tv_string_chk(tv); /* != NULL if number or string */
1840 if (s != NULL && op != NULL && *op != '=')
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001841 {
1842 opt_type = get_option_value(arg, &numval,
1843 &stringval, opt_flags);
1844 if ((opt_type == 1 && *op == '.')
1845 || (opt_type == 0 && *op != '.'))
1846 EMSG2(_(e_letwrong), op);
1847 else
1848 {
1849 if (opt_type == 1) /* number */
1850 {
1851 if (*op == '+')
1852 n = numval + n;
1853 else
1854 n = numval - n;
1855 }
1856 else if (opt_type == 0 && stringval != NULL) /* string */
1857 {
1858 s = concat_str(stringval, s);
1859 vim_free(stringval);
1860 stringval = s;
1861 }
1862 }
1863 }
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00001864 if (s != NULL)
1865 {
1866 set_option_value(arg, n, s, opt_flags);
1867 arg_end = p;
1868 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001869 *p = c1;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001870 vim_free(stringval);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001871 }
1872 }
1873
1874 /*
1875 * ":let @r = expr": Set register contents.
1876 */
1877 else if (*arg == '@')
1878 {
1879 ++arg;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001880 if (op != NULL && (*op == '+' || *op == '-'))
1881 EMSG2(_(e_letwrong), op);
1882 else if (endchars != NULL
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001883 && vim_strchr(endchars, *skipwhite(arg + 1)) == NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001884 EMSG(_(e_letunexp));
1885 else
1886 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001887 char_u *tofree = NULL;
1888 char_u *s;
1889
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00001890 p = get_tv_string_chk(tv);
1891 if (p != NULL && op != NULL && *op == '.')
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001892 {
Bram Moolenaar92124a32005-06-17 22:03:40 +00001893 s = get_reg_contents(*arg == '@' ? '"' : *arg, TRUE, TRUE);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001894 if (s != NULL)
1895 {
1896 p = tofree = concat_str(s, p);
1897 vim_free(s);
1898 }
1899 }
1900 if (p != NULL)
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00001901 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001902 write_reg_contents(*arg == '@' ? '"' : *arg, p, -1, FALSE);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00001903 arg_end = arg + 1;
1904 }
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001905 vim_free(tofree);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001906 }
1907 }
1908
1909 /*
1910 * ":let var = expr": Set internal variable.
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00001911 * ":let {expr} = expr": Idem, name made with curly braces
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001912 */
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +00001913 else if (eval_isnamec1(*arg) || *arg == '{')
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001914 {
Bram Moolenaar33570922005-01-25 22:26:29 +00001915 lval_T lv;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001916
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +00001917 p = get_lval(arg, tv, &lv, FALSE, FALSE, FALSE, FNE_CHECK_START);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00001918 if (p != NULL && lv.ll_name != NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001919 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00001920 if (endchars != NULL && vim_strchr(endchars, *skipwhite(p)) == NULL)
1921 EMSG(_(e_letunexp));
1922 else
1923 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001924 set_var_lval(&lv, p, tv, copy, op);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00001925 arg_end = p;
1926 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001927 }
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00001928 clear_lval(&lv);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001929 }
1930
1931 else
1932 EMSG2(_(e_invarg2), arg);
1933
1934 return arg_end;
1935}
1936
1937/*
Bram Moolenaar8c711452005-01-14 21:53:12 +00001938 * If "arg" is equal to "b:changedtick" give an error and return TRUE.
1939 */
1940 static int
1941check_changedtick(arg)
1942 char_u *arg;
1943{
1944 if (STRNCMP(arg, "b:changedtick", 13) == 0 && !eval_isnamec(arg[13]))
1945 {
1946 EMSG2(_(e_readonlyvar), arg);
1947 return TRUE;
1948 }
1949 return FALSE;
1950}
1951
1952/*
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00001953 * Get an lval: variable, Dict item or List item that can be assigned a value
1954 * to: "name", "na{me}", "name[expr]", "name[expr:expr]", "name[expr][expr]",
1955 * "name.key", "name.key[expr]" etc.
1956 * Indexing only works if "name" is an existing List or Dictionary.
1957 * "name" points to the start of the name.
1958 * If "rettv" is not NULL it points to the value to be assigned.
1959 * "unlet" is TRUE for ":unlet": slightly different behavior when something is
1960 * wrong; must end in space or cmd separator.
1961 *
1962 * Returns a pointer to just after the name, including indexes.
Bram Moolenaara7043832005-01-21 11:56:39 +00001963 * When an evaluation error occurs "lp->ll_name" is NULL;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00001964 * Returns NULL for a parsing error. Still need to free items in "lp"!
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001965 */
1966 static char_u *
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +00001967get_lval(name, rettv, lp, unlet, skip, quiet, fne_flags)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001968 char_u *name;
Bram Moolenaar33570922005-01-25 22:26:29 +00001969 typval_T *rettv;
1970 lval_T *lp;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00001971 int unlet;
1972 int skip;
1973 int quiet; /* don't give error messages */
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +00001974 int fne_flags; /* flags for find_name_end() */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001975{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001976 char_u *p;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00001977 char_u *expr_start, *expr_end;
1978 int cc;
Bram Moolenaar33570922005-01-25 22:26:29 +00001979 dictitem_T *v;
1980 typval_T var1;
1981 typval_T var2;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00001982 int empty1 = FALSE;
Bram Moolenaar33570922005-01-25 22:26:29 +00001983 listitem_T *ni;
Bram Moolenaar8c711452005-01-14 21:53:12 +00001984 char_u *key = NULL;
Bram Moolenaar8c711452005-01-14 21:53:12 +00001985 int len;
Bram Moolenaar33570922005-01-25 22:26:29 +00001986 hashtab_T *ht;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001987
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00001988 /* Clear everything in "lp". */
Bram Moolenaar33570922005-01-25 22:26:29 +00001989 vim_memset(lp, 0, sizeof(lval_T));
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00001990
1991 if (skip)
1992 {
1993 /* When skipping just find the end of the name. */
1994 lp->ll_name = name;
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +00001995 return find_name_end(name, NULL, NULL, FNE_INCL_BR | fne_flags);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00001996 }
1997
1998 /* Find the end of the name. */
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +00001999 p = find_name_end(name, &expr_start, &expr_end, fne_flags);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002000 if (expr_start != NULL)
2001 {
2002 /* Don't expand the name when we already know there is an error. */
2003 if (unlet && !vim_iswhite(*p) && !ends_excmd(*p)
2004 && *p != '[' && *p != '.')
2005 {
2006 EMSG(_(e_trailing));
2007 return NULL;
2008 }
2009
2010 lp->ll_exp_name = make_expanded_name(name, expr_start, expr_end, p);
2011 if (lp->ll_exp_name == NULL)
2012 {
2013 /* Report an invalid expression in braces, unless the
2014 * expression evaluation has been cancelled due to an
2015 * aborting error, an interrupt, or an exception. */
2016 if (!aborting() && !quiet)
2017 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00002018 emsg_severe = TRUE;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002019 EMSG2(_(e_invarg2), name);
2020 return NULL;
2021 }
2022 }
2023 lp->ll_name = lp->ll_exp_name;
2024 }
2025 else
2026 lp->ll_name = name;
2027
2028 /* Without [idx] or .key we are done. */
2029 if ((*p != '[' && *p != '.') || lp->ll_name == NULL)
2030 return p;
2031
2032 cc = *p;
2033 *p = NUL;
Bram Moolenaara7043832005-01-21 11:56:39 +00002034 v = find_var(lp->ll_name, &ht);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002035 if (v == NULL && !quiet)
2036 EMSG2(_(e_undefvar), lp->ll_name);
2037 *p = cc;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002038 if (v == NULL)
2039 return NULL;
2040
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002041 /*
2042 * Loop until no more [idx] or .key is following.
2043 */
Bram Moolenaar33570922005-01-25 22:26:29 +00002044 lp->ll_tv = &v->di_tv;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002045 while (*p == '[' || (*p == '.' && lp->ll_tv->v_type == VAR_DICT))
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002046 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002047 if (!(lp->ll_tv->v_type == VAR_LIST && lp->ll_tv->vval.v_list != NULL)
2048 && !(lp->ll_tv->v_type == VAR_DICT
2049 && lp->ll_tv->vval.v_dict != NULL))
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002050 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002051 if (!quiet)
2052 EMSG(_("E689: Can only index a List or Dictionary"));
2053 return NULL;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002054 }
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002055 if (lp->ll_range)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002056 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002057 if (!quiet)
2058 EMSG(_("E708: [:] must come last"));
2059 return NULL;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002060 }
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002061
Bram Moolenaar8c711452005-01-14 21:53:12 +00002062 len = -1;
2063 if (*p == '.')
2064 {
2065 key = p + 1;
2066 for (len = 0; ASCII_ISALNUM(key[len]) || key[len] == '_'; ++len)
2067 ;
2068 if (len == 0)
2069 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002070 if (!quiet)
2071 EMSG(_(e_emptykey));
2072 return NULL;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002073 }
2074 p = key + len;
2075 }
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002076 else
2077 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00002078 /* Get the index [expr] or the first index [expr: ]. */
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002079 p = skipwhite(p + 1);
Bram Moolenaar8c711452005-01-14 21:53:12 +00002080 if (*p == ':')
2081 empty1 = TRUE;
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002082 else
2083 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00002084 empty1 = FALSE;
2085 if (eval1(&p, &var1, TRUE) == FAIL) /* recursive! */
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002086 return NULL;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00002087 if (get_tv_string_chk(&var1) == NULL)
2088 {
2089 /* not a number or string */
2090 clear_tv(&var1);
2091 return NULL;
2092 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00002093 }
2094
2095 /* Optionally get the second index [ :expr]. */
2096 if (*p == ':')
2097 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002098 if (lp->ll_tv->v_type == VAR_DICT)
Bram Moolenaar8c711452005-01-14 21:53:12 +00002099 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002100 if (!quiet)
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002101 EMSG(_(e_dictrange));
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002102 if (!empty1)
2103 clear_tv(&var1);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002104 return NULL;
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002105 }
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002106 if (rettv != NULL && (rettv->v_type != VAR_LIST
2107 || rettv->vval.v_list == NULL))
Bram Moolenaar8c711452005-01-14 21:53:12 +00002108 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002109 if (!quiet)
2110 EMSG(_("E709: [:] requires a List value"));
Bram Moolenaar8c711452005-01-14 21:53:12 +00002111 if (!empty1)
2112 clear_tv(&var1);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002113 return NULL;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002114 }
2115 p = skipwhite(p + 1);
2116 if (*p == ']')
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002117 lp->ll_empty2 = TRUE;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002118 else
2119 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002120 lp->ll_empty2 = FALSE;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002121 if (eval1(&p, &var2, TRUE) == FAIL) /* recursive! */
2122 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00002123 if (!empty1)
2124 clear_tv(&var1);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002125 return NULL;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002126 }
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00002127 if (get_tv_string_chk(&var2) == NULL)
2128 {
2129 /* not a number or string */
2130 if (!empty1)
2131 clear_tv(&var1);
2132 clear_tv(&var2);
2133 return NULL;
2134 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00002135 }
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002136 lp->ll_range = TRUE;
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002137 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00002138 else
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002139 lp->ll_range = FALSE;
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002140
Bram Moolenaar8c711452005-01-14 21:53:12 +00002141 if (*p != ']')
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002142 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002143 if (!quiet)
2144 EMSG(_(e_missbrac));
Bram Moolenaar8c711452005-01-14 21:53:12 +00002145 if (!empty1)
2146 clear_tv(&var1);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002147 if (lp->ll_range && !lp->ll_empty2)
Bram Moolenaar8c711452005-01-14 21:53:12 +00002148 clear_tv(&var2);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002149 return NULL;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002150 }
2151
2152 /* Skip to past ']'. */
2153 ++p;
2154 }
2155
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002156 if (lp->ll_tv->v_type == VAR_DICT)
Bram Moolenaar8c711452005-01-14 21:53:12 +00002157 {
2158 if (len == -1)
2159 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002160 /* "[key]": get key from "var1" */
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00002161 key = get_tv_string(&var1); /* is number or string */
Bram Moolenaar8c711452005-01-14 21:53:12 +00002162 if (*key == NUL)
2163 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002164 if (!quiet)
2165 EMSG(_(e_emptykey));
Bram Moolenaar8c711452005-01-14 21:53:12 +00002166 clear_tv(&var1);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002167 return NULL;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002168 }
2169 }
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002170 lp->ll_list = NULL;
2171 lp->ll_dict = lp->ll_tv->vval.v_dict;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00002172 lp->ll_di = dict_find(lp->ll_dict, key, len);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002173 if (lp->ll_di == NULL)
Bram Moolenaar8c711452005-01-14 21:53:12 +00002174 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00002175 /* Key does not exist in dict: may need to add it. */
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002176 if (*p == '[' || *p == '.' || unlet)
Bram Moolenaar8c711452005-01-14 21:53:12 +00002177 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002178 if (!quiet)
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002179 EMSG2(_(e_dictkey), key);
Bram Moolenaar8c711452005-01-14 21:53:12 +00002180 if (len == -1)
2181 clear_tv(&var1);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002182 return NULL;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002183 }
2184 if (len == -1)
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002185 lp->ll_newkey = vim_strsave(key);
Bram Moolenaar8c711452005-01-14 21:53:12 +00002186 else
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002187 lp->ll_newkey = vim_strnsave(key, len);
Bram Moolenaar8c711452005-01-14 21:53:12 +00002188 if (len == -1)
2189 clear_tv(&var1);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002190 if (lp->ll_newkey == NULL)
Bram Moolenaar8c711452005-01-14 21:53:12 +00002191 p = NULL;
2192 break;
2193 }
2194 if (len == -1)
2195 clear_tv(&var1);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002196 lp->ll_tv = &lp->ll_di->di_tv;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002197 }
2198 else
2199 {
2200 /*
2201 * Get the number and item for the only or first index of the List.
2202 */
2203 if (empty1)
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002204 lp->ll_n1 = 0;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002205 else
2206 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00002207 lp->ll_n1 = get_tv_number(&var1); /* is number or string */
Bram Moolenaar8c711452005-01-14 21:53:12 +00002208 clear_tv(&var1);
2209 }
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002210 lp->ll_dict = NULL;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002211 lp->ll_list = lp->ll_tv->vval.v_list;
2212 lp->ll_li = list_find(lp->ll_list, lp->ll_n1);
2213 if (lp->ll_li == NULL)
Bram Moolenaar8c711452005-01-14 21:53:12 +00002214 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002215 if (!quiet)
2216 EMSGN(_(e_listidx), lp->ll_n1);
2217 if (lp->ll_range && !lp->ll_empty2)
Bram Moolenaar8c711452005-01-14 21:53:12 +00002218 clear_tv(&var2);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002219 return NULL;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002220 }
2221
2222 /*
2223 * May need to find the item or absolute index for the second
2224 * index of a range.
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002225 * When no index given: "lp->ll_empty2" is TRUE.
2226 * Otherwise "lp->ll_n2" is set to the second index.
Bram Moolenaar8c711452005-01-14 21:53:12 +00002227 */
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002228 if (lp->ll_range && !lp->ll_empty2)
Bram Moolenaar8c711452005-01-14 21:53:12 +00002229 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00002230 lp->ll_n2 = get_tv_number(&var2); /* is number or string */
Bram Moolenaar8c711452005-01-14 21:53:12 +00002231 clear_tv(&var2);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002232 if (lp->ll_n2 < 0)
Bram Moolenaar8c711452005-01-14 21:53:12 +00002233 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002234 ni = list_find(lp->ll_list, lp->ll_n2);
Bram Moolenaar8c711452005-01-14 21:53:12 +00002235 if (ni == NULL)
2236 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002237 if (!quiet)
2238 EMSGN(_(e_listidx), lp->ll_n2);
2239 return NULL;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002240 }
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002241 lp->ll_n2 = list_idx_of_item(lp->ll_list, ni);
Bram Moolenaar8c711452005-01-14 21:53:12 +00002242 }
2243
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002244 /* Check that lp->ll_n2 isn't before lp->ll_n1. */
2245 if (lp->ll_n1 < 0)
2246 lp->ll_n1 = list_idx_of_item(lp->ll_list, lp->ll_li);
2247 if (lp->ll_n2 < lp->ll_n1)
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002248 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002249 if (!quiet)
2250 EMSGN(_(e_listidx), lp->ll_n2);
2251 return NULL;
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002252 }
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002253 }
2254
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002255 lp->ll_tv = &lp->ll_li->li_tv;
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002256 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002257 }
2258
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002259 return p;
2260}
2261
2262/*
Bram Moolenaar33570922005-01-25 22:26:29 +00002263 * Clear lval "lp" that was filled by get_lval().
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002264 */
2265 static void
2266clear_lval(lp)
Bram Moolenaar33570922005-01-25 22:26:29 +00002267 lval_T *lp;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002268{
2269 vim_free(lp->ll_exp_name);
2270 vim_free(lp->ll_newkey);
2271}
2272
2273/*
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00002274 * Set a variable that was parsed by get_lval() to "rettv".
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002275 * "endp" points to just after the parsed name.
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002276 * "op" is NULL, "+" for "+=", "-" for "-=", "." for ".=" or "=" for "=".
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002277 */
2278 static void
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002279set_var_lval(lp, endp, rettv, copy, op)
Bram Moolenaar33570922005-01-25 22:26:29 +00002280 lval_T *lp;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002281 char_u *endp;
Bram Moolenaar33570922005-01-25 22:26:29 +00002282 typval_T *rettv;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002283 int copy;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002284 char_u *op;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002285{
2286 int cc;
Bram Moolenaar33570922005-01-25 22:26:29 +00002287 listitem_T *ni;
2288 listitem_T *ri;
2289 dictitem_T *di;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002290
2291 if (lp->ll_tv == NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002292 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002293 if (!check_changedtick(lp->ll_name))
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002294 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002295 cc = *endp;
2296 *endp = NUL;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002297 if (op != NULL && *op != '=')
2298 {
Bram Moolenaar33570922005-01-25 22:26:29 +00002299 typval_T tv;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002300
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00002301 /* handle +=, -= and .= */
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00002302 if (get_var_tv(lp->ll_name, STRLEN(lp->ll_name),
2303 &tv, TRUE) == OK)
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002304 {
2305 if (tv_op(&tv, rettv, op) == OK)
2306 set_var(lp->ll_name, &tv, FALSE);
2307 clear_tv(&tv);
2308 }
2309 }
2310 else
2311 set_var(lp->ll_name, rettv, copy);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002312 *endp = cc;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002313 }
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002314 }
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00002315 else if (tv_check_lock(lp->ll_newkey == NULL
2316 ? lp->ll_tv->v_lock
2317 : lp->ll_tv->vval.v_dict->dv_lock, lp->ll_name))
2318 ;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002319 else if (lp->ll_range)
2320 {
2321 /*
2322 * Assign the List values to the list items.
2323 */
2324 for (ri = rettv->vval.v_list->lv_first; ri != NULL; )
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002325 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002326 if (op != NULL && *op != '=')
2327 tv_op(&lp->ll_li->li_tv, &ri->li_tv, op);
2328 else
2329 {
2330 clear_tv(&lp->ll_li->li_tv);
2331 copy_tv(&ri->li_tv, &lp->ll_li->li_tv);
2332 }
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002333 ri = ri->li_next;
2334 if (ri == NULL || (!lp->ll_empty2 && lp->ll_n2 == lp->ll_n1))
2335 break;
2336 if (lp->ll_li->li_next == NULL)
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002337 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002338 /* Need to add an empty item. */
2339 ni = listitem_alloc();
2340 if (ni == NULL)
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002341 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002342 ri = NULL;
2343 break;
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002344 }
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002345 ni->li_tv.v_type = VAR_NUMBER;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00002346 ni->li_tv.v_lock = 0;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002347 ni->li_tv.vval.v_number = 0;
2348 list_append(lp->ll_list, ni);
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002349 }
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002350 lp->ll_li = lp->ll_li->li_next;
2351 ++lp->ll_n1;
2352 }
2353 if (ri != NULL)
2354 EMSG(_("E710: List value has more items than target"));
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002355 else if (lp->ll_empty2
2356 ? (lp->ll_li != NULL && lp->ll_li->li_next != NULL)
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002357 : lp->ll_n1 != lp->ll_n2)
2358 EMSG(_("E711: List value has not enough items"));
2359 }
2360 else
2361 {
2362 /*
2363 * Assign to a List or Dictionary item.
2364 */
2365 if (lp->ll_newkey != NULL)
2366 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002367 if (op != NULL && *op != '=')
2368 {
2369 EMSG2(_(e_letwrong), op);
2370 return;
2371 }
2372
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002373 /* Need to add an item to the Dictionary. */
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00002374 di = dictitem_alloc(lp->ll_newkey);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002375 if (di == NULL)
2376 return;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00002377 if (dict_add(lp->ll_tv->vval.v_dict, di) == FAIL)
2378 {
2379 vim_free(di);
2380 return;
2381 }
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002382 lp->ll_tv = &di->di_tv;
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002383 }
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002384 else if (op != NULL && *op != '=')
2385 {
2386 tv_op(lp->ll_tv, rettv, op);
2387 return;
2388 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002389 else
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002390 clear_tv(lp->ll_tv);
Bram Moolenaar8c711452005-01-14 21:53:12 +00002391
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002392 /*
2393 * Assign the value to the variable or list item.
2394 */
2395 if (copy)
2396 copy_tv(rettv, lp->ll_tv);
2397 else
2398 {
2399 *lp->ll_tv = *rettv;
Bram Moolenaar758711c2005-02-02 23:11:38 +00002400 lp->ll_tv->v_lock = 0;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002401 init_tv(rettv);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002402 }
2403 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002404}
2405
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002406/*
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002407 * Handle "tv1 += tv2", "tv1 -= tv2" and "tv1 .= tv2"
2408 * Returns OK or FAIL.
2409 */
2410 static int
2411tv_op(tv1, tv2, op)
Bram Moolenaar33570922005-01-25 22:26:29 +00002412 typval_T *tv1;
2413 typval_T *tv2;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002414 char_u *op;
2415{
2416 long n;
2417 char_u numbuf[NUMBUFLEN];
2418 char_u *s;
2419
2420 /* Can't do anything with a Funcref or a Dict on the right. */
2421 if (tv2->v_type != VAR_FUNC && tv2->v_type != VAR_DICT)
2422 {
2423 switch (tv1->v_type)
2424 {
2425 case VAR_DICT:
2426 case VAR_FUNC:
2427 break;
2428
2429 case VAR_LIST:
2430 if (*op != '+' || tv2->v_type != VAR_LIST)
2431 break;
2432 /* List += List */
2433 if (tv1->vval.v_list != NULL && tv2->vval.v_list != NULL)
2434 list_extend(tv1->vval.v_list, tv2->vval.v_list, NULL);
2435 return OK;
2436
2437 case VAR_NUMBER:
2438 case VAR_STRING:
2439 if (tv2->v_type == VAR_LIST)
2440 break;
2441 if (*op == '+' || *op == '-')
2442 {
2443 /* nr += nr or nr -= nr*/
2444 n = get_tv_number(tv1);
2445 if (*op == '+')
2446 n += get_tv_number(tv2);
2447 else
2448 n -= get_tv_number(tv2);
2449 clear_tv(tv1);
2450 tv1->v_type = VAR_NUMBER;
2451 tv1->vval.v_number = n;
2452 }
2453 else
2454 {
2455 /* str .= str */
2456 s = get_tv_string(tv1);
2457 s = concat_str(s, get_tv_string_buf(tv2, numbuf));
2458 clear_tv(tv1);
2459 tv1->v_type = VAR_STRING;
2460 tv1->vval.v_string = s;
2461 }
2462 return OK;
2463 }
2464 }
2465
2466 EMSG2(_(e_letwrong), op);
2467 return FAIL;
2468}
2469
2470/*
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002471 * Add a watcher to a list.
2472 */
2473 static void
2474list_add_watch(l, lw)
Bram Moolenaar33570922005-01-25 22:26:29 +00002475 list_T *l;
2476 listwatch_T *lw;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002477{
2478 lw->lw_next = l->lv_watch;
2479 l->lv_watch = lw;
2480}
2481
2482/*
Bram Moolenaar758711c2005-02-02 23:11:38 +00002483 * Remove a watcher from a list.
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002484 * No warning when it isn't found...
2485 */
2486 static void
2487list_rem_watch(l, lwrem)
Bram Moolenaar33570922005-01-25 22:26:29 +00002488 list_T *l;
2489 listwatch_T *lwrem;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002490{
Bram Moolenaar33570922005-01-25 22:26:29 +00002491 listwatch_T *lw, **lwp;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002492
2493 lwp = &l->lv_watch;
2494 for (lw = l->lv_watch; lw != NULL; lw = lw->lw_next)
2495 {
2496 if (lw == lwrem)
2497 {
2498 *lwp = lw->lw_next;
2499 break;
2500 }
2501 lwp = &lw->lw_next;
2502 }
2503}
2504
2505/*
2506 * Just before removing an item from a list: advance watchers to the next
2507 * item.
2508 */
2509 static void
2510list_fix_watch(l, item)
Bram Moolenaar33570922005-01-25 22:26:29 +00002511 list_T *l;
2512 listitem_T *item;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002513{
Bram Moolenaar33570922005-01-25 22:26:29 +00002514 listwatch_T *lw;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002515
2516 for (lw = l->lv_watch; lw != NULL; lw = lw->lw_next)
2517 if (lw->lw_item == item)
2518 lw->lw_item = item->li_next;
2519}
2520
2521/*
2522 * Evaluate the expression used in a ":for var in expr" command.
2523 * "arg" points to "var".
2524 * Set "*errp" to TRUE for an error, FALSE otherwise;
2525 * Return a pointer that holds the info. Null when there is an error.
2526 */
2527 void *
2528eval_for_line(arg, errp, nextcmdp, skip)
2529 char_u *arg;
2530 int *errp;
2531 char_u **nextcmdp;
2532 int skip;
2533{
Bram Moolenaar33570922005-01-25 22:26:29 +00002534 forinfo_T *fi;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002535 char_u *expr;
Bram Moolenaar33570922005-01-25 22:26:29 +00002536 typval_T tv;
2537 list_T *l;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002538
2539 *errp = TRUE; /* default: there is an error */
2540
Bram Moolenaar33570922005-01-25 22:26:29 +00002541 fi = (forinfo_T *)alloc_clear(sizeof(forinfo_T));
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002542 if (fi == NULL)
2543 return NULL;
2544
2545 expr = skip_var_list(arg, &fi->fi_varcount, &fi->fi_semicolon);
2546 if (expr == NULL)
2547 return fi;
2548
2549 expr = skipwhite(expr);
2550 if (expr[0] != 'i' || expr[1] != 'n' || !vim_iswhite(expr[2]))
2551 {
Bram Moolenaare49b69a2005-01-08 16:11:57 +00002552 EMSG(_("E690: Missing \"in\" after :for"));
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002553 return fi;
2554 }
2555
2556 if (skip)
2557 ++emsg_skip;
2558 if (eval0(skipwhite(expr + 2), &tv, nextcmdp, !skip) == OK)
2559 {
2560 *errp = FALSE;
2561 if (!skip)
2562 {
2563 l = tv.vval.v_list;
2564 if (tv.v_type != VAR_LIST || l == NULL)
2565 EMSG(_(e_listreq));
2566 else
2567 {
2568 fi->fi_list = l;
2569 list_add_watch(l, &fi->fi_lw);
2570 fi->fi_lw.lw_item = l->lv_first;
2571 }
2572 }
2573 }
2574 if (skip)
2575 --emsg_skip;
2576
2577 return fi;
2578}
2579
2580/*
2581 * Use the first item in a ":for" list. Advance to the next.
2582 * Assign the values to the variable (list). "arg" points to the first one.
2583 * Return TRUE when a valid item was found, FALSE when at end of list or
2584 * something wrong.
2585 */
2586 int
2587next_for_item(fi_void, arg)
2588 void *fi_void;
2589 char_u *arg;
2590{
Bram Moolenaar33570922005-01-25 22:26:29 +00002591 forinfo_T *fi = (forinfo_T *)fi_void;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002592 int result;
Bram Moolenaar33570922005-01-25 22:26:29 +00002593 listitem_T *item;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002594
2595 item = fi->fi_lw.lw_item;
2596 if (item == NULL)
2597 result = FALSE;
2598 else
2599 {
2600 fi->fi_lw.lw_item = item->li_next;
2601 result = (ex_let_vars(arg, &item->li_tv, TRUE,
2602 fi->fi_semicolon, fi->fi_varcount, NULL) == OK);
2603 }
2604 return result;
2605}
2606
2607/*
2608 * Free the structure used to store info used by ":for".
2609 */
2610 void
2611free_for_info(fi_void)
2612 void *fi_void;
2613{
Bram Moolenaar33570922005-01-25 22:26:29 +00002614 forinfo_T *fi = (forinfo_T *)fi_void;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002615
Bram Moolenaarab7013c2005-01-09 21:23:56 +00002616 if (fi != NULL && fi->fi_list != NULL)
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002617 list_rem_watch(fi->fi_list, &fi->fi_lw);
2618 vim_free(fi);
2619}
2620
Bram Moolenaar071d4272004-06-13 20:20:40 +00002621#if defined(FEAT_CMDL_COMPL) || defined(PROTO)
2622
2623 void
2624set_context_for_expression(xp, arg, cmdidx)
2625 expand_T *xp;
2626 char_u *arg;
2627 cmdidx_T cmdidx;
2628{
2629 int got_eq = FALSE;
2630 int c;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002631 char_u *p;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002632
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002633 if (cmdidx == CMD_let)
2634 {
2635 xp->xp_context = EXPAND_USER_VARS;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00002636 if (vim_strpbrk(arg, (char_u *)"\"'+-*/%.=!?~|&$([<>,#") == NULL)
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002637 {
2638 /* ":let var1 var2 ...": find last space. */
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00002639 for (p = arg + STRLEN(arg); p >= arg; )
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002640 {
2641 xp->xp_pattern = p;
Bram Moolenaar33570922005-01-25 22:26:29 +00002642 mb_ptr_back(arg, p);
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002643 if (vim_iswhite(*p))
2644 break;
2645 }
2646 return;
2647 }
2648 }
2649 else
2650 xp->xp_context = cmdidx == CMD_call ? EXPAND_FUNCTIONS
2651 : EXPAND_EXPRESSION;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002652 while ((xp->xp_pattern = vim_strpbrk(arg,
2653 (char_u *)"\"'+-*/%.=!?~|&$([<>,#")) != NULL)
2654 {
2655 c = *xp->xp_pattern;
2656 if (c == '&')
2657 {
2658 c = xp->xp_pattern[1];
2659 if (c == '&')
2660 {
2661 ++xp->xp_pattern;
2662 xp->xp_context = cmdidx != CMD_let || got_eq
2663 ? EXPAND_EXPRESSION : EXPAND_NOTHING;
2664 }
2665 else if (c != ' ')
Bram Moolenaar11cbeb12005-03-11 22:51:16 +00002666 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00002667 xp->xp_context = EXPAND_SETTINGS;
Bram Moolenaar11cbeb12005-03-11 22:51:16 +00002668 if ((c == 'l' || c == 'g') && xp->xp_pattern[2] == ':')
2669 xp->xp_pattern += 2;
2670
2671 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00002672 }
2673 else if (c == '$')
2674 {
2675 /* environment variable */
2676 xp->xp_context = EXPAND_ENV_VARS;
2677 }
2678 else if (c == '=')
2679 {
2680 got_eq = TRUE;
2681 xp->xp_context = EXPAND_EXPRESSION;
2682 }
2683 else if (c == '<'
2684 && xp->xp_context == EXPAND_FUNCTIONS
2685 && vim_strchr(xp->xp_pattern, '(') == NULL)
2686 {
2687 /* Function name can start with "<SNR>" */
2688 break;
2689 }
2690 else if (cmdidx != CMD_let || got_eq)
2691 {
2692 if (c == '"') /* string */
2693 {
2694 while ((c = *++xp->xp_pattern) != NUL && c != '"')
2695 if (c == '\\' && xp->xp_pattern[1] != NUL)
2696 ++xp->xp_pattern;
2697 xp->xp_context = EXPAND_NOTHING;
2698 }
2699 else if (c == '\'') /* literal string */
2700 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00002701 /* Trick: '' is like stopping and starting a literal string. */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002702 while ((c = *++xp->xp_pattern) != NUL && c != '\'')
2703 /* skip */ ;
2704 xp->xp_context = EXPAND_NOTHING;
2705 }
2706 else if (c == '|')
2707 {
2708 if (xp->xp_pattern[1] == '|')
2709 {
2710 ++xp->xp_pattern;
2711 xp->xp_context = EXPAND_EXPRESSION;
2712 }
2713 else
2714 xp->xp_context = EXPAND_COMMANDS;
2715 }
2716 else
2717 xp->xp_context = EXPAND_EXPRESSION;
2718 }
2719 else
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002720 /* Doesn't look like something valid, expand as an expression
2721 * anyway. */
2722 xp->xp_context = EXPAND_EXPRESSION;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002723 arg = xp->xp_pattern;
2724 if (*arg != NUL)
2725 while ((c = *++arg) != NUL && (c == ' ' || c == '\t'))
2726 /* skip */ ;
2727 }
2728 xp->xp_pattern = arg;
2729}
2730
2731#endif /* FEAT_CMDL_COMPL */
2732
2733/*
2734 * ":1,25call func(arg1, arg2)" function call.
2735 */
2736 void
2737ex_call(eap)
2738 exarg_T *eap;
2739{
2740 char_u *arg = eap->arg;
2741 char_u *startarg;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002742 char_u *name;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002743 char_u *tofree;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002744 int len;
Bram Moolenaar33570922005-01-25 22:26:29 +00002745 typval_T rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002746 linenr_T lnum;
2747 int doesrange;
2748 int failed = FALSE;
Bram Moolenaar33570922005-01-25 22:26:29 +00002749 funcdict_T fudi;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002750
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00002751 tofree = trans_function_name(&arg, eap->skip, TFN_INT, &fudi);
2752 vim_free(fudi.fd_newkey);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002753 if (tofree == NULL)
2754 return;
2755
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00002756 /* Increase refcount on dictionary, it could get deleted when evaluating
2757 * the arguments. */
2758 if (fudi.fd_dict != NULL)
2759 ++fudi.fd_dict->dv_refcount;
2760
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002761 /* If it is the name of a variable of type VAR_FUNC use its contents. */
2762 len = STRLEN(tofree);
2763 name = deref_func_name(tofree, &len);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002764
Bram Moolenaar532c7802005-01-27 14:44:31 +00002765 /* Skip white space to allow ":call func ()". Not good, but required for
2766 * backward compatibility. */
2767 startarg = skipwhite(arg);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002768 rettv.v_type = VAR_UNKNOWN; /* clear_tv() uses this */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002769
2770 if (*startarg != '(')
2771 {
Bram Moolenaar81bf7082005-02-12 14:31:42 +00002772 EMSG2(_("E107: Missing braces: %s"), eap->arg);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002773 goto end;
2774 }
2775
2776 /*
2777 * When skipping, evaluate the function once, to find the end of the
2778 * arguments.
2779 * When the function takes a range, this is discovered after the first
2780 * call, and the loop is broken.
2781 */
2782 if (eap->skip)
2783 {
2784 ++emsg_skip;
2785 lnum = eap->line2; /* do it once, also with an invalid range */
2786 }
2787 else
2788 lnum = eap->line1;
2789 for ( ; lnum <= eap->line2; ++lnum)
2790 {
2791 if (!eap->skip && eap->addr_count > 0)
2792 {
2793 curwin->w_cursor.lnum = lnum;
2794 curwin->w_cursor.col = 0;
2795 }
2796 arg = startarg;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002797 if (get_func_tv(name, STRLEN(name), &rettv, &arg,
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00002798 eap->line1, eap->line2, &doesrange,
2799 !eap->skip, fudi.fd_dict) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002800 {
2801 failed = TRUE;
2802 break;
2803 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002804 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002805 if (doesrange || eap->skip)
2806 break;
2807 /* Stop when immediately aborting on error, or when an interrupt
Bram Moolenaar49cd9572005-01-03 21:06:01 +00002808 * occurred or an exception was thrown but not caught.
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002809 * get_func_tv() returned OK, so that the check for trailing
Bram Moolenaar49cd9572005-01-03 21:06:01 +00002810 * characters below is executed. */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002811 if (aborting())
2812 break;
2813 }
2814 if (eap->skip)
2815 --emsg_skip;
2816
2817 if (!failed)
2818 {
2819 /* Check for trailing illegal characters and a following command. */
2820 if (!ends_excmd(*arg))
2821 {
2822 emsg_severe = TRUE;
2823 EMSG(_(e_trailing));
2824 }
2825 else
2826 eap->nextcmd = check_nextcmd(arg);
2827 }
2828
2829end:
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00002830 dict_unref(fudi.fd_dict);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002831 vim_free(tofree);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002832}
2833
2834/*
2835 * ":unlet[!] var1 ... " command.
2836 */
2837 void
2838ex_unlet(eap)
2839 exarg_T *eap;
2840{
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00002841 ex_unletlock(eap, eap->arg, 0);
2842}
2843
2844/*
2845 * ":lockvar" and ":unlockvar" commands
2846 */
2847 void
2848ex_lockvar(eap)
2849 exarg_T *eap;
2850{
Bram Moolenaar071d4272004-06-13 20:20:40 +00002851 char_u *arg = eap->arg;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00002852 int deep = 2;
2853
2854 if (eap->forceit)
2855 deep = -1;
2856 else if (vim_isdigit(*arg))
2857 {
2858 deep = getdigits(&arg);
2859 arg = skipwhite(arg);
2860 }
2861
2862 ex_unletlock(eap, arg, deep);
2863}
2864
2865/*
2866 * ":unlet", ":lockvar" and ":unlockvar" are quite similar.
2867 */
2868 static void
2869ex_unletlock(eap, argstart, deep)
2870 exarg_T *eap;
2871 char_u *argstart;
2872 int deep;
2873{
2874 char_u *arg = argstart;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002875 char_u *name_end;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002876 int error = FALSE;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00002877 lval_T lv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002878
2879 do
2880 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002881 /* Parse the name and find the end. */
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +00002882 name_end = get_lval(arg, NULL, &lv, TRUE, eap->skip || error, FALSE,
2883 FNE_CHECK_START);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002884 if (lv.ll_name == NULL)
2885 error = TRUE; /* error but continue parsing */
2886 if (name_end == NULL || (!vim_iswhite(*name_end)
2887 && !ends_excmd(*name_end)))
Bram Moolenaar071d4272004-06-13 20:20:40 +00002888 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002889 if (name_end != NULL)
2890 {
2891 emsg_severe = TRUE;
2892 EMSG(_(e_trailing));
2893 }
2894 if (!(eap->skip || error))
2895 clear_lval(&lv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002896 break;
2897 }
2898
2899 if (!error && !eap->skip)
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00002900 {
2901 if (eap->cmdidx == CMD_unlet)
2902 {
2903 if (do_unlet_var(&lv, name_end, eap->forceit) == FAIL)
2904 error = TRUE;
2905 }
2906 else
2907 {
2908 if (do_lock_var(&lv, name_end, deep,
2909 eap->cmdidx == CMD_lockvar) == FAIL)
2910 error = TRUE;
2911 }
2912 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00002913
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002914 if (!eap->skip)
2915 clear_lval(&lv);
2916
Bram Moolenaar071d4272004-06-13 20:20:40 +00002917 arg = skipwhite(name_end);
2918 } while (!ends_excmd(*arg));
2919
2920 eap->nextcmd = check_nextcmd(arg);
2921}
2922
Bram Moolenaar8c711452005-01-14 21:53:12 +00002923 static int
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002924do_unlet_var(lp, name_end, forceit)
Bram Moolenaar33570922005-01-25 22:26:29 +00002925 lval_T *lp;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002926 char_u *name_end;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002927 int forceit;
2928{
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002929 int ret = OK;
2930 int cc;
2931
2932 if (lp->ll_tv == NULL)
Bram Moolenaar8c711452005-01-14 21:53:12 +00002933 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002934 cc = *name_end;
2935 *name_end = NUL;
2936
2937 /* Normal name or expanded name. */
2938 if (check_changedtick(lp->ll_name))
2939 ret = FAIL;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00002940 else if (do_unlet(lp->ll_name, forceit) == FAIL)
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002941 ret = FAIL;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002942 *name_end = cc;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002943 }
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00002944 else if (tv_check_lock(lp->ll_tv->v_lock, lp->ll_name))
2945 return FAIL;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002946 else if (lp->ll_range)
2947 {
Bram Moolenaar33570922005-01-25 22:26:29 +00002948 listitem_T *li;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002949
2950 /* Delete a range of List items. */
2951 while (lp->ll_li != NULL && (lp->ll_empty2 || lp->ll_n2 >= lp->ll_n1))
2952 {
2953 li = lp->ll_li->li_next;
2954 listitem_remove(lp->ll_list, lp->ll_li);
2955 lp->ll_li = li;
2956 ++lp->ll_n1;
2957 }
2958 }
2959 else
2960 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002961 if (lp->ll_list != NULL)
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002962 /* unlet a List item. */
2963 listitem_remove(lp->ll_list, lp->ll_li);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002964 else
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002965 /* unlet a Dictionary item. */
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00002966 dictitem_remove(lp->ll_dict, lp->ll_di);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002967 }
2968
2969 return ret;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002970}
2971
Bram Moolenaar071d4272004-06-13 20:20:40 +00002972/*
2973 * "unlet" a variable. Return OK if it existed, FAIL if not.
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00002974 * When "forceit" is TRUE don't complain if the variable doesn't exist.
Bram Moolenaar071d4272004-06-13 20:20:40 +00002975 */
2976 int
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00002977do_unlet(name, forceit)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002978 char_u *name;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00002979 int forceit;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002980{
Bram Moolenaar33570922005-01-25 22:26:29 +00002981 hashtab_T *ht;
2982 hashitem_T *hi;
Bram Moolenaara7043832005-01-21 11:56:39 +00002983 char_u *varname;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002984
Bram Moolenaar33570922005-01-25 22:26:29 +00002985 ht = find_var_ht(name, &varname);
2986 if (ht != NULL && *varname != NUL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002987 {
Bram Moolenaar33570922005-01-25 22:26:29 +00002988 hi = hash_find(ht, varname);
2989 if (!HASHITEM_EMPTY(hi))
Bram Moolenaara7043832005-01-21 11:56:39 +00002990 {
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00002991 if (var_check_ro(HI2DI(hi)->di_flags, name))
2992 return FAIL;
2993 delete_var(ht, hi);
2994 return OK;
Bram Moolenaara7043832005-01-21 11:56:39 +00002995 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00002996 }
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00002997 if (forceit)
2998 return OK;
2999 EMSG2(_("E108: No such variable: \"%s\""), name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003000 return FAIL;
3001}
3002
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00003003/*
3004 * Lock or unlock variable indicated by "lp".
3005 * "deep" is the levels to go (-1 for unlimited);
3006 * "lock" is TRUE for ":lockvar", FALSE for ":unlockvar".
3007 */
3008 static int
3009do_lock_var(lp, name_end, deep, lock)
3010 lval_T *lp;
3011 char_u *name_end;
3012 int deep;
3013 int lock;
3014{
3015 int ret = OK;
3016 int cc;
3017 dictitem_T *di;
3018
3019 if (deep == 0) /* nothing to do */
3020 return OK;
3021
3022 if (lp->ll_tv == NULL)
3023 {
3024 cc = *name_end;
3025 *name_end = NUL;
3026
3027 /* Normal name or expanded name. */
3028 if (check_changedtick(lp->ll_name))
3029 ret = FAIL;
3030 else
3031 {
3032 di = find_var(lp->ll_name, NULL);
3033 if (di == NULL)
3034 ret = FAIL;
3035 else
3036 {
3037 if (lock)
3038 di->di_flags |= DI_FLAGS_LOCK;
3039 else
3040 di->di_flags &= ~DI_FLAGS_LOCK;
3041 item_lock(&di->di_tv, deep, lock);
3042 }
3043 }
3044 *name_end = cc;
3045 }
3046 else if (lp->ll_range)
3047 {
3048 listitem_T *li = lp->ll_li;
3049
3050 /* (un)lock a range of List items. */
3051 while (li != NULL && (lp->ll_empty2 || lp->ll_n2 >= lp->ll_n1))
3052 {
3053 item_lock(&li->li_tv, deep, lock);
3054 li = li->li_next;
3055 ++lp->ll_n1;
3056 }
3057 }
3058 else if (lp->ll_list != NULL)
3059 /* (un)lock a List item. */
3060 item_lock(&lp->ll_li->li_tv, deep, lock);
3061 else
3062 /* un(lock) a Dictionary item. */
3063 item_lock(&lp->ll_di->di_tv, deep, lock);
3064
3065 return ret;
3066}
3067
3068/*
3069 * Lock or unlock an item. "deep" is nr of levels to go.
3070 */
3071 static void
3072item_lock(tv, deep, lock)
3073 typval_T *tv;
3074 int deep;
3075 int lock;
3076{
3077 static int recurse = 0;
3078 list_T *l;
3079 listitem_T *li;
3080 dict_T *d;
3081 hashitem_T *hi;
3082 int todo;
3083
3084 if (recurse >= DICT_MAXNEST)
3085 {
3086 EMSG(_("E743: variable nested too deep for (un)lock"));
3087 return;
3088 }
3089 if (deep == 0)
3090 return;
3091 ++recurse;
3092
3093 /* lock/unlock the item itself */
3094 if (lock)
3095 tv->v_lock |= VAR_LOCKED;
3096 else
3097 tv->v_lock &= ~VAR_LOCKED;
3098
3099 switch (tv->v_type)
3100 {
3101 case VAR_LIST:
3102 if ((l = tv->vval.v_list) != NULL)
3103 {
3104 if (lock)
3105 l->lv_lock |= VAR_LOCKED;
3106 else
3107 l->lv_lock &= ~VAR_LOCKED;
3108 if (deep < 0 || deep > 1)
3109 /* recursive: lock/unlock the items the List contains */
3110 for (li = l->lv_first; li != NULL; li = li->li_next)
3111 item_lock(&li->li_tv, deep - 1, lock);
3112 }
3113 break;
3114 case VAR_DICT:
3115 if ((d = tv->vval.v_dict) != NULL)
3116 {
3117 if (lock)
3118 d->dv_lock |= VAR_LOCKED;
3119 else
3120 d->dv_lock &= ~VAR_LOCKED;
3121 if (deep < 0 || deep > 1)
3122 {
3123 /* recursive: lock/unlock the items the List contains */
3124 todo = d->dv_hashtab.ht_used;
3125 for (hi = d->dv_hashtab.ht_array; todo > 0; ++hi)
3126 {
3127 if (!HASHITEM_EMPTY(hi))
3128 {
3129 --todo;
3130 item_lock(&HI2DI(hi)->di_tv, deep - 1, lock);
3131 }
3132 }
3133 }
3134 }
3135 }
3136 --recurse;
3137}
3138
Bram Moolenaar071d4272004-06-13 20:20:40 +00003139#if (defined(FEAT_MENU) && defined(FEAT_MULTI_LANG)) || defined(PROTO)
3140/*
3141 * Delete all "menutrans_" variables.
3142 */
3143 void
3144del_menutrans_vars()
3145{
Bram Moolenaar33570922005-01-25 22:26:29 +00003146 hashitem_T *hi;
Bram Moolenaara7043832005-01-21 11:56:39 +00003147 int todo;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003148
Bram Moolenaar33570922005-01-25 22:26:29 +00003149 hash_lock(&globvarht);
3150 todo = globvarht.ht_used;
3151 for (hi = globvarht.ht_array; todo > 0 && !got_int; ++hi)
Bram Moolenaara7043832005-01-21 11:56:39 +00003152 {
3153 if (!HASHITEM_EMPTY(hi))
3154 {
3155 --todo;
Bram Moolenaar33570922005-01-25 22:26:29 +00003156 if (STRNCMP(HI2DI(hi)->di_key, "menutrans_", 10) == 0)
3157 delete_var(&globvarht, hi);
Bram Moolenaara7043832005-01-21 11:56:39 +00003158 }
3159 }
Bram Moolenaar33570922005-01-25 22:26:29 +00003160 hash_unlock(&globvarht);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003161}
3162#endif
3163
3164#if defined(FEAT_CMDL_COMPL) || defined(PROTO)
3165
3166/*
3167 * Local string buffer for the next two functions to store a variable name
3168 * with its prefix. Allocated in cat_prefix_varname(), freed later in
3169 * get_user_var_name().
3170 */
3171
3172static char_u *cat_prefix_varname __ARGS((int prefix, char_u *name));
3173
3174static char_u *varnamebuf = NULL;
3175static int varnamebuflen = 0;
3176
3177/*
3178 * Function to concatenate a prefix and a variable name.
3179 */
3180 static char_u *
3181cat_prefix_varname(prefix, name)
3182 int prefix;
3183 char_u *name;
3184{
3185 int len;
3186
3187 len = (int)STRLEN(name) + 3;
3188 if (len > varnamebuflen)
3189 {
3190 vim_free(varnamebuf);
3191 len += 10; /* some additional space */
3192 varnamebuf = alloc(len);
3193 if (varnamebuf == NULL)
3194 {
3195 varnamebuflen = 0;
3196 return NULL;
3197 }
3198 varnamebuflen = len;
3199 }
3200 *varnamebuf = prefix;
3201 varnamebuf[1] = ':';
3202 STRCPY(varnamebuf + 2, name);
3203 return varnamebuf;
3204}
3205
3206/*
3207 * Function given to ExpandGeneric() to obtain the list of user defined
3208 * (global/buffer/window/built-in) variable names.
3209 */
3210/*ARGSUSED*/
3211 char_u *
3212get_user_var_name(xp, idx)
3213 expand_T *xp;
3214 int idx;
3215{
Bram Moolenaar532c7802005-01-27 14:44:31 +00003216 static long_u gdone;
3217 static long_u bdone;
3218 static long_u wdone;
3219 static int vidx;
3220 static hashitem_T *hi;
3221 hashtab_T *ht;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003222
3223 if (idx == 0)
Bram Moolenaara7043832005-01-21 11:56:39 +00003224 gdone = bdone = wdone = vidx = 0;
Bram Moolenaar33570922005-01-25 22:26:29 +00003225
3226 /* Global variables */
3227 if (gdone < globvarht.ht_used)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003228 {
Bram Moolenaara7043832005-01-21 11:56:39 +00003229 if (gdone++ == 0)
Bram Moolenaar33570922005-01-25 22:26:29 +00003230 hi = globvarht.ht_array;
Bram Moolenaar532c7802005-01-27 14:44:31 +00003231 else
3232 ++hi;
Bram Moolenaara7043832005-01-21 11:56:39 +00003233 while (HASHITEM_EMPTY(hi))
3234 ++hi;
3235 if (STRNCMP("g:", xp->xp_pattern, 2) == 0)
3236 return cat_prefix_varname('g', hi->hi_key);
3237 return hi->hi_key;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003238 }
Bram Moolenaar33570922005-01-25 22:26:29 +00003239
3240 /* b: variables */
3241 ht = &curbuf->b_vars.dv_hashtab;
3242 if (bdone < ht->ht_used)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003243 {
Bram Moolenaara7043832005-01-21 11:56:39 +00003244 if (bdone++ == 0)
Bram Moolenaar33570922005-01-25 22:26:29 +00003245 hi = ht->ht_array;
Bram Moolenaar532c7802005-01-27 14:44:31 +00003246 else
3247 ++hi;
Bram Moolenaara7043832005-01-21 11:56:39 +00003248 while (HASHITEM_EMPTY(hi))
3249 ++hi;
3250 return cat_prefix_varname('b', hi->hi_key);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003251 }
Bram Moolenaar33570922005-01-25 22:26:29 +00003252 if (bdone == ht->ht_used)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003253 {
Bram Moolenaara7043832005-01-21 11:56:39 +00003254 ++bdone;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003255 return (char_u *)"b:changedtick";
3256 }
Bram Moolenaar33570922005-01-25 22:26:29 +00003257
3258 /* w: variables */
3259 ht = &curwin->w_vars.dv_hashtab;
3260 if (wdone < ht->ht_used)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003261 {
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +00003262 if (wdone++ == 0)
Bram Moolenaar33570922005-01-25 22:26:29 +00003263 hi = ht->ht_array;
Bram Moolenaar532c7802005-01-27 14:44:31 +00003264 else
3265 ++hi;
Bram Moolenaara7043832005-01-21 11:56:39 +00003266 while (HASHITEM_EMPTY(hi))
3267 ++hi;
3268 return cat_prefix_varname('w', hi->hi_key);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003269 }
Bram Moolenaar33570922005-01-25 22:26:29 +00003270
3271 /* v: variables */
3272 if (vidx < VV_LEN)
3273 return cat_prefix_varname('v', (char_u *)vimvars[vidx++].vv_name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003274
3275 vim_free(varnamebuf);
3276 varnamebuf = NULL;
3277 varnamebuflen = 0;
3278 return NULL;
3279}
3280
3281#endif /* FEAT_CMDL_COMPL */
3282
3283/*
3284 * types for expressions.
3285 */
3286typedef enum
3287{
3288 TYPE_UNKNOWN = 0
3289 , TYPE_EQUAL /* == */
3290 , TYPE_NEQUAL /* != */
3291 , TYPE_GREATER /* > */
3292 , TYPE_GEQUAL /* >= */
3293 , TYPE_SMALLER /* < */
3294 , TYPE_SEQUAL /* <= */
3295 , TYPE_MATCH /* =~ */
3296 , TYPE_NOMATCH /* !~ */
3297} exptype_T;
3298
3299/*
3300 * The "evaluate" argument: When FALSE, the argument is only parsed but not
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003301 * executed. The function may return OK, but the rettv will be of type
Bram Moolenaar071d4272004-06-13 20:20:40 +00003302 * VAR_UNKNOWN. The function still returns FAIL for a syntax error.
3303 */
3304
3305/*
3306 * Handle zero level expression.
3307 * This calls eval1() and handles error message and nextcmd.
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003308 * Put the result in "rettv" when returning OK and "evaluate" is TRUE.
Bram Moolenaar071d4272004-06-13 20:20:40 +00003309 * Return OK or FAIL.
3310 */
3311 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003312eval0(arg, rettv, nextcmd, evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003313 char_u *arg;
Bram Moolenaar33570922005-01-25 22:26:29 +00003314 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003315 char_u **nextcmd;
3316 int evaluate;
3317{
3318 int ret;
3319 char_u *p;
3320
3321 p = skipwhite(arg);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003322 ret = eval1(&p, rettv, evaluate);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003323 if (ret == FAIL || !ends_excmd(*p))
3324 {
3325 if (ret != FAIL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003326 clear_tv(rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003327 /*
3328 * Report the invalid expression unless the expression evaluation has
3329 * been cancelled due to an aborting error, an interrupt, or an
3330 * exception.
3331 */
3332 if (!aborting())
3333 EMSG2(_(e_invexpr2), arg);
3334 ret = FAIL;
3335 }
3336 if (nextcmd != NULL)
3337 *nextcmd = check_nextcmd(p);
3338
3339 return ret;
3340}
3341
3342/*
3343 * Handle top level expression:
3344 * expr1 ? expr0 : expr0
3345 *
3346 * "arg" must point to the first non-white of the expression.
3347 * "arg" is advanced to the next non-white after the recognized expression.
3348 *
3349 * Return OK or FAIL.
3350 */
3351 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003352eval1(arg, rettv, evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003353 char_u **arg;
Bram Moolenaar33570922005-01-25 22:26:29 +00003354 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003355 int evaluate;
3356{
3357 int result;
Bram Moolenaar33570922005-01-25 22:26:29 +00003358 typval_T var2;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003359
3360 /*
3361 * Get the first variable.
3362 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003363 if (eval2(arg, rettv, evaluate) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003364 return FAIL;
3365
3366 if ((*arg)[0] == '?')
3367 {
3368 result = FALSE;
3369 if (evaluate)
3370 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00003371 int error = FALSE;
3372
3373 if (get_tv_number_chk(rettv, &error) != 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003374 result = TRUE;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003375 clear_tv(rettv);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00003376 if (error)
3377 return FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003378 }
3379
3380 /*
3381 * Get the second variable.
3382 */
3383 *arg = skipwhite(*arg + 1);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003384 if (eval1(arg, rettv, evaluate && result) == FAIL) /* recursive! */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003385 return FAIL;
3386
3387 /*
3388 * Check for the ":".
3389 */
3390 if ((*arg)[0] != ':')
3391 {
3392 EMSG(_("E109: Missing ':' after '?'"));
3393 if (evaluate && result)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003394 clear_tv(rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003395 return FAIL;
3396 }
3397
3398 /*
3399 * Get the third variable.
3400 */
3401 *arg = skipwhite(*arg + 1);
3402 if (eval1(arg, &var2, evaluate && !result) == FAIL) /* recursive! */
3403 {
3404 if (evaluate && result)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003405 clear_tv(rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003406 return FAIL;
3407 }
3408 if (evaluate && !result)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003409 *rettv = var2;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003410 }
3411
3412 return OK;
3413}
3414
3415/*
3416 * Handle first level expression:
3417 * expr2 || expr2 || expr2 logical OR
3418 *
3419 * "arg" must point to the first non-white of the expression.
3420 * "arg" is advanced to the next non-white after the recognized expression.
3421 *
3422 * Return OK or FAIL.
3423 */
3424 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003425eval2(arg, rettv, evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003426 char_u **arg;
Bram Moolenaar33570922005-01-25 22:26:29 +00003427 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003428 int evaluate;
3429{
Bram Moolenaar33570922005-01-25 22:26:29 +00003430 typval_T var2;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003431 long result;
3432 int first;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00003433 int error = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003434
3435 /*
3436 * Get the first variable.
3437 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003438 if (eval3(arg, rettv, evaluate) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003439 return FAIL;
3440
3441 /*
3442 * Repeat until there is no following "||".
3443 */
3444 first = TRUE;
3445 result = FALSE;
3446 while ((*arg)[0] == '|' && (*arg)[1] == '|')
3447 {
3448 if (evaluate && first)
3449 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00003450 if (get_tv_number_chk(rettv, &error) != 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003451 result = TRUE;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003452 clear_tv(rettv);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00003453 if (error)
3454 return FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003455 first = FALSE;
3456 }
3457
3458 /*
3459 * Get the second variable.
3460 */
3461 *arg = skipwhite(*arg + 2);
3462 if (eval3(arg, &var2, evaluate && !result) == FAIL)
3463 return FAIL;
3464
3465 /*
3466 * Compute the result.
3467 */
3468 if (evaluate && !result)
3469 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00003470 if (get_tv_number_chk(&var2, &error) != 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003471 result = TRUE;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003472 clear_tv(&var2);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00003473 if (error)
3474 return FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003475 }
3476 if (evaluate)
3477 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003478 rettv->v_type = VAR_NUMBER;
3479 rettv->vval.v_number = result;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003480 }
3481 }
3482
3483 return OK;
3484}
3485
3486/*
3487 * Handle second level expression:
3488 * expr3 && expr3 && expr3 logical AND
3489 *
3490 * "arg" must point to the first non-white of the expression.
3491 * "arg" is advanced to the next non-white after the recognized expression.
3492 *
3493 * Return OK or FAIL.
3494 */
3495 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003496eval3(arg, rettv, evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003497 char_u **arg;
Bram Moolenaar33570922005-01-25 22:26:29 +00003498 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003499 int evaluate;
3500{
Bram Moolenaar33570922005-01-25 22:26:29 +00003501 typval_T var2;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003502 long result;
3503 int first;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00003504 int error = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003505
3506 /*
3507 * Get the first variable.
3508 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003509 if (eval4(arg, rettv, evaluate) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003510 return FAIL;
3511
3512 /*
3513 * Repeat until there is no following "&&".
3514 */
3515 first = TRUE;
3516 result = TRUE;
3517 while ((*arg)[0] == '&' && (*arg)[1] == '&')
3518 {
3519 if (evaluate && first)
3520 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00003521 if (get_tv_number_chk(rettv, &error) == 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003522 result = FALSE;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003523 clear_tv(rettv);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00003524 if (error)
3525 return FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003526 first = FALSE;
3527 }
3528
3529 /*
3530 * Get the second variable.
3531 */
3532 *arg = skipwhite(*arg + 2);
3533 if (eval4(arg, &var2, evaluate && result) == FAIL)
3534 return FAIL;
3535
3536 /*
3537 * Compute the result.
3538 */
3539 if (evaluate && result)
3540 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00003541 if (get_tv_number_chk(&var2, &error) == 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003542 result = FALSE;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003543 clear_tv(&var2);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00003544 if (error)
3545 return FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003546 }
3547 if (evaluate)
3548 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003549 rettv->v_type = VAR_NUMBER;
3550 rettv->vval.v_number = result;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003551 }
3552 }
3553
3554 return OK;
3555}
3556
3557/*
3558 * Handle third level expression:
3559 * var1 == var2
3560 * var1 =~ var2
3561 * var1 != var2
3562 * var1 !~ var2
3563 * var1 > var2
3564 * var1 >= var2
3565 * var1 < var2
3566 * var1 <= var2
Bram Moolenaar8a283e52005-01-06 23:28:25 +00003567 * var1 is var2
3568 * var1 isnot var2
Bram Moolenaar071d4272004-06-13 20:20:40 +00003569 *
3570 * "arg" must point to the first non-white of the expression.
3571 * "arg" is advanced to the next non-white after the recognized expression.
3572 *
3573 * Return OK or FAIL.
3574 */
3575 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003576eval4(arg, rettv, evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003577 char_u **arg;
Bram Moolenaar33570922005-01-25 22:26:29 +00003578 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003579 int evaluate;
3580{
Bram Moolenaar33570922005-01-25 22:26:29 +00003581 typval_T var2;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003582 char_u *p;
3583 int i;
3584 exptype_T type = TYPE_UNKNOWN;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00003585 int type_is = FALSE; /* TRUE for "is" and "isnot" */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003586 int len = 2;
3587 long n1, n2;
3588 char_u *s1, *s2;
3589 char_u buf1[NUMBUFLEN], buf2[NUMBUFLEN];
3590 regmatch_T regmatch;
3591 int ic;
3592 char_u *save_cpo;
3593
3594 /*
3595 * Get the first variable.
3596 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003597 if (eval5(arg, rettv, evaluate) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003598 return FAIL;
3599
3600 p = *arg;
3601 switch (p[0])
3602 {
3603 case '=': if (p[1] == '=')
3604 type = TYPE_EQUAL;
3605 else if (p[1] == '~')
3606 type = TYPE_MATCH;
3607 break;
3608 case '!': if (p[1] == '=')
3609 type = TYPE_NEQUAL;
3610 else if (p[1] == '~')
3611 type = TYPE_NOMATCH;
3612 break;
3613 case '>': if (p[1] != '=')
3614 {
3615 type = TYPE_GREATER;
3616 len = 1;
3617 }
3618 else
3619 type = TYPE_GEQUAL;
3620 break;
3621 case '<': if (p[1] != '=')
3622 {
3623 type = TYPE_SMALLER;
3624 len = 1;
3625 }
3626 else
3627 type = TYPE_SEQUAL;
3628 break;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00003629 case 'i': if (p[1] == 's')
3630 {
3631 if (p[2] == 'n' && p[3] == 'o' && p[4] == 't')
3632 len = 5;
3633 if (!vim_isIDc(p[len]))
3634 {
3635 type = len == 2 ? TYPE_EQUAL : TYPE_NEQUAL;
3636 type_is = TRUE;
3637 }
3638 }
3639 break;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003640 }
3641
3642 /*
3643 * If there is a comparitive operator, use it.
3644 */
3645 if (type != TYPE_UNKNOWN)
3646 {
3647 /* extra question mark appended: ignore case */
3648 if (p[len] == '?')
3649 {
3650 ic = TRUE;
3651 ++len;
3652 }
3653 /* extra '#' appended: match case */
3654 else if (p[len] == '#')
3655 {
3656 ic = FALSE;
3657 ++len;
3658 }
3659 /* nothing appened: use 'ignorecase' */
3660 else
3661 ic = p_ic;
3662
3663 /*
3664 * Get the second variable.
3665 */
3666 *arg = skipwhite(p + len);
3667 if (eval5(arg, &var2, evaluate) == FAIL)
3668 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003669 clear_tv(rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003670 return FAIL;
3671 }
3672
3673 if (evaluate)
3674 {
Bram Moolenaar8a283e52005-01-06 23:28:25 +00003675 if (type_is && rettv->v_type != var2.v_type)
3676 {
3677 /* For "is" a different type always means FALSE, for "notis"
3678 * it means TRUE. */
3679 n1 = (type == TYPE_NEQUAL);
3680 }
3681 else if (rettv->v_type == VAR_LIST || var2.v_type == VAR_LIST)
3682 {
3683 if (type_is)
3684 {
3685 n1 = (rettv->v_type == var2.v_type
3686 && rettv->vval.v_list == var2.vval.v_list);
3687 if (type == TYPE_NEQUAL)
3688 n1 = !n1;
3689 }
3690 else if (rettv->v_type != var2.v_type
3691 || (type != TYPE_EQUAL && type != TYPE_NEQUAL))
3692 {
3693 if (rettv->v_type != var2.v_type)
Bram Moolenaare49b69a2005-01-08 16:11:57 +00003694 EMSG(_("E691: Can only compare List with List"));
Bram Moolenaar8a283e52005-01-06 23:28:25 +00003695 else
Bram Moolenaare49b69a2005-01-08 16:11:57 +00003696 EMSG(_("E692: Invalid operation for Lists"));
Bram Moolenaar8a283e52005-01-06 23:28:25 +00003697 clear_tv(rettv);
3698 clear_tv(&var2);
3699 return FAIL;
3700 }
3701 else
3702 {
3703 /* Compare two Lists for being equal or unequal. */
3704 n1 = list_equal(rettv->vval.v_list, var2.vval.v_list, ic);
3705 if (type == TYPE_NEQUAL)
3706 n1 = !n1;
3707 }
3708 }
3709
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00003710 else if (rettv->v_type == VAR_DICT || var2.v_type == VAR_DICT)
3711 {
3712 if (type_is)
3713 {
3714 n1 = (rettv->v_type == var2.v_type
3715 && rettv->vval.v_dict == var2.vval.v_dict);
3716 if (type == TYPE_NEQUAL)
3717 n1 = !n1;
3718 }
3719 else if (rettv->v_type != var2.v_type
3720 || (type != TYPE_EQUAL && type != TYPE_NEQUAL))
3721 {
3722 if (rettv->v_type != var2.v_type)
3723 EMSG(_("E735: Can only compare Dictionary with Dictionary"));
3724 else
3725 EMSG(_("E736: Invalid operation for Dictionary"));
3726 clear_tv(rettv);
3727 clear_tv(&var2);
3728 return FAIL;
3729 }
3730 else
3731 {
3732 /* Compare two Dictionaries for being equal or unequal. */
3733 n1 = dict_equal(rettv->vval.v_dict, var2.vval.v_dict, ic);
3734 if (type == TYPE_NEQUAL)
3735 n1 = !n1;
3736 }
3737 }
3738
Bram Moolenaar8a283e52005-01-06 23:28:25 +00003739 else if (rettv->v_type == VAR_FUNC || var2.v_type == VAR_FUNC)
3740 {
3741 if (rettv->v_type != var2.v_type
3742 || (type != TYPE_EQUAL && type != TYPE_NEQUAL))
3743 {
3744 if (rettv->v_type != var2.v_type)
Bram Moolenaare49b69a2005-01-08 16:11:57 +00003745 EMSG(_("E693: Can only compare Funcref with Funcref"));
Bram Moolenaar8a283e52005-01-06 23:28:25 +00003746 else
Bram Moolenaare49b69a2005-01-08 16:11:57 +00003747 EMSG(_("E694: Invalid operation for Funcrefs"));
Bram Moolenaar8a283e52005-01-06 23:28:25 +00003748 clear_tv(rettv);
3749 clear_tv(&var2);
3750 return FAIL;
3751 }
3752 else
3753 {
3754 /* Compare two Funcrefs for being equal or unequal. */
3755 if (rettv->vval.v_string == NULL
3756 || var2.vval.v_string == NULL)
3757 n1 = FALSE;
3758 else
3759 n1 = STRCMP(rettv->vval.v_string,
3760 var2.vval.v_string) == 0;
3761 if (type == TYPE_NEQUAL)
3762 n1 = !n1;
3763 }
3764 }
3765
Bram Moolenaar071d4272004-06-13 20:20:40 +00003766 /*
3767 * If one of the two variables is a number, compare as a number.
3768 * When using "=~" or "!~", always compare as string.
3769 */
Bram Moolenaar8a283e52005-01-06 23:28:25 +00003770 else if ((rettv->v_type == VAR_NUMBER || var2.v_type == VAR_NUMBER)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003771 && type != TYPE_MATCH && type != TYPE_NOMATCH)
3772 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003773 n1 = get_tv_number(rettv);
3774 n2 = get_tv_number(&var2);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003775 switch (type)
3776 {
3777 case TYPE_EQUAL: n1 = (n1 == n2); break;
3778 case TYPE_NEQUAL: n1 = (n1 != n2); break;
3779 case TYPE_GREATER: n1 = (n1 > n2); break;
3780 case TYPE_GEQUAL: n1 = (n1 >= n2); break;
3781 case TYPE_SMALLER: n1 = (n1 < n2); break;
3782 case TYPE_SEQUAL: n1 = (n1 <= n2); break;
3783 case TYPE_UNKNOWN:
3784 case TYPE_MATCH:
3785 case TYPE_NOMATCH: break; /* avoid gcc warning */
3786 }
3787 }
3788 else
3789 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003790 s1 = get_tv_string_buf(rettv, buf1);
3791 s2 = get_tv_string_buf(&var2, buf2);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003792 if (type != TYPE_MATCH && type != TYPE_NOMATCH)
3793 i = ic ? MB_STRICMP(s1, s2) : STRCMP(s1, s2);
3794 else
3795 i = 0;
3796 n1 = FALSE;
3797 switch (type)
3798 {
3799 case TYPE_EQUAL: n1 = (i == 0); break;
3800 case TYPE_NEQUAL: n1 = (i != 0); break;
3801 case TYPE_GREATER: n1 = (i > 0); break;
3802 case TYPE_GEQUAL: n1 = (i >= 0); break;
3803 case TYPE_SMALLER: n1 = (i < 0); break;
3804 case TYPE_SEQUAL: n1 = (i <= 0); break;
3805
3806 case TYPE_MATCH:
3807 case TYPE_NOMATCH:
3808 /* avoid 'l' flag in 'cpoptions' */
3809 save_cpo = p_cpo;
3810 p_cpo = (char_u *)"";
3811 regmatch.regprog = vim_regcomp(s2,
3812 RE_MAGIC + RE_STRING);
3813 regmatch.rm_ic = ic;
3814 if (regmatch.regprog != NULL)
3815 {
3816 n1 = vim_regexec_nl(&regmatch, s1, (colnr_T)0);
3817 vim_free(regmatch.regprog);
3818 if (type == TYPE_NOMATCH)
3819 n1 = !n1;
3820 }
3821 p_cpo = save_cpo;
3822 break;
3823
3824 case TYPE_UNKNOWN: break; /* avoid gcc warning */
3825 }
3826 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003827 clear_tv(rettv);
3828 clear_tv(&var2);
3829 rettv->v_type = VAR_NUMBER;
3830 rettv->vval.v_number = n1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003831 }
3832 }
3833
3834 return OK;
3835}
3836
3837/*
3838 * Handle fourth level expression:
3839 * + number addition
3840 * - number subtraction
3841 * . string concatenation
3842 *
3843 * "arg" must point to the first non-white of the expression.
3844 * "arg" is advanced to the next non-white after the recognized expression.
3845 *
3846 * Return OK or FAIL.
3847 */
3848 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003849eval5(arg, rettv, evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003850 char_u **arg;
Bram Moolenaar33570922005-01-25 22:26:29 +00003851 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003852 int evaluate;
3853{
Bram Moolenaar33570922005-01-25 22:26:29 +00003854 typval_T var2;
3855 typval_T var3;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003856 int op;
3857 long n1, n2;
3858 char_u *s1, *s2;
3859 char_u buf1[NUMBUFLEN], buf2[NUMBUFLEN];
3860 char_u *p;
3861
3862 /*
3863 * Get the first variable.
3864 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003865 if (eval6(arg, rettv, evaluate) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003866 return FAIL;
3867
3868 /*
3869 * Repeat computing, until no '+', '-' or '.' is following.
3870 */
3871 for (;;)
3872 {
3873 op = **arg;
3874 if (op != '+' && op != '-' && op != '.')
3875 break;
3876
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00003877 if (op != '+' || rettv->v_type != VAR_LIST)
3878 {
3879 /* For "list + ...", an illegal use of the first operand as
3880 * a number cannot be determined before evaluating the 2nd
3881 * operand: if this is also a list, all is ok.
3882 * For "something . ...", "something - ..." or "non-list + ...",
3883 * we know that the first operand needs to be a string or number
3884 * without evaluating the 2nd operand. So check before to avoid
3885 * side effects after an error. */
3886 if (evaluate && get_tv_string_chk(rettv) == NULL)
3887 {
3888 clear_tv(rettv);
3889 return FAIL;
3890 }
3891 }
3892
Bram Moolenaar071d4272004-06-13 20:20:40 +00003893 /*
3894 * Get the second variable.
3895 */
3896 *arg = skipwhite(*arg + 1);
3897 if (eval6(arg, &var2, evaluate) == FAIL)
3898 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003899 clear_tv(rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003900 return FAIL;
3901 }
3902
3903 if (evaluate)
3904 {
3905 /*
3906 * Compute the result.
3907 */
3908 if (op == '.')
3909 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00003910 s1 = get_tv_string_buf(rettv, buf1); /* already checked */
3911 s2 = get_tv_string_buf_chk(&var2, buf2);
3912 if (s2 == NULL) /* type error ? */
3913 {
3914 clear_tv(rettv);
3915 clear_tv(&var2);
3916 return FAIL;
3917 }
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00003918 p = concat_str(s1, s2);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003919 clear_tv(rettv);
3920 rettv->v_type = VAR_STRING;
3921 rettv->vval.v_string = p;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003922 }
Bram Moolenaare9a41262005-01-15 22:18:47 +00003923 else if (op == '+' && rettv->v_type == VAR_LIST
3924 && var2.v_type == VAR_LIST)
Bram Moolenaar8a283e52005-01-06 23:28:25 +00003925 {
3926 /* concatenate Lists */
3927 if (list_concat(rettv->vval.v_list, var2.vval.v_list,
3928 &var3) == FAIL)
3929 {
3930 clear_tv(rettv);
3931 clear_tv(&var2);
3932 return FAIL;
3933 }
3934 clear_tv(rettv);
3935 *rettv = var3;
3936 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00003937 else
3938 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00003939 int error = FALSE;
3940
3941 n1 = get_tv_number_chk(rettv, &error);
3942 if (error)
3943 {
3944 /* This can only happen for "list + non-list".
3945 * For "non-list + ..." or "something - ...", we returned
3946 * before evaluating the 2nd operand. */
3947 clear_tv(rettv);
3948 return FAIL;
3949 }
3950 n2 = get_tv_number_chk(&var2, &error);
3951 if (error)
3952 {
3953 clear_tv(rettv);
3954 clear_tv(&var2);
3955 return FAIL;
3956 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003957 clear_tv(rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003958 if (op == '+')
3959 n1 = n1 + n2;
3960 else
3961 n1 = n1 - n2;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003962 rettv->v_type = VAR_NUMBER;
3963 rettv->vval.v_number = n1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003964 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003965 clear_tv(&var2);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003966 }
3967 }
3968 return OK;
3969}
3970
3971/*
3972 * Handle fifth level expression:
3973 * * number multiplication
3974 * / number division
3975 * % number modulo
3976 *
3977 * "arg" must point to the first non-white of the expression.
3978 * "arg" is advanced to the next non-white after the recognized expression.
3979 *
3980 * Return OK or FAIL.
3981 */
3982 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003983eval6(arg, rettv, evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003984 char_u **arg;
Bram Moolenaar33570922005-01-25 22:26:29 +00003985 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003986 int evaluate;
3987{
Bram Moolenaar33570922005-01-25 22:26:29 +00003988 typval_T var2;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003989 int op;
3990 long n1, n2;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00003991 int error = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003992
3993 /*
3994 * Get the first variable.
3995 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003996 if (eval7(arg, rettv, evaluate) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003997 return FAIL;
3998
3999 /*
4000 * Repeat computing, until no '*', '/' or '%' is following.
4001 */
4002 for (;;)
4003 {
4004 op = **arg;
4005 if (op != '*' && op != '/' && op != '%')
4006 break;
4007
4008 if (evaluate)
4009 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004010 n1 = get_tv_number_chk(rettv, &error);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004011 clear_tv(rettv);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004012 if (error)
4013 return FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004014 }
4015 else
4016 n1 = 0;
4017
4018 /*
4019 * Get the second variable.
4020 */
4021 *arg = skipwhite(*arg + 1);
4022 if (eval7(arg, &var2, evaluate) == FAIL)
4023 return FAIL;
4024
4025 if (evaluate)
4026 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004027 n2 = get_tv_number_chk(&var2, &error);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004028 clear_tv(&var2);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004029 if (error)
4030 return FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004031
4032 /*
4033 * Compute the result.
4034 */
4035 if (op == '*')
4036 n1 = n1 * n2;
4037 else if (op == '/')
4038 {
4039 if (n2 == 0) /* give an error message? */
4040 n1 = 0x7fffffffL;
4041 else
4042 n1 = n1 / n2;
4043 }
4044 else
4045 {
4046 if (n2 == 0) /* give an error message? */
4047 n1 = 0;
4048 else
4049 n1 = n1 % n2;
4050 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004051 rettv->v_type = VAR_NUMBER;
4052 rettv->vval.v_number = n1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004053 }
4054 }
4055
4056 return OK;
4057}
4058
4059/*
4060 * Handle sixth level expression:
4061 * number number constant
4062 * "string" string contstant
4063 * 'string' literal string contstant
4064 * &option-name option value
4065 * @r register contents
4066 * identifier variable value
4067 * function() function call
4068 * $VAR environment variable
4069 * (expression) nested expression
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00004070 * [expr, expr] List
4071 * {key: val, key: val} Dictionary
Bram Moolenaar071d4272004-06-13 20:20:40 +00004072 *
4073 * Also handle:
4074 * ! in front logical NOT
4075 * - in front unary minus
4076 * + in front unary plus (ignored)
Bram Moolenaar8c711452005-01-14 21:53:12 +00004077 * trailing [] subscript in String or List
4078 * trailing .name entry in Dictionary
Bram Moolenaar071d4272004-06-13 20:20:40 +00004079 *
4080 * "arg" must point to the first non-white of the expression.
4081 * "arg" is advanced to the next non-white after the recognized expression.
4082 *
4083 * Return OK or FAIL.
4084 */
4085 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004086eval7(arg, rettv, evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004087 char_u **arg;
Bram Moolenaar33570922005-01-25 22:26:29 +00004088 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004089 int evaluate;
4090{
Bram Moolenaar071d4272004-06-13 20:20:40 +00004091 long n;
4092 int len;
4093 char_u *s;
4094 int val;
4095 char_u *start_leader, *end_leader;
4096 int ret = OK;
4097 char_u *alias;
4098
4099 /*
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004100 * Initialise variable so that clear_tv() can't mistake this for a
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004101 * string and free a string that isn't there.
Bram Moolenaar071d4272004-06-13 20:20:40 +00004102 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004103 rettv->v_type = VAR_UNKNOWN;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004104
4105 /*
4106 * Skip '!' and '-' characters. They are handled later.
4107 */
4108 start_leader = *arg;
4109 while (**arg == '!' || **arg == '-' || **arg == '+')
4110 *arg = skipwhite(*arg + 1);
4111 end_leader = *arg;
4112
4113 switch (**arg)
4114 {
4115 /*
4116 * Number constant.
4117 */
4118 case '0':
4119 case '1':
4120 case '2':
4121 case '3':
4122 case '4':
4123 case '5':
4124 case '6':
4125 case '7':
4126 case '8':
4127 case '9':
4128 vim_str2nr(*arg, NULL, &len, TRUE, TRUE, &n, NULL);
4129 *arg += len;
4130 if (evaluate)
4131 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004132 rettv->v_type = VAR_NUMBER;
4133 rettv->vval.v_number = n;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004134 }
4135 break;
4136
4137 /*
4138 * String constant: "string".
4139 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004140 case '"': ret = get_string_tv(arg, rettv, evaluate);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004141 break;
4142
4143 /*
Bram Moolenaar8c711452005-01-14 21:53:12 +00004144 * Literal string constant: 'str''ing'.
Bram Moolenaar071d4272004-06-13 20:20:40 +00004145 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004146 case '\'': ret = get_lit_string_tv(arg, rettv, evaluate);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004147 break;
4148
4149 /*
4150 * List: [expr, expr]
4151 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004152 case '[': ret = get_list_tv(arg, rettv, evaluate);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004153 break;
4154
4155 /*
Bram Moolenaar8c711452005-01-14 21:53:12 +00004156 * Dictionary: {key: val, key: val}
4157 */
4158 case '{': ret = get_dict_tv(arg, rettv, evaluate);
4159 break;
4160
4161 /*
Bram Moolenaare9a41262005-01-15 22:18:47 +00004162 * Option value: &name
Bram Moolenaar071d4272004-06-13 20:20:40 +00004163 */
Bram Moolenaare9a41262005-01-15 22:18:47 +00004164 case '&': ret = get_option_tv(arg, rettv, evaluate);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004165 break;
4166
4167 /*
4168 * Environment variable: $VAR.
4169 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004170 case '$': ret = get_env_tv(arg, rettv, evaluate);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004171 break;
4172
4173 /*
4174 * Register contents: @r.
4175 */
4176 case '@': ++*arg;
4177 if (evaluate)
4178 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004179 rettv->v_type = VAR_STRING;
Bram Moolenaar92124a32005-06-17 22:03:40 +00004180 rettv->vval.v_string = get_reg_contents(**arg, TRUE, TRUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004181 }
4182 if (**arg != NUL)
4183 ++*arg;
4184 break;
4185
4186 /*
4187 * nested expression: (expression).
4188 */
4189 case '(': *arg = skipwhite(*arg + 1);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004190 ret = eval1(arg, rettv, evaluate); /* recursive! */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004191 if (**arg == ')')
4192 ++*arg;
4193 else if (ret == OK)
4194 {
4195 EMSG(_("E110: Missing ')'"));
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004196 clear_tv(rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004197 ret = FAIL;
4198 }
4199 break;
4200
Bram Moolenaar8c711452005-01-14 21:53:12 +00004201 default: ret = NOTDONE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004202 break;
4203 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00004204
4205 if (ret == NOTDONE)
4206 {
4207 /*
4208 * Must be a variable or function name.
4209 * Can also be a curly-braces kind of name: {expr}.
4210 */
4211 s = *arg;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00004212 len = get_name_len(arg, &alias, evaluate, TRUE);
Bram Moolenaar8c711452005-01-14 21:53:12 +00004213 if (alias != NULL)
4214 s = alias;
4215
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00004216 if (len <= 0)
Bram Moolenaar8c711452005-01-14 21:53:12 +00004217 ret = FAIL;
4218 else
4219 {
4220 if (**arg == '(') /* recursive! */
4221 {
4222 /* If "s" is the name of a variable of type VAR_FUNC
4223 * use its contents. */
4224 s = deref_func_name(s, &len);
4225
4226 /* Invoke the function. */
4227 ret = get_func_tv(s, len, rettv, arg,
4228 curwin->w_cursor.lnum, curwin->w_cursor.lnum,
Bram Moolenaare9a41262005-01-15 22:18:47 +00004229 &len, evaluate, NULL);
Bram Moolenaar8c711452005-01-14 21:53:12 +00004230 /* Stop the expression evaluation when immediately
4231 * aborting on error, or when an interrupt occurred or
4232 * an exception was thrown but not caught. */
4233 if (aborting())
4234 {
4235 if (ret == OK)
4236 clear_tv(rettv);
4237 ret = FAIL;
4238 }
4239 }
4240 else if (evaluate)
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00004241 ret = get_var_tv(s, len, rettv, TRUE);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00004242 else
4243 ret = OK;
Bram Moolenaar8c711452005-01-14 21:53:12 +00004244 }
4245
4246 if (alias != NULL)
4247 vim_free(alias);
4248 }
4249
Bram Moolenaar071d4272004-06-13 20:20:40 +00004250 *arg = skipwhite(*arg);
4251
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00004252 /* Handle following '[', '(' and '.' for expr[expr], expr.name,
4253 * expr(expr). */
4254 if (ret == OK)
4255 ret = handle_subscript(arg, rettv, evaluate, TRUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004256
4257 /*
4258 * Apply logical NOT and unary '-', from right to left, ignore '+'.
4259 */
4260 if (ret == OK && evaluate && end_leader > start_leader)
4261 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004262 int error = FALSE;
4263
4264 val = get_tv_number_chk(rettv, &error);
4265 if (error)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004266 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004267 clear_tv(rettv);
4268 ret = FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004269 }
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004270 else
4271 {
4272 while (end_leader > start_leader)
4273 {
4274 --end_leader;
4275 if (*end_leader == '!')
4276 val = !val;
4277 else if (*end_leader == '-')
4278 val = -val;
4279 }
4280 clear_tv(rettv);
4281 rettv->v_type = VAR_NUMBER;
4282 rettv->vval.v_number = val;
4283 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004284 }
4285
4286 return ret;
4287}
4288
4289/*
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004290 * Evaluate an "[expr]" or "[expr:expr]" index.
4291 * "*arg" points to the '['.
4292 * Returns FAIL or OK. "*arg" is advanced to after the ']'.
4293 */
4294 static int
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00004295eval_index(arg, rettv, evaluate, verbose)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004296 char_u **arg;
Bram Moolenaar33570922005-01-25 22:26:29 +00004297 typval_T *rettv;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004298 int evaluate;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00004299 int verbose; /* give error messages */
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004300{
4301 int empty1 = FALSE, empty2 = FALSE;
Bram Moolenaar33570922005-01-25 22:26:29 +00004302 typval_T var1, var2;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004303 long n1, n2 = 0;
Bram Moolenaar8c711452005-01-14 21:53:12 +00004304 long len = -1;
4305 int range = FALSE;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004306 char_u *s;
Bram Moolenaar8c711452005-01-14 21:53:12 +00004307 char_u *key = NULL;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004308
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004309 if (rettv->v_type == VAR_FUNC)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004310 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00004311 if (verbose)
4312 EMSG(_("E695: Cannot index a Funcref"));
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004313 return FAIL;
4314 }
4315
Bram Moolenaar8c711452005-01-14 21:53:12 +00004316 if (**arg == '.')
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004317 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00004318 /*
4319 * dict.name
4320 */
4321 key = *arg + 1;
4322 for (len = 0; ASCII_ISALNUM(key[len]) || key[len] == '_'; ++len)
4323 ;
4324 if (len == 0)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004325 return FAIL;
Bram Moolenaar8c711452005-01-14 21:53:12 +00004326 *arg = skipwhite(key + len);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004327 }
4328 else
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004329 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00004330 /*
4331 * something[idx]
4332 *
4333 * Get the (first) variable from inside the [].
4334 */
4335 *arg = skipwhite(*arg + 1);
4336 if (**arg == ':')
4337 empty1 = TRUE;
4338 else if (eval1(arg, &var1, evaluate) == FAIL) /* recursive! */
4339 return FAIL;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004340 else if (evaluate && get_tv_string_chk(&var1) == NULL)
4341 {
4342 /* not a number or string */
4343 clear_tv(&var1);
4344 return FAIL;
4345 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00004346
4347 /*
4348 * Get the second variable from inside the [:].
4349 */
4350 if (**arg == ':')
4351 {
4352 range = TRUE;
4353 *arg = skipwhite(*arg + 1);
4354 if (**arg == ']')
4355 empty2 = TRUE;
4356 else if (eval1(arg, &var2, evaluate) == FAIL) /* recursive! */
4357 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004358 if (!empty1)
4359 clear_tv(&var1);
4360 return FAIL;
4361 }
4362 else if (evaluate && get_tv_string_chk(&var2) == NULL)
4363 {
4364 /* not a number or string */
4365 if (!empty1)
4366 clear_tv(&var1);
4367 clear_tv(&var2);
Bram Moolenaar8c711452005-01-14 21:53:12 +00004368 return FAIL;
4369 }
4370 }
4371
4372 /* Check for the ']'. */
4373 if (**arg != ']')
4374 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00004375 if (verbose)
4376 EMSG(_(e_missbrac));
Bram Moolenaar8c711452005-01-14 21:53:12 +00004377 clear_tv(&var1);
4378 if (range)
4379 clear_tv(&var2);
4380 return FAIL;
4381 }
4382 *arg = skipwhite(*arg + 1); /* skip the ']' */
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004383 }
4384
4385 if (evaluate)
4386 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00004387 n1 = 0;
4388 if (!empty1 && rettv->v_type != VAR_DICT)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004389 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004390 n1 = get_tv_number(&var1);
4391 clear_tv(&var1);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004392 }
4393 if (range)
4394 {
4395 if (empty2)
4396 n2 = -1;
4397 else
4398 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004399 n2 = get_tv_number(&var2);
4400 clear_tv(&var2);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004401 }
4402 }
4403
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004404 switch (rettv->v_type)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004405 {
4406 case VAR_NUMBER:
4407 case VAR_STRING:
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004408 s = get_tv_string(rettv);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004409 len = (long)STRLEN(s);
4410 if (range)
4411 {
4412 /* The resulting variable is a substring. If the indexes
4413 * are out of range the result is empty. */
4414 if (n1 < 0)
4415 {
4416 n1 = len + n1;
4417 if (n1 < 0)
4418 n1 = 0;
4419 }
4420 if (n2 < 0)
4421 n2 = len + n2;
4422 else if (n2 >= len)
4423 n2 = len;
4424 if (n1 >= len || n2 < 0 || n1 > n2)
4425 s = NULL;
4426 else
4427 s = vim_strnsave(s + n1, (int)(n2 - n1 + 1));
4428 }
4429 else
4430 {
4431 /* The resulting variable is a string of a single
4432 * character. If the index is too big or negative the
4433 * result is empty. */
4434 if (n1 >= len || n1 < 0)
4435 s = NULL;
4436 else
4437 s = vim_strnsave(s + n1, 1);
4438 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004439 clear_tv(rettv);
4440 rettv->v_type = VAR_STRING;
4441 rettv->vval.v_string = s;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004442 break;
4443
4444 case VAR_LIST:
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004445 len = list_len(rettv->vval.v_list);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004446 if (n1 < 0)
4447 n1 = len + n1;
4448 if (!empty1 && (n1 < 0 || n1 >= len))
4449 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00004450 if (verbose)
4451 EMSGN(_(e_listidx), n1);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004452 return FAIL;
4453 }
4454 if (range)
4455 {
Bram Moolenaar33570922005-01-25 22:26:29 +00004456 list_T *l;
4457 listitem_T *item;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004458
4459 if (n2 < 0)
4460 n2 = len + n2;
Bram Moolenaar8c711452005-01-14 21:53:12 +00004461 if (!empty2 && (n2 < 0 || n2 >= len || n2 + 1 < n1))
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004462 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00004463 if (verbose)
4464 EMSGN(_(e_listidx), n2);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004465 return FAIL;
4466 }
4467 l = list_alloc();
4468 if (l == NULL)
4469 return FAIL;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004470 for (item = list_find(rettv->vval.v_list, n1);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004471 n1 <= n2; ++n1)
4472 {
4473 if (list_append_tv(l, &item->li_tv) == FAIL)
4474 {
4475 list_free(l);
4476 return FAIL;
4477 }
4478 item = item->li_next;
4479 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004480 clear_tv(rettv);
4481 rettv->v_type = VAR_LIST;
4482 rettv->vval.v_list = l;
Bram Moolenaar0d660222005-01-07 21:51:51 +00004483 ++l->lv_refcount;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004484 }
4485 else
4486 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004487 copy_tv(&list_find(rettv->vval.v_list, n1)->li_tv,
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004488 &var1);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004489 clear_tv(rettv);
4490 *rettv = var1;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004491 }
4492 break;
Bram Moolenaar8c711452005-01-14 21:53:12 +00004493
4494 case VAR_DICT:
4495 if (range)
4496 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00004497 if (verbose)
4498 EMSG(_(e_dictrange));
Bram Moolenaar8c711452005-01-14 21:53:12 +00004499 if (len == -1)
4500 clear_tv(&var1);
4501 return FAIL;
4502 }
4503 {
Bram Moolenaar33570922005-01-25 22:26:29 +00004504 dictitem_T *item;
Bram Moolenaar8c711452005-01-14 21:53:12 +00004505
4506 if (len == -1)
4507 {
4508 key = get_tv_string(&var1);
4509 if (*key == NUL)
4510 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00004511 if (verbose)
4512 EMSG(_(e_emptykey));
Bram Moolenaar8c711452005-01-14 21:53:12 +00004513 clear_tv(&var1);
4514 return FAIL;
4515 }
4516 }
4517
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00004518 item = dict_find(rettv->vval.v_dict, key, (int)len);
Bram Moolenaar8c711452005-01-14 21:53:12 +00004519
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00004520 if (item == NULL && verbose)
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00004521 EMSG2(_(e_dictkey), key);
Bram Moolenaar8c711452005-01-14 21:53:12 +00004522 if (len == -1)
4523 clear_tv(&var1);
4524 if (item == NULL)
4525 return FAIL;
4526
4527 copy_tv(&item->di_tv, &var1);
4528 clear_tv(rettv);
4529 *rettv = var1;
4530 }
4531 break;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004532 }
4533 }
4534
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004535 return OK;
4536}
4537
4538/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00004539 * Get an option value.
4540 * "arg" points to the '&' or '+' before the option name.
4541 * "arg" is advanced to character after the option name.
4542 * Return OK or FAIL.
4543 */
4544 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004545get_option_tv(arg, rettv, evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004546 char_u **arg;
Bram Moolenaar33570922005-01-25 22:26:29 +00004547 typval_T *rettv; /* when NULL, only check if option exists */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004548 int evaluate;
4549{
4550 char_u *option_end;
4551 long numval;
4552 char_u *stringval;
4553 int opt_type;
4554 int c;
4555 int working = (**arg == '+'); /* has("+option") */
4556 int ret = OK;
4557 int opt_flags;
4558
4559 /*
4560 * Isolate the option name and find its value.
4561 */
4562 option_end = find_option_end(arg, &opt_flags);
4563 if (option_end == NULL)
4564 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004565 if (rettv != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004566 EMSG2(_("E112: Option name missing: %s"), *arg);
4567 return FAIL;
4568 }
4569
4570 if (!evaluate)
4571 {
4572 *arg = option_end;
4573 return OK;
4574 }
4575
4576 c = *option_end;
4577 *option_end = NUL;
4578 opt_type = get_option_value(*arg, &numval,
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004579 rettv == NULL ? NULL : &stringval, opt_flags);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004580
4581 if (opt_type == -3) /* invalid name */
4582 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004583 if (rettv != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004584 EMSG2(_("E113: Unknown option: %s"), *arg);
4585 ret = FAIL;
4586 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004587 else if (rettv != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004588 {
4589 if (opt_type == -2) /* hidden string option */
4590 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004591 rettv->v_type = VAR_STRING;
4592 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004593 }
4594 else if (opt_type == -1) /* hidden number option */
4595 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004596 rettv->v_type = VAR_NUMBER;
4597 rettv->vval.v_number = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004598 }
4599 else if (opt_type == 1) /* number option */
4600 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004601 rettv->v_type = VAR_NUMBER;
4602 rettv->vval.v_number = numval;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004603 }
4604 else /* string option */
4605 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004606 rettv->v_type = VAR_STRING;
4607 rettv->vval.v_string = stringval;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004608 }
4609 }
4610 else if (working && (opt_type == -2 || opt_type == -1))
4611 ret = FAIL;
4612
4613 *option_end = c; /* put back for error messages */
4614 *arg = option_end;
4615
4616 return ret;
4617}
4618
4619/*
4620 * Allocate a variable for a string constant.
4621 * Return OK or FAIL.
4622 */
4623 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004624get_string_tv(arg, rettv, evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004625 char_u **arg;
Bram Moolenaar33570922005-01-25 22:26:29 +00004626 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004627 int evaluate;
4628{
4629 char_u *p;
4630 char_u *name;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004631 int extra = 0;
4632
4633 /*
4634 * Find the end of the string, skipping backslashed characters.
4635 */
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00004636 for (p = *arg + 1; *p != NUL && *p != '"'; mb_ptr_adv(p))
Bram Moolenaar071d4272004-06-13 20:20:40 +00004637 {
4638 if (*p == '\\' && p[1] != NUL)
4639 {
4640 ++p;
4641 /* A "\<x>" form occupies at least 4 characters, and produces up
4642 * to 6 characters: reserve space for 2 extra */
4643 if (*p == '<')
4644 extra += 2;
4645 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004646 }
4647
4648 if (*p != '"')
4649 {
4650 EMSG2(_("E114: Missing quote: %s"), *arg);
4651 return FAIL;
4652 }
4653
4654 /* If only parsing, set *arg and return here */
4655 if (!evaluate)
4656 {
4657 *arg = p + 1;
4658 return OK;
4659 }
4660
4661 /*
4662 * Copy the string into allocated memory, handling backslashed
4663 * characters.
4664 */
4665 name = alloc((unsigned)(p - *arg + extra));
4666 if (name == NULL)
4667 return FAIL;
Bram Moolenaar8c711452005-01-14 21:53:12 +00004668 rettv->v_type = VAR_STRING;
4669 rettv->vval.v_string = name;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004670
Bram Moolenaar8c711452005-01-14 21:53:12 +00004671 for (p = *arg + 1; *p != NUL && *p != '"'; )
Bram Moolenaar071d4272004-06-13 20:20:40 +00004672 {
4673 if (*p == '\\')
4674 {
4675 switch (*++p)
4676 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00004677 case 'b': *name++ = BS; ++p; break;
4678 case 'e': *name++ = ESC; ++p; break;
4679 case 'f': *name++ = FF; ++p; break;
4680 case 'n': *name++ = NL; ++p; break;
4681 case 'r': *name++ = CAR; ++p; break;
4682 case 't': *name++ = TAB; ++p; break;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004683
4684 case 'X': /* hex: "\x1", "\x12" */
4685 case 'x':
4686 case 'u': /* Unicode: "\u0023" */
4687 case 'U':
4688 if (vim_isxdigit(p[1]))
4689 {
4690 int n, nr;
4691 int c = toupper(*p);
4692
4693 if (c == 'X')
4694 n = 2;
4695 else
4696 n = 4;
4697 nr = 0;
4698 while (--n >= 0 && vim_isxdigit(p[1]))
4699 {
4700 ++p;
4701 nr = (nr << 4) + hex2nr(*p);
4702 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00004703 ++p;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004704#ifdef FEAT_MBYTE
4705 /* For "\u" store the number according to
4706 * 'encoding'. */
4707 if (c != 'X')
Bram Moolenaar8c711452005-01-14 21:53:12 +00004708 name += (*mb_char2bytes)(nr, name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004709 else
4710#endif
Bram Moolenaar8c711452005-01-14 21:53:12 +00004711 *name++ = nr;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004712 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004713 break;
4714
4715 /* octal: "\1", "\12", "\123" */
4716 case '0':
4717 case '1':
4718 case '2':
4719 case '3':
4720 case '4':
4721 case '5':
4722 case '6':
Bram Moolenaar8c711452005-01-14 21:53:12 +00004723 case '7': *name = *p++ - '0';
4724 if (*p >= '0' && *p <= '7')
Bram Moolenaar071d4272004-06-13 20:20:40 +00004725 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00004726 *name = (*name << 3) + *p++ - '0';
4727 if (*p >= '0' && *p <= '7')
4728 *name = (*name << 3) + *p++ - '0';
Bram Moolenaar071d4272004-06-13 20:20:40 +00004729 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00004730 ++name;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004731 break;
4732
4733 /* Special key, e.g.: "\<C-W>" */
Bram Moolenaar8c711452005-01-14 21:53:12 +00004734 case '<': extra = trans_special(&p, name, TRUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004735 if (extra != 0)
4736 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00004737 name += extra;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004738 break;
4739 }
4740 /* FALLTHROUGH */
4741
Bram Moolenaar8c711452005-01-14 21:53:12 +00004742 default: MB_COPY_CHAR(p, name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004743 break;
4744 }
4745 }
4746 else
Bram Moolenaar8c711452005-01-14 21:53:12 +00004747 MB_COPY_CHAR(p, name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004748
Bram Moolenaar071d4272004-06-13 20:20:40 +00004749 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00004750 *name = NUL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004751 *arg = p + 1;
4752
Bram Moolenaar071d4272004-06-13 20:20:40 +00004753 return OK;
4754}
4755
4756/*
Bram Moolenaar8c711452005-01-14 21:53:12 +00004757 * Allocate a variable for a 'str''ing' constant.
Bram Moolenaar071d4272004-06-13 20:20:40 +00004758 * Return OK or FAIL.
4759 */
4760 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004761get_lit_string_tv(arg, rettv, evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004762 char_u **arg;
Bram Moolenaar33570922005-01-25 22:26:29 +00004763 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004764 int evaluate;
4765{
4766 char_u *p;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00004767 char_u *str;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00004768 int reduce = 0;
4769
4770 /*
Bram Moolenaar8c711452005-01-14 21:53:12 +00004771 * Find the end of the string, skipping ''.
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00004772 */
4773 for (p = *arg + 1; *p != NUL; mb_ptr_adv(p))
4774 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00004775 if (*p == '\'')
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00004776 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00004777 if (p[1] != '\'')
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00004778 break;
4779 ++reduce;
4780 ++p;
4781 }
4782 }
4783
Bram Moolenaar8c711452005-01-14 21:53:12 +00004784 if (*p != '\'')
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00004785 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00004786 EMSG2(_("E115: Missing quote: %s"), *arg);
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00004787 return FAIL;
4788 }
4789
Bram Moolenaar8c711452005-01-14 21:53:12 +00004790 /* If only parsing return after setting "*arg" */
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00004791 if (!evaluate)
4792 {
4793 *arg = p + 1;
4794 return OK;
4795 }
4796
4797 /*
Bram Moolenaar8c711452005-01-14 21:53:12 +00004798 * Copy the string into allocated memory, handling '' to ' reduction.
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00004799 */
4800 str = alloc((unsigned)((p - *arg) - reduce));
4801 if (str == NULL)
4802 return FAIL;
Bram Moolenaar8c711452005-01-14 21:53:12 +00004803 rettv->v_type = VAR_STRING;
4804 rettv->vval.v_string = str;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00004805
Bram Moolenaar8c711452005-01-14 21:53:12 +00004806 for (p = *arg + 1; *p != NUL; )
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00004807 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00004808 if (*p == '\'')
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00004809 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00004810 if (p[1] != '\'')
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00004811 break;
4812 ++p;
4813 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00004814 MB_COPY_CHAR(p, str);
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00004815 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00004816 *str = NUL;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00004817 *arg = p + 1;
4818
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00004819 return OK;
4820}
4821
4822/*
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004823 * Allocate a variable for a List and fill it from "*arg".
4824 * Return OK or FAIL.
4825 */
4826 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004827get_list_tv(arg, rettv, evaluate)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004828 char_u **arg;
Bram Moolenaar33570922005-01-25 22:26:29 +00004829 typval_T *rettv;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004830 int evaluate;
4831{
Bram Moolenaar33570922005-01-25 22:26:29 +00004832 list_T *l = NULL;
4833 typval_T tv;
4834 listitem_T *item;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004835
4836 if (evaluate)
4837 {
4838 l = list_alloc();
4839 if (l == NULL)
4840 return FAIL;
4841 }
4842
4843 *arg = skipwhite(*arg + 1);
4844 while (**arg != ']' && **arg != NUL)
4845 {
4846 if (eval1(arg, &tv, evaluate) == FAIL) /* recursive! */
4847 goto failret;
4848 if (evaluate)
4849 {
4850 item = listitem_alloc();
4851 if (item != NULL)
4852 {
4853 item->li_tv = tv;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00004854 item->li_tv.v_lock = 0;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004855 list_append(l, item);
4856 }
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00004857 else
4858 clear_tv(&tv);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004859 }
4860
4861 if (**arg == ']')
4862 break;
4863 if (**arg != ',')
4864 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00004865 EMSG2(_("E696: Missing comma in List: %s"), *arg);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004866 goto failret;
4867 }
4868 *arg = skipwhite(*arg + 1);
4869 }
4870
4871 if (**arg != ']')
4872 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00004873 EMSG2(_("E697: Missing end of List ']': %s"), *arg);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004874failret:
4875 if (evaluate)
4876 list_free(l);
4877 return FAIL;
4878 }
4879
4880 *arg = skipwhite(*arg + 1);
4881 if (evaluate)
4882 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004883 rettv->v_type = VAR_LIST;
4884 rettv->vval.v_list = l;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004885 ++l->lv_refcount;
4886 }
4887
4888 return OK;
4889}
4890
4891/*
4892 * Allocate an empty header for a list.
4893 */
Bram Moolenaar33570922005-01-25 22:26:29 +00004894 static list_T *
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004895list_alloc()
4896{
Bram Moolenaar33570922005-01-25 22:26:29 +00004897 return (list_T *)alloc_clear(sizeof(list_T));
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004898}
4899
4900/*
4901 * Unreference a list: decrement the reference count and free it when it
4902 * becomes zero.
4903 */
4904 static void
4905list_unref(l)
Bram Moolenaar33570922005-01-25 22:26:29 +00004906 list_T *l;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004907{
4908 if (l != NULL && --l->lv_refcount <= 0)
4909 list_free(l);
4910}
4911
4912/*
4913 * Free a list, including all items it points to.
4914 * Ignores the reference count.
4915 */
4916 static void
4917list_free(l)
Bram Moolenaar33570922005-01-25 22:26:29 +00004918 list_T *l;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004919{
Bram Moolenaar33570922005-01-25 22:26:29 +00004920 listitem_T *item;
4921 listitem_T *next;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004922
4923 for (item = l->lv_first; item != NULL; item = next)
4924 {
4925 next = item->li_next;
4926 listitem_free(item);
4927 }
4928 vim_free(l);
4929}
4930
4931/*
4932 * Allocate a list item.
4933 */
Bram Moolenaar33570922005-01-25 22:26:29 +00004934 static listitem_T *
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004935listitem_alloc()
4936{
Bram Moolenaar33570922005-01-25 22:26:29 +00004937 return (listitem_T *)alloc(sizeof(listitem_T));
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004938}
4939
4940/*
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00004941 * Free a list item. Also clears the value. Does not notify watchers.
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004942 */
4943 static void
4944listitem_free(item)
Bram Moolenaar33570922005-01-25 22:26:29 +00004945 listitem_T *item;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004946{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004947 clear_tv(&item->li_tv);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004948 vim_free(item);
4949}
4950
4951/*
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00004952 * Remove a list item from a List and free it. Also clears the value.
4953 */
4954 static void
4955listitem_remove(l, item)
Bram Moolenaar33570922005-01-25 22:26:29 +00004956 list_T *l;
4957 listitem_T *item;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00004958{
4959 list_remove(l, item, item);
4960 listitem_free(item);
4961}
4962
4963/*
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004964 * Get the number of items in a list.
4965 */
4966 static long
4967list_len(l)
Bram Moolenaar33570922005-01-25 22:26:29 +00004968 list_T *l;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004969{
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004970 if (l == NULL)
4971 return 0L;
Bram Moolenaar758711c2005-02-02 23:11:38 +00004972 return l->lv_len;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004973}
4974
4975/*
Bram Moolenaar8a283e52005-01-06 23:28:25 +00004976 * Return TRUE when two lists have exactly the same values.
4977 */
4978 static int
4979list_equal(l1, l2, ic)
Bram Moolenaar33570922005-01-25 22:26:29 +00004980 list_T *l1;
4981 list_T *l2;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00004982 int ic; /* ignore case for strings */
4983{
Bram Moolenaar33570922005-01-25 22:26:29 +00004984 listitem_T *item1, *item2;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00004985
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00004986 if (list_len(l1) != list_len(l2))
4987 return FALSE;
4988
Bram Moolenaar8a283e52005-01-06 23:28:25 +00004989 for (item1 = l1->lv_first, item2 = l2->lv_first;
4990 item1 != NULL && item2 != NULL;
4991 item1 = item1->li_next, item2 = item2->li_next)
4992 if (!tv_equal(&item1->li_tv, &item2->li_tv, ic))
4993 return FALSE;
4994 return item1 == NULL && item2 == NULL;
4995}
4996
4997/*
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00004998 * Return TRUE when two dictionaries have exactly the same key/values.
4999 */
5000 static int
5001dict_equal(d1, d2, ic)
Bram Moolenaar33570922005-01-25 22:26:29 +00005002 dict_T *d1;
5003 dict_T *d2;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00005004 int ic; /* ignore case for strings */
5005{
Bram Moolenaar33570922005-01-25 22:26:29 +00005006 hashitem_T *hi;
5007 dictitem_T *item2;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005008 int todo;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00005009
5010 if (dict_len(d1) != dict_len(d2))
5011 return FALSE;
5012
Bram Moolenaar33570922005-01-25 22:26:29 +00005013 todo = d1->dv_hashtab.ht_used;
5014 for (hi = d1->dv_hashtab.ht_array; todo > 0; ++hi)
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00005015 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005016 if (!HASHITEM_EMPTY(hi))
5017 {
5018 item2 = dict_find(d2, hi->hi_key, -1);
5019 if (item2 == NULL)
5020 return FALSE;
5021 if (!tv_equal(&HI2DI(hi)->di_tv, &item2->di_tv, ic))
5022 return FALSE;
5023 --todo;
5024 }
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00005025 }
5026 return TRUE;
5027}
5028
5029/*
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005030 * Return TRUE if "tv1" and "tv2" have the same value.
5031 * Compares the items just like "==" would compare them.
5032 */
5033 static int
5034tv_equal(tv1, tv2, ic)
Bram Moolenaar33570922005-01-25 22:26:29 +00005035 typval_T *tv1;
5036 typval_T *tv2;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005037 int ic; /* ignore case */
5038{
5039 char_u buf1[NUMBUFLEN], buf2[NUMBUFLEN];
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00005040 char_u *s1, *s2;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005041
5042 if (tv1->v_type == VAR_LIST || tv2->v_type == VAR_LIST)
5043 {
5044 /* recursive! */
5045 if (tv1->v_type != tv2->v_type
5046 || !list_equal(tv1->vval.v_list, tv2->vval.v_list, ic))
5047 return FALSE;
5048 }
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005049 else if (tv1->v_type == VAR_DICT || tv2->v_type == VAR_DICT)
5050 {
5051 /* recursive! */
5052 if (tv1->v_type != tv2->v_type
5053 || !dict_equal(tv1->vval.v_dict, tv2->vval.v_dict, ic))
5054 return FALSE;
5055 }
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005056 else if (tv1->v_type == VAR_FUNC || tv2->v_type == VAR_FUNC)
5057 {
5058 if (tv1->v_type != tv2->v_type
5059 || tv1->vval.v_string == NULL
5060 || tv2->vval.v_string == NULL
5061 || STRCMP(tv1->vval.v_string, tv2->vval.v_string) != 0)
5062 return FALSE;
5063 }
5064 else if (tv1->v_type == VAR_NUMBER || tv2->v_type == VAR_NUMBER)
5065 {
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005066 /* "4" is equal to 4. But don't consider 'a' and zero to be equal.
5067 * Don't consider "4x" to be equal to 4. */
5068 if ((tv1->v_type == VAR_STRING
5069 && !string_isa_number(tv1->vval.v_string))
5070 || (tv2->v_type == VAR_STRING
5071 && !string_isa_number(tv2->vval.v_string)))
5072 return FALSE;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005073 if (get_tv_number(tv1) != get_tv_number(tv2))
5074 return FALSE;
5075 }
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00005076 else
5077 {
5078 s1 = get_tv_string_buf(tv1, buf1);
5079 s2 = get_tv_string_buf(tv2, buf2);
5080 if ((ic ? MB_STRICMP(s1, s2) : STRCMP(s1, s2)) != 0)
5081 return FALSE;
5082 }
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005083 return TRUE;
5084}
5085
5086/*
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005087 * Return TRUE if "tv" is a number without other non-white characters.
5088 */
5089 static int
5090string_isa_number(s)
5091 char_u *s;
5092{
5093 int len;
5094
5095 vim_str2nr(s, NULL, &len, TRUE, TRUE, NULL, NULL);
5096 return len > 0 && *skipwhite(s + len) == NUL;
5097}
5098
5099/*
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005100 * Locate item with index "n" in list "l" and return it.
5101 * A negative index is counted from the end; -1 is the last item.
5102 * Returns NULL when "n" is out of range.
5103 */
Bram Moolenaar33570922005-01-25 22:26:29 +00005104 static listitem_T *
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005105list_find(l, n)
Bram Moolenaar33570922005-01-25 22:26:29 +00005106 list_T *l;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005107 long n;
5108{
Bram Moolenaar33570922005-01-25 22:26:29 +00005109 listitem_T *item;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005110 long idx;
5111
5112 if (l == NULL)
5113 return NULL;
Bram Moolenaar758711c2005-02-02 23:11:38 +00005114
5115 /* Negative index is relative to the end. */
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005116 if (n < 0)
Bram Moolenaar758711c2005-02-02 23:11:38 +00005117 n = l->lv_len + n;
5118
5119 /* Check for index out of range. */
5120 if (n < 0 || n >= l->lv_len)
5121 return NULL;
5122
5123 /* When there is a cached index may start search from there. */
5124 if (l->lv_idx_item != NULL)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005125 {
Bram Moolenaar758711c2005-02-02 23:11:38 +00005126 if (n < l->lv_idx / 2)
5127 {
5128 /* closest to the start of the list */
5129 item = l->lv_first;
5130 idx = 0;
5131 }
5132 else if (n > (l->lv_idx + l->lv_len) / 2)
5133 {
5134 /* closest to the end of the list */
5135 item = l->lv_last;
5136 idx = l->lv_len - 1;
5137 }
5138 else
5139 {
5140 /* closest to the cached index */
5141 item = l->lv_idx_item;
5142 idx = l->lv_idx;
5143 }
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005144 }
5145 else
5146 {
Bram Moolenaar758711c2005-02-02 23:11:38 +00005147 if (n < l->lv_len / 2)
5148 {
5149 /* closest to the start of the list */
5150 item = l->lv_first;
5151 idx = 0;
5152 }
5153 else
5154 {
5155 /* closest to the end of the list */
5156 item = l->lv_last;
5157 idx = l->lv_len - 1;
5158 }
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005159 }
Bram Moolenaar758711c2005-02-02 23:11:38 +00005160
5161 while (n > idx)
5162 {
5163 /* search forward */
5164 item = item->li_next;
5165 ++idx;
5166 }
5167 while (n < idx)
5168 {
5169 /* search backward */
5170 item = item->li_prev;
5171 --idx;
5172 }
5173
5174 /* cache the used index */
5175 l->lv_idx = idx;
5176 l->lv_idx_item = item;
5177
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005178 return item;
5179}
5180
5181/*
Bram Moolenaar6cc16192005-01-08 21:49:45 +00005182 * Locate "item" list "l" and return its index.
5183 * Returns -1 when "item" is not in the list.
5184 */
5185 static long
5186list_idx_of_item(l, item)
Bram Moolenaar33570922005-01-25 22:26:29 +00005187 list_T *l;
5188 listitem_T *item;
Bram Moolenaar6cc16192005-01-08 21:49:45 +00005189{
5190 long idx = 0;
Bram Moolenaar33570922005-01-25 22:26:29 +00005191 listitem_T *li;
Bram Moolenaar6cc16192005-01-08 21:49:45 +00005192
5193 if (l == NULL)
5194 return -1;
5195 idx = 0;
5196 for (li = l->lv_first; li != NULL && li != item; li = li->li_next)
5197 ++idx;
5198 if (li == NULL)
5199 return -1;
Bram Moolenaar75c50c42005-06-04 22:06:24 +00005200 return idx;
Bram Moolenaar6cc16192005-01-08 21:49:45 +00005201}
5202
5203/*
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005204 * Append item "item" to the end of list "l".
5205 */
5206 static void
5207list_append(l, item)
Bram Moolenaar33570922005-01-25 22:26:29 +00005208 list_T *l;
5209 listitem_T *item;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005210{
5211 if (l->lv_last == NULL)
5212 {
5213 /* empty list */
5214 l->lv_first = item;
5215 l->lv_last = item;
5216 item->li_prev = NULL;
5217 }
5218 else
5219 {
5220 l->lv_last->li_next = item;
5221 item->li_prev = l->lv_last;
5222 l->lv_last = item;
5223 }
Bram Moolenaar758711c2005-02-02 23:11:38 +00005224 ++l->lv_len;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005225 item->li_next = NULL;
5226}
5227
5228/*
Bram Moolenaar33570922005-01-25 22:26:29 +00005229 * Append typval_T "tv" to the end of list "l".
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005230 * Return FAIL when out of memory.
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005231 */
5232 static int
5233list_append_tv(l, tv)
Bram Moolenaar33570922005-01-25 22:26:29 +00005234 list_T *l;
5235 typval_T *tv;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005236{
Bram Moolenaar05159a02005-02-26 23:04:13 +00005237 listitem_T *li = listitem_alloc();
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005238
Bram Moolenaar05159a02005-02-26 23:04:13 +00005239 if (li == NULL)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005240 return FAIL;
Bram Moolenaar05159a02005-02-26 23:04:13 +00005241 copy_tv(tv, &li->li_tv);
5242 list_append(l, li);
5243 return OK;
5244}
5245
5246/*
Bram Moolenaar2641f772005-03-25 21:58:17 +00005247 * Add a dictionary to a list. Used by getqflist().
Bram Moolenaar05159a02005-02-26 23:04:13 +00005248 * Return FAIL when out of memory.
5249 */
5250 int
5251list_append_dict(list, dict)
5252 list_T *list;
5253 dict_T *dict;
5254{
5255 listitem_T *li = listitem_alloc();
5256
5257 if (li == NULL)
5258 return FAIL;
5259 li->li_tv.v_type = VAR_DICT;
5260 li->li_tv.v_lock = 0;
5261 li->li_tv.vval.v_dict = dict;
5262 list_append(list, li);
5263 ++dict->dv_refcount;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005264 return OK;
5265}
5266
5267/*
Bram Moolenaar33570922005-01-25 22:26:29 +00005268 * Insert typval_T "tv" in list "l" before "item".
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005269 * If "item" is NULL append at the end.
5270 * Return FAIL when out of memory.
5271 */
5272 static int
5273list_insert_tv(l, tv, item)
Bram Moolenaar33570922005-01-25 22:26:29 +00005274 list_T *l;
5275 typval_T *tv;
5276 listitem_T *item;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005277{
Bram Moolenaar33570922005-01-25 22:26:29 +00005278 listitem_T *ni = listitem_alloc();
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005279
5280 if (ni == NULL)
5281 return FAIL;
5282 copy_tv(tv, &ni->li_tv);
5283 if (item == NULL)
5284 /* Append new item at end of list. */
5285 list_append(l, ni);
5286 else
5287 {
5288 /* Insert new item before existing item. */
5289 ni->li_prev = item->li_prev;
5290 ni->li_next = item;
5291 if (item->li_prev == NULL)
Bram Moolenaar758711c2005-02-02 23:11:38 +00005292 {
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005293 l->lv_first = ni;
Bram Moolenaar758711c2005-02-02 23:11:38 +00005294 ++l->lv_idx;
5295 }
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005296 else
Bram Moolenaar758711c2005-02-02 23:11:38 +00005297 {
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005298 item->li_prev->li_next = ni;
Bram Moolenaar758711c2005-02-02 23:11:38 +00005299 l->lv_idx_item = NULL;
5300 }
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005301 item->li_prev = ni;
Bram Moolenaar758711c2005-02-02 23:11:38 +00005302 ++l->lv_len;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005303 }
5304 return OK;
5305}
5306
5307/*
5308 * Extend "l1" with "l2".
5309 * If "bef" is NULL append at the end, otherwise insert before this item.
5310 * Returns FAIL when out of memory.
5311 */
5312 static int
5313list_extend(l1, l2, bef)
Bram Moolenaar33570922005-01-25 22:26:29 +00005314 list_T *l1;
5315 list_T *l2;
5316 listitem_T *bef;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005317{
Bram Moolenaar33570922005-01-25 22:26:29 +00005318 listitem_T *item;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005319
5320 for (item = l2->lv_first; item != NULL; item = item->li_next)
5321 if (list_insert_tv(l1, &item->li_tv, bef) == FAIL)
5322 return FAIL;
5323 return OK;
5324}
5325
5326/*
5327 * Concatenate lists "l1" and "l2" into a new list, stored in "tv".
5328 * Return FAIL when out of memory.
5329 */
5330 static int
5331list_concat(l1, l2, tv)
Bram Moolenaar33570922005-01-25 22:26:29 +00005332 list_T *l1;
5333 list_T *l2;
5334 typval_T *tv;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005335{
Bram Moolenaar33570922005-01-25 22:26:29 +00005336 list_T *l;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005337
5338 /* make a copy of the first list. */
Bram Moolenaar81bf7082005-02-12 14:31:42 +00005339 l = list_copy(l1, FALSE, 0);
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005340 if (l == NULL)
5341 return FAIL;
5342 tv->v_type = VAR_LIST;
5343 tv->vval.v_list = l;
5344
5345 /* append all items from the second list */
5346 return list_extend(l, l2, NULL);
5347}
5348
5349/*
Bram Moolenaare9a41262005-01-15 22:18:47 +00005350 * Make a copy of list "orig". Shallow if "deep" is FALSE.
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005351 * The refcount of the new list is set to 1.
Bram Moolenaar81bf7082005-02-12 14:31:42 +00005352 * See item_copy() for "copyID".
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005353 * Returns NULL when out of memory.
5354 */
Bram Moolenaar33570922005-01-25 22:26:29 +00005355 static list_T *
Bram Moolenaar81bf7082005-02-12 14:31:42 +00005356list_copy(orig, deep, copyID)
Bram Moolenaar33570922005-01-25 22:26:29 +00005357 list_T *orig;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005358 int deep;
Bram Moolenaar81bf7082005-02-12 14:31:42 +00005359 int copyID;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005360{
Bram Moolenaar33570922005-01-25 22:26:29 +00005361 list_T *copy;
5362 listitem_T *item;
5363 listitem_T *ni;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005364
5365 if (orig == NULL)
5366 return NULL;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005367
5368 copy = list_alloc();
5369 if (copy != NULL)
5370 {
Bram Moolenaar81bf7082005-02-12 14:31:42 +00005371 if (copyID != 0)
5372 {
5373 /* Do this before adding the items, because one of the items may
5374 * refer back to this list. */
5375 orig->lv_copyID = copyID;
5376 orig->lv_copylist = copy;
5377 }
5378 for (item = orig->lv_first; item != NULL && !got_int;
5379 item = item->li_next)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005380 {
5381 ni = listitem_alloc();
5382 if (ni == NULL)
5383 break;
Bram Moolenaare9a41262005-01-15 22:18:47 +00005384 if (deep)
Bram Moolenaar81bf7082005-02-12 14:31:42 +00005385 {
5386 if (item_copy(&item->li_tv, &ni->li_tv, deep, copyID) == FAIL)
5387 {
5388 vim_free(ni);
5389 break;
5390 }
5391 }
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005392 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005393 copy_tv(&item->li_tv, &ni->li_tv);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005394 list_append(copy, ni);
5395 }
5396 ++copy->lv_refcount;
Bram Moolenaar81bf7082005-02-12 14:31:42 +00005397 if (item != NULL)
5398 {
5399 list_unref(copy);
5400 copy = NULL;
5401 }
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005402 }
5403
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005404 return copy;
5405}
5406
5407/*
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005408 * Remove items "item" to "item2" from list "l".
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00005409 * Does not free the listitem or the value!
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005410 */
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005411 static void
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00005412list_remove(l, item, item2)
Bram Moolenaar33570922005-01-25 22:26:29 +00005413 list_T *l;
5414 listitem_T *item;
5415 listitem_T *item2;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005416{
Bram Moolenaar33570922005-01-25 22:26:29 +00005417 listitem_T *ip;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005418
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005419 /* notify watchers */
5420 for (ip = item; ip != NULL; ip = ip->li_next)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005421 {
Bram Moolenaar758711c2005-02-02 23:11:38 +00005422 --l->lv_len;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005423 list_fix_watch(l, ip);
5424 if (ip == item2)
5425 break;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005426 }
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005427
5428 if (item2->li_next == NULL)
5429 l->lv_last = item->li_prev;
5430 else
5431 item2->li_next->li_prev = item->li_prev;
5432 if (item->li_prev == NULL)
5433 l->lv_first = item2->li_next;
5434 else
5435 item->li_prev->li_next = item2->li_next;
Bram Moolenaar758711c2005-02-02 23:11:38 +00005436 l->lv_idx_item = NULL;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005437}
5438
5439/*
5440 * Return an allocated string with the string representation of a list.
5441 * May return NULL.
5442 */
5443 static char_u *
5444list2string(tv)
Bram Moolenaar33570922005-01-25 22:26:29 +00005445 typval_T *tv;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005446{
5447 garray_T ga;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005448
5449 if (tv->vval.v_list == NULL)
5450 return NULL;
5451 ga_init2(&ga, (int)sizeof(char), 80);
5452 ga_append(&ga, '[');
Bram Moolenaar81bf7082005-02-12 14:31:42 +00005453 if (list_join(&ga, tv->vval.v_list, (char_u *)", ", FALSE) == FAIL)
5454 {
5455 vim_free(ga.ga_data);
5456 return NULL;
5457 }
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005458 ga_append(&ga, ']');
5459 ga_append(&ga, NUL);
5460 return (char_u *)ga.ga_data;
5461}
5462
5463/*
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005464 * Join list "l" into a string in "*gap", using separator "sep".
5465 * When "echo" is TRUE use String as echoed, otherwise as inside a List.
Bram Moolenaar81bf7082005-02-12 14:31:42 +00005466 * Return FAIL or OK.
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005467 */
Bram Moolenaar81bf7082005-02-12 14:31:42 +00005468 static int
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005469list_join(gap, l, sep, echo)
5470 garray_T *gap;
Bram Moolenaar33570922005-01-25 22:26:29 +00005471 list_T *l;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005472 char_u *sep;
5473 int echo;
5474{
5475 int first = TRUE;
5476 char_u *tofree;
5477 char_u numbuf[NUMBUFLEN];
Bram Moolenaar33570922005-01-25 22:26:29 +00005478 listitem_T *item;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005479 char_u *s;
5480
Bram Moolenaar81bf7082005-02-12 14:31:42 +00005481 for (item = l->lv_first; item != NULL && !got_int; item = item->li_next)
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005482 {
5483 if (first)
5484 first = FALSE;
5485 else
5486 ga_concat(gap, sep);
5487
5488 if (echo)
5489 s = echo_string(&item->li_tv, &tofree, numbuf);
5490 else
5491 s = tv2string(&item->li_tv, &tofree, numbuf);
5492 if (s != NULL)
5493 ga_concat(gap, s);
5494 vim_free(tofree);
Bram Moolenaar81bf7082005-02-12 14:31:42 +00005495 if (s == NULL)
5496 return FAIL;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005497 }
Bram Moolenaar81bf7082005-02-12 14:31:42 +00005498 return OK;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005499}
5500
5501/*
Bram Moolenaar8c711452005-01-14 21:53:12 +00005502 * Allocate an empty header for a dictionary.
5503 */
Bram Moolenaar05159a02005-02-26 23:04:13 +00005504 dict_T *
Bram Moolenaar8c711452005-01-14 21:53:12 +00005505dict_alloc()
5506{
Bram Moolenaar33570922005-01-25 22:26:29 +00005507 dict_T *d;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005508
Bram Moolenaar33570922005-01-25 22:26:29 +00005509 d = (dict_T *)alloc(sizeof(dict_T));
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005510 if (d != NULL)
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00005511 {
Bram Moolenaar33570922005-01-25 22:26:29 +00005512 hash_init(&d->dv_hashtab);
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00005513 d->dv_lock = 0;
5514 d->dv_refcount = 0;
Bram Moolenaar81bf7082005-02-12 14:31:42 +00005515 d->dv_copyID = 0;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00005516 }
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005517 return d;
Bram Moolenaar8c711452005-01-14 21:53:12 +00005518}
5519
5520/*
5521 * Unreference a Dictionary: decrement the reference count and free it when it
5522 * becomes zero.
5523 */
5524 static void
5525dict_unref(d)
Bram Moolenaar33570922005-01-25 22:26:29 +00005526 dict_T *d;
Bram Moolenaar8c711452005-01-14 21:53:12 +00005527{
5528 if (d != NULL && --d->dv_refcount <= 0)
5529 dict_free(d);
5530}
5531
5532/*
5533 * Free a Dictionary, including all items it contains.
5534 * Ignores the reference count.
5535 */
5536 static void
5537dict_free(d)
Bram Moolenaar33570922005-01-25 22:26:29 +00005538 dict_T *d;
Bram Moolenaar8c711452005-01-14 21:53:12 +00005539{
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005540 int todo;
Bram Moolenaar33570922005-01-25 22:26:29 +00005541 hashitem_T *hi;
Bram Moolenaar8c711452005-01-14 21:53:12 +00005542
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005543 /* Careful: we free the dictitems while they still appear in the
Bram Moolenaar33570922005-01-25 22:26:29 +00005544 * hashtab. Must not try to resize the hashtab! */
5545 todo = d->dv_hashtab.ht_used;
5546 for (hi = d->dv_hashtab.ht_array; todo > 0; ++hi)
Bram Moolenaar8c711452005-01-14 21:53:12 +00005547 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005548 if (!HASHITEM_EMPTY(hi))
5549 {
5550 dictitem_free(HI2DI(hi));
5551 --todo;
5552 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00005553 }
Bram Moolenaar33570922005-01-25 22:26:29 +00005554 hash_clear(&d->dv_hashtab);
Bram Moolenaar8c711452005-01-14 21:53:12 +00005555 vim_free(d);
5556}
5557
5558/*
5559 * Allocate a Dictionary item.
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005560 * The "key" is copied to the new item.
5561 * Note that the value of the item "di_tv" still needs to be initialized!
5562 * Returns NULL when out of memory.
Bram Moolenaar8c711452005-01-14 21:53:12 +00005563 */
Bram Moolenaar33570922005-01-25 22:26:29 +00005564 static dictitem_T *
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005565dictitem_alloc(key)
5566 char_u *key;
Bram Moolenaar8c711452005-01-14 21:53:12 +00005567{
Bram Moolenaar33570922005-01-25 22:26:29 +00005568 dictitem_T *di;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005569
Bram Moolenaar33570922005-01-25 22:26:29 +00005570 di = (dictitem_T *)alloc(sizeof(dictitem_T) + STRLEN(key));
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005571 if (di != NULL)
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00005572 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005573 STRCPY(di->di_key, key);
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00005574 di->di_flags = 0;
5575 }
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005576 return di;
Bram Moolenaar8c711452005-01-14 21:53:12 +00005577}
5578
5579/*
Bram Moolenaare9a41262005-01-15 22:18:47 +00005580 * Make a copy of a Dictionary item.
5581 */
Bram Moolenaar33570922005-01-25 22:26:29 +00005582 static dictitem_T *
Bram Moolenaare9a41262005-01-15 22:18:47 +00005583dictitem_copy(org)
Bram Moolenaar33570922005-01-25 22:26:29 +00005584 dictitem_T *org;
Bram Moolenaare9a41262005-01-15 22:18:47 +00005585{
Bram Moolenaar33570922005-01-25 22:26:29 +00005586 dictitem_T *di;
Bram Moolenaare9a41262005-01-15 22:18:47 +00005587
Bram Moolenaar33570922005-01-25 22:26:29 +00005588 di = (dictitem_T *)alloc(sizeof(dictitem_T) + STRLEN(org->di_key));
Bram Moolenaare9a41262005-01-15 22:18:47 +00005589 if (di != NULL)
5590 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005591 STRCPY(di->di_key, org->di_key);
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00005592 di->di_flags = 0;
Bram Moolenaare9a41262005-01-15 22:18:47 +00005593 copy_tv(&org->di_tv, &di->di_tv);
5594 }
5595 return di;
5596}
5597
5598/*
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005599 * Remove item "item" from Dictionary "dict" and free it.
5600 */
5601 static void
5602dictitem_remove(dict, item)
Bram Moolenaar33570922005-01-25 22:26:29 +00005603 dict_T *dict;
5604 dictitem_T *item;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005605{
Bram Moolenaar33570922005-01-25 22:26:29 +00005606 hashitem_T *hi;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005607
Bram Moolenaar33570922005-01-25 22:26:29 +00005608 hi = hash_find(&dict->dv_hashtab, item->di_key);
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005609 if (HASHITEM_EMPTY(hi))
5610 EMSG2(_(e_intern2), "dictitem_remove()");
5611 else
Bram Moolenaar33570922005-01-25 22:26:29 +00005612 hash_remove(&dict->dv_hashtab, hi);
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005613 dictitem_free(item);
5614}
5615
5616/*
Bram Moolenaar8c711452005-01-14 21:53:12 +00005617 * Free a dict item. Also clears the value.
5618 */
5619 static void
5620dictitem_free(item)
Bram Moolenaar33570922005-01-25 22:26:29 +00005621 dictitem_T *item;
Bram Moolenaar8c711452005-01-14 21:53:12 +00005622{
Bram Moolenaar8c711452005-01-14 21:53:12 +00005623 clear_tv(&item->di_tv);
5624 vim_free(item);
5625}
5626
5627/*
Bram Moolenaare9a41262005-01-15 22:18:47 +00005628 * Make a copy of dict "d". Shallow if "deep" is FALSE.
5629 * The refcount of the new dict is set to 1.
Bram Moolenaar81bf7082005-02-12 14:31:42 +00005630 * See item_copy() for "copyID".
Bram Moolenaare9a41262005-01-15 22:18:47 +00005631 * Returns NULL when out of memory.
5632 */
Bram Moolenaar33570922005-01-25 22:26:29 +00005633 static dict_T *
Bram Moolenaar81bf7082005-02-12 14:31:42 +00005634dict_copy(orig, deep, copyID)
Bram Moolenaar33570922005-01-25 22:26:29 +00005635 dict_T *orig;
Bram Moolenaare9a41262005-01-15 22:18:47 +00005636 int deep;
Bram Moolenaar81bf7082005-02-12 14:31:42 +00005637 int copyID;
Bram Moolenaare9a41262005-01-15 22:18:47 +00005638{
Bram Moolenaar33570922005-01-25 22:26:29 +00005639 dict_T *copy;
5640 dictitem_T *di;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005641 int todo;
Bram Moolenaar33570922005-01-25 22:26:29 +00005642 hashitem_T *hi;
Bram Moolenaare9a41262005-01-15 22:18:47 +00005643
5644 if (orig == NULL)
5645 return NULL;
5646
5647 copy = dict_alloc();
5648 if (copy != NULL)
5649 {
Bram Moolenaar81bf7082005-02-12 14:31:42 +00005650 if (copyID != 0)
5651 {
5652 orig->dv_copyID = copyID;
5653 orig->dv_copydict = copy;
5654 }
Bram Moolenaar33570922005-01-25 22:26:29 +00005655 todo = orig->dv_hashtab.ht_used;
Bram Moolenaar81bf7082005-02-12 14:31:42 +00005656 for (hi = orig->dv_hashtab.ht_array; todo > 0 && !got_int; ++hi)
Bram Moolenaare9a41262005-01-15 22:18:47 +00005657 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005658 if (!HASHITEM_EMPTY(hi))
Bram Moolenaare9a41262005-01-15 22:18:47 +00005659 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005660 --todo;
5661
5662 di = dictitem_alloc(hi->hi_key);
5663 if (di == NULL)
5664 break;
5665 if (deep)
Bram Moolenaar81bf7082005-02-12 14:31:42 +00005666 {
5667 if (item_copy(&HI2DI(hi)->di_tv, &di->di_tv, deep,
5668 copyID) == FAIL)
5669 {
5670 vim_free(di);
5671 break;
5672 }
5673 }
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005674 else
5675 copy_tv(&HI2DI(hi)->di_tv, &di->di_tv);
5676 if (dict_add(copy, di) == FAIL)
5677 {
5678 dictitem_free(di);
5679 break;
5680 }
Bram Moolenaare9a41262005-01-15 22:18:47 +00005681 }
Bram Moolenaare9a41262005-01-15 22:18:47 +00005682 }
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005683
Bram Moolenaare9a41262005-01-15 22:18:47 +00005684 ++copy->dv_refcount;
Bram Moolenaar81bf7082005-02-12 14:31:42 +00005685 if (todo > 0)
5686 {
5687 dict_unref(copy);
5688 copy = NULL;
5689 }
Bram Moolenaare9a41262005-01-15 22:18:47 +00005690 }
5691
5692 return copy;
5693}
5694
5695/*
Bram Moolenaar8c711452005-01-14 21:53:12 +00005696 * Add item "item" to Dictionary "d".
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005697 * Returns FAIL when out of memory and when key already existed.
Bram Moolenaar8c711452005-01-14 21:53:12 +00005698 */
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005699 static int
Bram Moolenaar8c711452005-01-14 21:53:12 +00005700dict_add(d, item)
Bram Moolenaar33570922005-01-25 22:26:29 +00005701 dict_T *d;
5702 dictitem_T *item;
Bram Moolenaar8c711452005-01-14 21:53:12 +00005703{
Bram Moolenaar33570922005-01-25 22:26:29 +00005704 return hash_add(&d->dv_hashtab, item->di_key);
Bram Moolenaar8c711452005-01-14 21:53:12 +00005705}
5706
Bram Moolenaar8c711452005-01-14 21:53:12 +00005707/*
Bram Moolenaar05159a02005-02-26 23:04:13 +00005708 * Add a number or string entry to dictionary "d".
5709 * When "str" is NULL use number "nr", otherwise use "str".
5710 * Returns FAIL when out of memory and when key already exists.
5711 */
5712 int
5713dict_add_nr_str(d, key, nr, str)
5714 dict_T *d;
5715 char *key;
5716 long nr;
5717 char_u *str;
5718{
5719 dictitem_T *item;
5720
5721 item = dictitem_alloc((char_u *)key);
5722 if (item == NULL)
5723 return FAIL;
5724 item->di_tv.v_lock = 0;
5725 if (str == NULL)
5726 {
5727 item->di_tv.v_type = VAR_NUMBER;
5728 item->di_tv.vval.v_number = nr;
5729 }
5730 else
5731 {
5732 item->di_tv.v_type = VAR_STRING;
5733 item->di_tv.vval.v_string = vim_strsave(str);
5734 }
5735 if (dict_add(d, item) == FAIL)
5736 {
5737 dictitem_free(item);
5738 return FAIL;
5739 }
5740 return OK;
5741}
5742
5743/*
Bram Moolenaare9a41262005-01-15 22:18:47 +00005744 * Get the number of items in a Dictionary.
5745 */
5746 static long
5747dict_len(d)
Bram Moolenaar33570922005-01-25 22:26:29 +00005748 dict_T *d;
Bram Moolenaare9a41262005-01-15 22:18:47 +00005749{
Bram Moolenaare9a41262005-01-15 22:18:47 +00005750 if (d == NULL)
5751 return 0L;
Bram Moolenaar33570922005-01-25 22:26:29 +00005752 return d->dv_hashtab.ht_used;
Bram Moolenaare9a41262005-01-15 22:18:47 +00005753}
5754
5755/*
Bram Moolenaar8c711452005-01-14 21:53:12 +00005756 * Find item "key[len]" in Dictionary "d".
5757 * If "len" is negative use strlen(key).
5758 * Returns NULL when not found.
5759 */
Bram Moolenaar33570922005-01-25 22:26:29 +00005760 static dictitem_T *
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005761dict_find(d, key, len)
Bram Moolenaar33570922005-01-25 22:26:29 +00005762 dict_T *d;
Bram Moolenaar8c711452005-01-14 21:53:12 +00005763 char_u *key;
5764 int len;
5765{
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005766#define AKEYLEN 200
5767 char_u buf[AKEYLEN];
5768 char_u *akey;
5769 char_u *tofree = NULL;
Bram Moolenaar33570922005-01-25 22:26:29 +00005770 hashitem_T *hi;
Bram Moolenaar8c711452005-01-14 21:53:12 +00005771
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005772 if (len < 0)
5773 akey = key;
5774 else if (len >= AKEYLEN)
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00005775 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005776 tofree = akey = vim_strnsave(key, len);
5777 if (akey == NULL)
5778 return NULL;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00005779 }
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005780 else
5781 {
5782 /* Avoid a malloc/free by using buf[]. */
5783 STRNCPY(buf, key, len);
5784 buf[len] = NUL;
5785 akey = buf;
5786 }
5787
Bram Moolenaar33570922005-01-25 22:26:29 +00005788 hi = hash_find(&d->dv_hashtab, akey);
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005789 vim_free(tofree);
5790 if (HASHITEM_EMPTY(hi))
5791 return NULL;
5792 return HI2DI(hi);
Bram Moolenaar8c711452005-01-14 21:53:12 +00005793}
5794
5795/*
Bram Moolenaar2641f772005-03-25 21:58:17 +00005796 * Get a string item from a dictionary in allocated memory.
5797 * Returns NULL if the entry doesn't exist or out of memory.
5798 */
5799 char_u *
5800get_dict_string(d, key)
5801 dict_T *d;
5802 char_u *key;
5803{
5804 dictitem_T *di;
5805
5806 di = dict_find(d, key, -1);
5807 if (di == NULL)
5808 return NULL;
5809 return vim_strsave(get_tv_string(&di->di_tv));
5810}
5811
5812/*
5813 * Get a number item from a dictionary.
5814 * Returns 0 if the entry doesn't exist or out of memory.
5815 */
5816 long
5817get_dict_number(d, key)
5818 dict_T *d;
5819 char_u *key;
5820{
5821 dictitem_T *di;
5822
5823 di = dict_find(d, key, -1);
5824 if (di == NULL)
5825 return 0;
5826 return get_tv_number(&di->di_tv);
5827}
5828
5829/*
Bram Moolenaar8c711452005-01-14 21:53:12 +00005830 * Return an allocated string with the string representation of a Dictionary.
5831 * May return NULL.
5832 */
5833 static char_u *
5834dict2string(tv)
Bram Moolenaar33570922005-01-25 22:26:29 +00005835 typval_T *tv;
Bram Moolenaar8c711452005-01-14 21:53:12 +00005836{
5837 garray_T ga;
5838 int first = TRUE;
5839 char_u *tofree;
5840 char_u numbuf[NUMBUFLEN];
Bram Moolenaar33570922005-01-25 22:26:29 +00005841 hashitem_T *hi;
Bram Moolenaar8c711452005-01-14 21:53:12 +00005842 char_u *s;
Bram Moolenaar33570922005-01-25 22:26:29 +00005843 dict_T *d;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005844 int todo;
Bram Moolenaar8c711452005-01-14 21:53:12 +00005845
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005846 if ((d = tv->vval.v_dict) == NULL)
Bram Moolenaar8c711452005-01-14 21:53:12 +00005847 return NULL;
5848 ga_init2(&ga, (int)sizeof(char), 80);
5849 ga_append(&ga, '{');
5850
Bram Moolenaar33570922005-01-25 22:26:29 +00005851 todo = d->dv_hashtab.ht_used;
Bram Moolenaar81bf7082005-02-12 14:31:42 +00005852 for (hi = d->dv_hashtab.ht_array; todo > 0 && !got_int; ++hi)
Bram Moolenaar8c711452005-01-14 21:53:12 +00005853 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005854 if (!HASHITEM_EMPTY(hi))
Bram Moolenaar8c711452005-01-14 21:53:12 +00005855 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005856 --todo;
5857
5858 if (first)
5859 first = FALSE;
5860 else
5861 ga_concat(&ga, (char_u *)", ");
5862
5863 tofree = string_quote(hi->hi_key, FALSE);
5864 if (tofree != NULL)
5865 {
5866 ga_concat(&ga, tofree);
5867 vim_free(tofree);
5868 }
5869 ga_concat(&ga, (char_u *)": ");
5870 s = tv2string(&HI2DI(hi)->di_tv, &tofree, numbuf);
5871 if (s != NULL)
5872 ga_concat(&ga, s);
Bram Moolenaar8c711452005-01-14 21:53:12 +00005873 vim_free(tofree);
Bram Moolenaar81bf7082005-02-12 14:31:42 +00005874 if (s == NULL)
5875 break;
Bram Moolenaar8c711452005-01-14 21:53:12 +00005876 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00005877 }
Bram Moolenaar81bf7082005-02-12 14:31:42 +00005878 if (todo > 0)
5879 {
5880 vim_free(ga.ga_data);
5881 return NULL;
5882 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00005883
5884 ga_append(&ga, '}');
5885 ga_append(&ga, NUL);
5886 return (char_u *)ga.ga_data;
5887}
5888
5889/*
5890 * Allocate a variable for a Dictionary and fill it from "*arg".
5891 * Return OK or FAIL. Returns NOTDONE for {expr}.
5892 */
5893 static int
5894get_dict_tv(arg, rettv, evaluate)
5895 char_u **arg;
Bram Moolenaar33570922005-01-25 22:26:29 +00005896 typval_T *rettv;
Bram Moolenaar8c711452005-01-14 21:53:12 +00005897 int evaluate;
5898{
Bram Moolenaar33570922005-01-25 22:26:29 +00005899 dict_T *d = NULL;
5900 typval_T tvkey;
5901 typval_T tv;
Bram Moolenaar8c711452005-01-14 21:53:12 +00005902 char_u *key;
Bram Moolenaar33570922005-01-25 22:26:29 +00005903 dictitem_T *item;
Bram Moolenaar8c711452005-01-14 21:53:12 +00005904 char_u *start = skipwhite(*arg + 1);
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005905 char_u buf[NUMBUFLEN];
Bram Moolenaar8c711452005-01-14 21:53:12 +00005906
5907 /*
5908 * First check if it's not a curly-braces thing: {expr}.
5909 * Must do this without evaluating, otherwise a function may be called
5910 * twice. Unfortunately this means we need to call eval1() twice for the
5911 * first item.
Bram Moolenaare9a41262005-01-15 22:18:47 +00005912 * But {} is an empty Dictionary.
Bram Moolenaar8c711452005-01-14 21:53:12 +00005913 */
Bram Moolenaare9a41262005-01-15 22:18:47 +00005914 if (*start != '}')
5915 {
5916 if (eval1(&start, &tv, FALSE) == FAIL) /* recursive! */
5917 return FAIL;
5918 if (*start == '}')
5919 return NOTDONE;
5920 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00005921
5922 if (evaluate)
5923 {
5924 d = dict_alloc();
5925 if (d == NULL)
5926 return FAIL;
5927 }
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005928 tvkey.v_type = VAR_UNKNOWN;
5929 tv.v_type = VAR_UNKNOWN;
Bram Moolenaar8c711452005-01-14 21:53:12 +00005930
5931 *arg = skipwhite(*arg + 1);
5932 while (**arg != '}' && **arg != NUL)
5933 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005934 if (eval1(arg, &tvkey, evaluate) == FAIL) /* recursive! */
Bram Moolenaar8c711452005-01-14 21:53:12 +00005935 goto failret;
5936 if (**arg != ':')
5937 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00005938 EMSG2(_("E720: Missing colon in Dictionary: %s"), *arg);
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005939 clear_tv(&tvkey);
Bram Moolenaar8c711452005-01-14 21:53:12 +00005940 goto failret;
5941 }
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00005942 key = get_tv_string_buf_chk(&tvkey, buf);
5943 if (key == NULL || *key == NUL)
Bram Moolenaar8c711452005-01-14 21:53:12 +00005944 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00005945 /* "key" is NULL when get_tv_string_buf_chk() gave an errmsg */
5946 if (key != NULL)
5947 EMSG(_(e_emptykey));
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005948 clear_tv(&tvkey);
Bram Moolenaar8c711452005-01-14 21:53:12 +00005949 goto failret;
5950 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00005951
5952 *arg = skipwhite(*arg + 1);
5953 if (eval1(arg, &tv, evaluate) == FAIL) /* recursive! */
5954 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005955 clear_tv(&tvkey);
Bram Moolenaar8c711452005-01-14 21:53:12 +00005956 goto failret;
5957 }
5958 if (evaluate)
5959 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005960 item = dict_find(d, key, -1);
Bram Moolenaar8c711452005-01-14 21:53:12 +00005961 if (item != NULL)
5962 {
Bram Moolenaarb982ca52005-03-28 21:02:15 +00005963 EMSG2(_("E721: Duplicate key in Dictionary: \"%s\""), key);
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005964 clear_tv(&tvkey);
Bram Moolenaar8c711452005-01-14 21:53:12 +00005965 clear_tv(&tv);
5966 goto failret;
5967 }
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005968 item = dictitem_alloc(key);
5969 clear_tv(&tvkey);
5970 if (item != NULL)
Bram Moolenaar8c711452005-01-14 21:53:12 +00005971 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00005972 item->di_tv = tv;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00005973 item->di_tv.v_lock = 0;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005974 if (dict_add(d, item) == FAIL)
5975 dictitem_free(item);
Bram Moolenaar8c711452005-01-14 21:53:12 +00005976 }
5977 }
5978
5979 if (**arg == '}')
5980 break;
5981 if (**arg != ',')
5982 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00005983 EMSG2(_("E722: Missing comma in Dictionary: %s"), *arg);
Bram Moolenaar8c711452005-01-14 21:53:12 +00005984 goto failret;
5985 }
5986 *arg = skipwhite(*arg + 1);
5987 }
5988
5989 if (**arg != '}')
5990 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00005991 EMSG2(_("E723: Missing end of Dictionary '}': %s"), *arg);
Bram Moolenaar8c711452005-01-14 21:53:12 +00005992failret:
5993 if (evaluate)
5994 dict_free(d);
5995 return FAIL;
5996 }
5997
5998 *arg = skipwhite(*arg + 1);
5999 if (evaluate)
6000 {
6001 rettv->v_type = VAR_DICT;
6002 rettv->vval.v_dict = d;
6003 ++d->dv_refcount;
6004 }
6005
6006 return OK;
6007}
6008
Bram Moolenaar8c711452005-01-14 21:53:12 +00006009/*
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006010 * Return a string with the string representation of a variable.
6011 * If the memory is allocated "tofree" is set to it, otherwise NULL.
Bram Moolenaar8a283e52005-01-06 23:28:25 +00006012 * "numbuf" is used for a number.
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00006013 * Does not put quotes around strings, as ":echo" displays values.
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006014 * May return NULL;
6015 */
6016 static char_u *
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00006017echo_string(tv, tofree, numbuf)
Bram Moolenaar33570922005-01-25 22:26:29 +00006018 typval_T *tv;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006019 char_u **tofree;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00006020 char_u *numbuf;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006021{
Bram Moolenaare9a41262005-01-15 22:18:47 +00006022 static int recurse = 0;
6023 char_u *r = NULL;
6024
Bram Moolenaar33570922005-01-25 22:26:29 +00006025 if (recurse >= DICT_MAXNEST)
Bram Moolenaare9a41262005-01-15 22:18:47 +00006026 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00006027 EMSG(_("E724: variable nested too deep for displaying"));
Bram Moolenaare9a41262005-01-15 22:18:47 +00006028 *tofree = NULL;
6029 return NULL;
6030 }
6031 ++recurse;
6032
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006033 switch (tv->v_type)
6034 {
6035 case VAR_FUNC:
6036 *tofree = NULL;
Bram Moolenaare9a41262005-01-15 22:18:47 +00006037 r = tv->vval.v_string;
6038 break;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006039 case VAR_LIST:
6040 *tofree = list2string(tv);
Bram Moolenaare9a41262005-01-15 22:18:47 +00006041 r = *tofree;
6042 break;
Bram Moolenaar8c711452005-01-14 21:53:12 +00006043 case VAR_DICT:
6044 *tofree = dict2string(tv);
Bram Moolenaare9a41262005-01-15 22:18:47 +00006045 r = *tofree;
6046 break;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006047 case VAR_STRING:
6048 case VAR_NUMBER:
Bram Moolenaare9a41262005-01-15 22:18:47 +00006049 *tofree = NULL;
6050 r = get_tv_string_buf(tv, numbuf);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006051 break;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006052 default:
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00006053 EMSG2(_(e_intern2), "echo_string()");
Bram Moolenaare9a41262005-01-15 22:18:47 +00006054 *tofree = NULL;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00006055 }
Bram Moolenaare9a41262005-01-15 22:18:47 +00006056
6057 --recurse;
6058 return r;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00006059}
6060
6061/*
6062 * Return a string with the string representation of a variable.
6063 * If the memory is allocated "tofree" is set to it, otherwise NULL.
6064 * "numbuf" is used for a number.
6065 * Puts quotes around strings, so that they can be parsed back by eval().
6066 * May return NULL;
6067 */
6068 static char_u *
6069tv2string(tv, tofree, numbuf)
Bram Moolenaar33570922005-01-25 22:26:29 +00006070 typval_T *tv;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00006071 char_u **tofree;
6072 char_u *numbuf;
6073{
6074 switch (tv->v_type)
6075 {
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00006076 case VAR_FUNC:
6077 *tofree = string_quote(tv->vval.v_string, TRUE);
6078 return *tofree;
6079 case VAR_STRING:
6080 *tofree = string_quote(tv->vval.v_string, FALSE);
6081 return *tofree;
Bram Moolenaare9a41262005-01-15 22:18:47 +00006082 case VAR_NUMBER:
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00006083 case VAR_LIST:
Bram Moolenaar8c711452005-01-14 21:53:12 +00006084 case VAR_DICT:
Bram Moolenaare9a41262005-01-15 22:18:47 +00006085 break;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00006086 default:
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006087 EMSG2(_(e_intern2), "tv2string()");
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006088 }
Bram Moolenaare9a41262005-01-15 22:18:47 +00006089 return echo_string(tv, tofree, numbuf);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006090}
6091
6092/*
Bram Moolenaar33570922005-01-25 22:26:29 +00006093 * Return string "str" in ' quotes, doubling ' characters.
6094 * If "str" is NULL an empty string is assumed.
Bram Moolenaar8c711452005-01-14 21:53:12 +00006095 * If "function" is TRUE make it function('string').
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00006096 */
6097 static char_u *
6098string_quote(str, function)
6099 char_u *str;
6100 int function;
6101{
Bram Moolenaar33570922005-01-25 22:26:29 +00006102 unsigned len;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00006103 char_u *p, *r, *s;
6104
Bram Moolenaar33570922005-01-25 22:26:29 +00006105 len = (function ? 13 : 3);
6106 if (str != NULL)
6107 {
6108 len += STRLEN(str);
6109 for (p = str; *p != NUL; mb_ptr_adv(p))
6110 if (*p == '\'')
6111 ++len;
6112 }
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00006113 s = r = alloc(len);
6114 if (r != NULL)
6115 {
6116 if (function)
6117 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00006118 STRCPY(r, "function('");
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00006119 r += 10;
6120 }
6121 else
Bram Moolenaar8c711452005-01-14 21:53:12 +00006122 *r++ = '\'';
Bram Moolenaar33570922005-01-25 22:26:29 +00006123 if (str != NULL)
6124 for (p = str; *p != NUL; )
6125 {
6126 if (*p == '\'')
6127 *r++ = '\'';
6128 MB_COPY_CHAR(p, r);
6129 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00006130 *r++ = '\'';
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00006131 if (function)
6132 *r++ = ')';
6133 *r++ = NUL;
6134 }
6135 return s;
6136}
6137
6138/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00006139 * Get the value of an environment variable.
6140 * "arg" is pointing to the '$'. It is advanced to after the name.
6141 * If the environment variable was not set, silently assume it is empty.
6142 * Always return OK.
6143 */
6144 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006145get_env_tv(arg, rettv, evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006146 char_u **arg;
Bram Moolenaar33570922005-01-25 22:26:29 +00006147 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006148 int evaluate;
6149{
6150 char_u *string = NULL;
6151 int len;
6152 int cc;
6153 char_u *name;
Bram Moolenaar05159a02005-02-26 23:04:13 +00006154 int mustfree = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006155
6156 ++*arg;
6157 name = *arg;
6158 len = get_env_len(arg);
6159 if (evaluate)
6160 {
6161 if (len != 0)
6162 {
6163 cc = name[len];
6164 name[len] = NUL;
Bram Moolenaar05159a02005-02-26 23:04:13 +00006165 /* first try vim_getenv(), fast for normal environment vars */
6166 string = vim_getenv(name, &mustfree);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006167 if (string != NULL && *string != NUL)
Bram Moolenaar05159a02005-02-26 23:04:13 +00006168 {
6169 if (!mustfree)
6170 string = vim_strsave(string);
6171 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00006172 else
6173 {
Bram Moolenaar05159a02005-02-26 23:04:13 +00006174 if (mustfree)
6175 vim_free(string);
6176
Bram Moolenaar071d4272004-06-13 20:20:40 +00006177 /* next try expanding things like $VIM and ${HOME} */
6178 string = expand_env_save(name - 1);
6179 if (string != NULL && *string == '$')
6180 {
6181 vim_free(string);
6182 string = NULL;
6183 }
6184 }
6185 name[len] = cc;
6186 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006187 rettv->v_type = VAR_STRING;
6188 rettv->vval.v_string = string;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006189 }
6190
6191 return OK;
6192}
6193
6194/*
6195 * Array with names and number of arguments of all internal functions
6196 * MUST BE KEPT SORTED IN strcmp() ORDER FOR BINARY SEARCH!
6197 */
6198static struct fst
6199{
6200 char *f_name; /* function name */
6201 char f_min_argc; /* minimal number of arguments */
6202 char f_max_argc; /* maximal number of arguments */
Bram Moolenaar33570922005-01-25 22:26:29 +00006203 void (*f_func) __ARGS((typval_T *args, typval_T *rvar));
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006204 /* implemenation of function */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006205} functions[] =
6206{
Bram Moolenaar0d660222005-01-07 21:51:51 +00006207 {"add", 2, 2, f_add},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006208 {"append", 2, 2, f_append},
6209 {"argc", 0, 0, f_argc},
6210 {"argidx", 0, 0, f_argidx},
6211 {"argv", 1, 1, f_argv},
6212 {"browse", 4, 4, f_browse},
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00006213 {"browsedir", 2, 2, f_browsedir},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006214 {"bufexists", 1, 1, f_bufexists},
6215 {"buffer_exists", 1, 1, f_bufexists}, /* obsolete */
6216 {"buffer_name", 1, 1, f_bufname}, /* obsolete */
6217 {"buffer_number", 1, 1, f_bufnr}, /* obsolete */
6218 {"buflisted", 1, 1, f_buflisted},
6219 {"bufloaded", 1, 1, f_bufloaded},
6220 {"bufname", 1, 1, f_bufname},
6221 {"bufnr", 1, 1, f_bufnr},
6222 {"bufwinnr", 1, 1, f_bufwinnr},
6223 {"byte2line", 1, 1, f_byte2line},
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00006224 {"byteidx", 2, 2, f_byteidx},
Bram Moolenaare9a41262005-01-15 22:18:47 +00006225 {"call", 2, 3, f_call},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006226 {"char2nr", 1, 1, f_char2nr},
6227 {"cindent", 1, 1, f_cindent},
6228 {"col", 1, 1, f_col},
6229 {"confirm", 1, 4, f_confirm},
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006230 {"copy", 1, 1, f_copy},
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00006231 {"count", 2, 4, f_count},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006232 {"cscope_connection",0,3, f_cscope_connection},
6233 {"cursor", 2, 2, f_cursor},
Bram Moolenaar81bf7082005-02-12 14:31:42 +00006234 {"deepcopy", 1, 2, f_deepcopy},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006235 {"delete", 1, 1, f_delete},
6236 {"did_filetype", 0, 0, f_did_filetype},
Bram Moolenaar47136d72004-10-12 20:02:24 +00006237 {"diff_filler", 1, 1, f_diff_filler},
6238 {"diff_hlID", 2, 2, f_diff_hlID},
Bram Moolenaare49b69a2005-01-08 16:11:57 +00006239 {"empty", 1, 1, f_empty},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006240 {"escape", 2, 2, f_escape},
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00006241 {"eval", 1, 1, f_eval},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006242 {"eventhandler", 0, 0, f_eventhandler},
6243 {"executable", 1, 1, f_executable},
6244 {"exists", 1, 1, f_exists},
6245 {"expand", 1, 2, f_expand},
Bram Moolenaar8a283e52005-01-06 23:28:25 +00006246 {"extend", 2, 3, f_extend},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006247 {"file_readable", 1, 1, f_filereadable}, /* obsolete */
6248 {"filereadable", 1, 1, f_filereadable},
6249 {"filewritable", 1, 1, f_filewritable},
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00006250 {"filter", 2, 2, f_filter},
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00006251 {"finddir", 1, 3, f_finddir},
6252 {"findfile", 1, 3, f_findfile},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006253 {"fnamemodify", 2, 2, f_fnamemodify},
6254 {"foldclosed", 1, 1, f_foldclosed},
6255 {"foldclosedend", 1, 1, f_foldclosedend},
6256 {"foldlevel", 1, 1, f_foldlevel},
6257 {"foldtext", 0, 0, f_foldtext},
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00006258 {"foldtextresult", 1, 1, f_foldtextresult},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006259 {"foreground", 0, 0, f_foreground},
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006260 {"function", 1, 1, f_function},
Bram Moolenaar0d660222005-01-07 21:51:51 +00006261 {"get", 2, 3, f_get},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006262 {"getbufvar", 2, 2, f_getbufvar},
6263 {"getchar", 0, 1, f_getchar},
6264 {"getcharmod", 0, 0, f_getcharmod},
6265 {"getcmdline", 0, 0, f_getcmdline},
6266 {"getcmdpos", 0, 0, f_getcmdpos},
6267 {"getcwd", 0, 0, f_getcwd},
Bram Moolenaar46c9c732004-12-12 11:37:09 +00006268 {"getfontname", 0, 1, f_getfontname},
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00006269 {"getfperm", 1, 1, f_getfperm},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006270 {"getfsize", 1, 1, f_getfsize},
6271 {"getftime", 1, 1, f_getftime},
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00006272 {"getftype", 1, 1, f_getftype},
Bram Moolenaar0d660222005-01-07 21:51:51 +00006273 {"getline", 1, 2, f_getline},
Bram Moolenaar2641f772005-03-25 21:58:17 +00006274 {"getqflist", 0, 0, f_getqflist},
Bram Moolenaar67fe1a12005-05-22 22:12:58 +00006275 {"getreg", 0, 2, f_getreg},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006276 {"getregtype", 0, 1, f_getregtype},
6277 {"getwinposx", 0, 0, f_getwinposx},
6278 {"getwinposy", 0, 0, f_getwinposy},
6279 {"getwinvar", 2, 2, f_getwinvar},
6280 {"glob", 1, 1, f_glob},
6281 {"globpath", 2, 2, f_globpath},
6282 {"has", 1, 1, f_has},
Bram Moolenaare9a41262005-01-15 22:18:47 +00006283 {"has_key", 2, 2, f_has_key},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006284 {"hasmapto", 1, 2, f_hasmapto},
6285 {"highlightID", 1, 1, f_hlID}, /* obsolete */
6286 {"highlight_exists",1, 1, f_hlexists}, /* obsolete */
6287 {"histadd", 2, 2, f_histadd},
6288 {"histdel", 1, 2, f_histdel},
6289 {"histget", 1, 2, f_histget},
6290 {"histnr", 1, 1, f_histnr},
6291 {"hlID", 1, 1, f_hlID},
6292 {"hlexists", 1, 1, f_hlexists},
6293 {"hostname", 0, 0, f_hostname},
6294 {"iconv", 3, 3, f_iconv},
6295 {"indent", 1, 1, f_indent},
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00006296 {"index", 2, 4, f_index},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006297 {"input", 1, 2, f_input},
6298 {"inputdialog", 1, 3, f_inputdialog},
6299 {"inputrestore", 0, 0, f_inputrestore},
6300 {"inputsave", 0, 0, f_inputsave},
6301 {"inputsecret", 1, 2, f_inputsecret},
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006302 {"insert", 2, 3, f_insert},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006303 {"isdirectory", 1, 1, f_isdirectory},
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00006304 {"islocked", 1, 1, f_islocked},
Bram Moolenaar8c711452005-01-14 21:53:12 +00006305 {"items", 1, 1, f_items},
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00006306 {"join", 1, 2, f_join},
Bram Moolenaar8c711452005-01-14 21:53:12 +00006307 {"keys", 1, 1, f_keys},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006308 {"last_buffer_nr", 0, 0, f_last_buffer_nr},/* obsolete */
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006309 {"len", 1, 1, f_len},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006310 {"libcall", 3, 3, f_libcall},
6311 {"libcallnr", 3, 3, f_libcallnr},
6312 {"line", 1, 1, f_line},
6313 {"line2byte", 1, 1, f_line2byte},
6314 {"lispindent", 1, 1, f_lispindent},
6315 {"localtime", 0, 0, f_localtime},
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00006316 {"map", 2, 2, f_map},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006317 {"maparg", 1, 2, f_maparg},
6318 {"mapcheck", 1, 2, f_mapcheck},
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00006319 {"match", 2, 4, f_match},
6320 {"matchend", 2, 4, f_matchend},
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00006321 {"matchlist", 2, 4, f_matchlist},
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00006322 {"matchstr", 2, 4, f_matchstr},
Bram Moolenaar6cc16192005-01-08 21:49:45 +00006323 {"max", 1, 1, f_max},
6324 {"min", 1, 1, f_min},
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00006325#ifdef vim_mkdir
6326 {"mkdir", 1, 3, f_mkdir},
6327#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00006328 {"mode", 0, 0, f_mode},
6329 {"nextnonblank", 1, 1, f_nextnonblank},
6330 {"nr2char", 1, 1, f_nr2char},
6331 {"prevnonblank", 1, 1, f_prevnonblank},
Bram Moolenaar8c711452005-01-14 21:53:12 +00006332 {"range", 1, 3, f_range},
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00006333 {"readfile", 1, 3, f_readfile},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006334 {"remote_expr", 2, 3, f_remote_expr},
6335 {"remote_foreground", 1, 1, f_remote_foreground},
6336 {"remote_peek", 1, 2, f_remote_peek},
6337 {"remote_read", 1, 1, f_remote_read},
6338 {"remote_send", 2, 3, f_remote_send},
Bram Moolenaar8a283e52005-01-06 23:28:25 +00006339 {"remove", 2, 3, f_remove},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006340 {"rename", 2, 2, f_rename},
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00006341 {"repeat", 2, 2, f_repeat},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006342 {"resolve", 1, 1, f_resolve},
Bram Moolenaar0d660222005-01-07 21:51:51 +00006343 {"reverse", 1, 1, f_reverse},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006344 {"search", 1, 2, f_search},
6345 {"searchpair", 3, 5, f_searchpair},
6346 {"server2client", 2, 2, f_server2client},
6347 {"serverlist", 0, 0, f_serverlist},
6348 {"setbufvar", 3, 3, f_setbufvar},
6349 {"setcmdpos", 1, 1, f_setcmdpos},
6350 {"setline", 2, 2, f_setline},
Bram Moolenaarf4630b62005-05-20 21:31:17 +00006351 {"setqflist", 1, 2, f_setqflist},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006352 {"setreg", 2, 3, f_setreg},
6353 {"setwinvar", 3, 3, f_setwinvar},
6354 {"simplify", 1, 1, f_simplify},
Bram Moolenaar0d660222005-01-07 21:51:51 +00006355 {"sort", 1, 2, f_sort},
Bram Moolenaard857f0e2005-06-21 22:37:39 +00006356 {"spellbadword", 0, 0, f_spellbadword},
6357 {"spellsuggest", 1, 2, f_spellsuggest},
Bram Moolenaar67fe1a12005-05-22 22:12:58 +00006358 {"split", 1, 3, f_split},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006359#ifdef HAVE_STRFTIME
6360 {"strftime", 1, 2, f_strftime},
6361#endif
Bram Moolenaar33570922005-01-25 22:26:29 +00006362 {"stridx", 2, 3, f_stridx},
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006363 {"string", 1, 1, f_string},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006364 {"strlen", 1, 1, f_strlen},
6365 {"strpart", 2, 3, f_strpart},
Bram Moolenaar532c7802005-01-27 14:44:31 +00006366 {"strridx", 2, 3, f_strridx},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006367 {"strtrans", 1, 1, f_strtrans},
6368 {"submatch", 1, 1, f_submatch},
6369 {"substitute", 4, 4, f_substitute},
6370 {"synID", 3, 3, f_synID},
6371 {"synIDattr", 2, 3, f_synIDattr},
6372 {"synIDtrans", 1, 1, f_synIDtrans},
Bram Moolenaarc0197e22004-09-13 20:26:32 +00006373 {"system", 1, 2, f_system},
Bram Moolenaar19a09a12005-03-04 23:39:37 +00006374 {"taglist", 1, 1, f_taglist},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006375 {"tempname", 0, 0, f_tempname},
6376 {"tolower", 1, 1, f_tolower},
6377 {"toupper", 1, 1, f_toupper},
Bram Moolenaar8299df92004-07-10 09:47:34 +00006378 {"tr", 3, 3, f_tr},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006379 {"type", 1, 1, f_type},
Bram Moolenaar8c711452005-01-14 21:53:12 +00006380 {"values", 1, 1, f_values},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006381 {"virtcol", 1, 1, f_virtcol},
6382 {"visualmode", 0, 1, f_visualmode},
6383 {"winbufnr", 1, 1, f_winbufnr},
6384 {"wincol", 0, 0, f_wincol},
6385 {"winheight", 1, 1, f_winheight},
6386 {"winline", 0, 0, f_winline},
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00006387 {"winnr", 0, 1, f_winnr},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006388 {"winrestcmd", 0, 0, f_winrestcmd},
6389 {"winwidth", 1, 1, f_winwidth},
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00006390 {"writefile", 2, 3, f_writefile},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006391};
6392
6393#if defined(FEAT_CMDL_COMPL) || defined(PROTO)
6394
6395/*
6396 * Function given to ExpandGeneric() to obtain the list of internal
6397 * or user defined function names.
6398 */
6399 char_u *
6400get_function_name(xp, idx)
6401 expand_T *xp;
6402 int idx;
6403{
6404 static int intidx = -1;
6405 char_u *name;
6406
6407 if (idx == 0)
6408 intidx = -1;
6409 if (intidx < 0)
6410 {
6411 name = get_user_func_name(xp, idx);
6412 if (name != NULL)
6413 return name;
6414 }
6415 if (++intidx < (int)(sizeof(functions) / sizeof(struct fst)))
6416 {
6417 STRCPY(IObuff, functions[intidx].f_name);
6418 STRCAT(IObuff, "(");
6419 if (functions[intidx].f_max_argc == 0)
6420 STRCAT(IObuff, ")");
6421 return IObuff;
6422 }
6423
6424 return NULL;
6425}
6426
6427/*
6428 * Function given to ExpandGeneric() to obtain the list of internal or
6429 * user defined variable or function names.
6430 */
6431/*ARGSUSED*/
6432 char_u *
6433get_expr_name(xp, idx)
6434 expand_T *xp;
6435 int idx;
6436{
6437 static int intidx = -1;
6438 char_u *name;
6439
6440 if (idx == 0)
6441 intidx = -1;
6442 if (intidx < 0)
6443 {
6444 name = get_function_name(xp, idx);
6445 if (name != NULL)
6446 return name;
6447 }
6448 return get_user_var_name(xp, ++intidx);
6449}
6450
6451#endif /* FEAT_CMDL_COMPL */
6452
6453/*
6454 * Find internal function in table above.
6455 * Return index, or -1 if not found
6456 */
6457 static int
6458find_internal_func(name)
6459 char_u *name; /* name of the function */
6460{
6461 int first = 0;
6462 int last = (int)(sizeof(functions) / sizeof(struct fst)) - 1;
6463 int cmp;
6464 int x;
6465
6466 /*
6467 * Find the function name in the table. Binary search.
6468 */
6469 while (first <= last)
6470 {
6471 x = first + ((unsigned)(last - first) >> 1);
6472 cmp = STRCMP(name, functions[x].f_name);
6473 if (cmp < 0)
6474 last = x - 1;
6475 else if (cmp > 0)
6476 first = x + 1;
6477 else
6478 return x;
6479 }
6480 return -1;
6481}
6482
6483/*
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006484 * Check if "name" is a variable of type VAR_FUNC. If so, return the function
6485 * name it contains, otherwise return "name".
6486 */
6487 static char_u *
6488deref_func_name(name, lenp)
6489 char_u *name;
6490 int *lenp;
6491{
Bram Moolenaar33570922005-01-25 22:26:29 +00006492 dictitem_T *v;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006493 int cc;
6494
6495 cc = name[*lenp];
6496 name[*lenp] = NUL;
Bram Moolenaara7043832005-01-21 11:56:39 +00006497 v = find_var(name, NULL);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006498 name[*lenp] = cc;
Bram Moolenaar33570922005-01-25 22:26:29 +00006499 if (v != NULL && v->di_tv.v_type == VAR_FUNC)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006500 {
Bram Moolenaar33570922005-01-25 22:26:29 +00006501 if (v->di_tv.vval.v_string == NULL)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006502 {
6503 *lenp = 0;
6504 return (char_u *)""; /* just in case */
6505 }
Bram Moolenaar33570922005-01-25 22:26:29 +00006506 *lenp = STRLEN(v->di_tv.vval.v_string);
6507 return v->di_tv.vval.v_string;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006508 }
6509
6510 return name;
6511}
6512
6513/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00006514 * Allocate a variable for the result of a function.
6515 * Return OK or FAIL.
6516 */
6517 static int
Bram Moolenaare9a41262005-01-15 22:18:47 +00006518get_func_tv(name, len, rettv, arg, firstline, lastline, doesrange,
6519 evaluate, selfdict)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006520 char_u *name; /* name of the function */
6521 int len; /* length of "name" */
Bram Moolenaar33570922005-01-25 22:26:29 +00006522 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006523 char_u **arg; /* argument, pointing to the '(' */
6524 linenr_T firstline; /* first line of range */
6525 linenr_T lastline; /* last line of range */
6526 int *doesrange; /* return: function handled range */
6527 int evaluate;
Bram Moolenaar33570922005-01-25 22:26:29 +00006528 dict_T *selfdict; /* Dictionary for "self" */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006529{
6530 char_u *argp;
6531 int ret = OK;
Bram Moolenaar33570922005-01-25 22:26:29 +00006532 typval_T argvars[MAX_FUNC_ARGS]; /* vars for arguments */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006533 int argcount = 0; /* number of arguments found */
6534
6535 /*
6536 * Get the arguments.
6537 */
6538 argp = *arg;
6539 while (argcount < MAX_FUNC_ARGS)
6540 {
6541 argp = skipwhite(argp + 1); /* skip the '(' or ',' */
6542 if (*argp == ')' || *argp == ',' || *argp == NUL)
6543 break;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006544 if (eval1(&argp, &argvars[argcount], evaluate) == FAIL)
6545 {
6546 ret = FAIL;
6547 break;
6548 }
6549 ++argcount;
6550 if (*argp != ',')
6551 break;
6552 }
6553 if (*argp == ')')
6554 ++argp;
6555 else
6556 ret = FAIL;
6557
6558 if (ret == OK)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006559 ret = call_func(name, len, rettv, argcount, argvars,
Bram Moolenaare9a41262005-01-15 22:18:47 +00006560 firstline, lastline, doesrange, evaluate, selfdict);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006561 else if (!aborting())
Bram Moolenaar33570922005-01-25 22:26:29 +00006562 {
6563 if (argcount == MAX_FUNC_ARGS)
Bram Moolenaar81bf7082005-02-12 14:31:42 +00006564 emsg_funcname("E740: Too many arguments for function %s", name);
Bram Moolenaar33570922005-01-25 22:26:29 +00006565 else
Bram Moolenaar81bf7082005-02-12 14:31:42 +00006566 emsg_funcname("E116: Invalid arguments for function %s", name);
Bram Moolenaar33570922005-01-25 22:26:29 +00006567 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00006568
6569 while (--argcount >= 0)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006570 clear_tv(&argvars[argcount]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006571
6572 *arg = skipwhite(argp);
6573 return ret;
6574}
6575
6576
6577/*
6578 * Call a function with its resolved parameters
6579 * Return OK or FAIL.
6580 */
6581 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006582call_func(name, len, rettv, argcount, argvars, firstline, lastline,
Bram Moolenaare9a41262005-01-15 22:18:47 +00006583 doesrange, evaluate, selfdict)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006584 char_u *name; /* name of the function */
6585 int len; /* length of "name" */
Bram Moolenaar33570922005-01-25 22:26:29 +00006586 typval_T *rettv; /* return value goes here */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006587 int argcount; /* number of "argvars" */
Bram Moolenaar33570922005-01-25 22:26:29 +00006588 typval_T *argvars; /* vars for arguments */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006589 linenr_T firstline; /* first line of range */
6590 linenr_T lastline; /* last line of range */
6591 int *doesrange; /* return: function handled range */
6592 int evaluate;
Bram Moolenaar33570922005-01-25 22:26:29 +00006593 dict_T *selfdict; /* Dictionary for "self" */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006594{
6595 int ret = FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006596#define ERROR_UNKNOWN 0
6597#define ERROR_TOOMANY 1
6598#define ERROR_TOOFEW 2
6599#define ERROR_SCRIPT 3
Bram Moolenaare9a41262005-01-15 22:18:47 +00006600#define ERROR_DICT 4
6601#define ERROR_NONE 5
6602#define ERROR_OTHER 6
Bram Moolenaar071d4272004-06-13 20:20:40 +00006603 int error = ERROR_NONE;
6604 int i;
6605 int llen;
6606 ufunc_T *fp;
6607 int cc;
6608#define FLEN_FIXED 40
6609 char_u fname_buf[FLEN_FIXED + 1];
6610 char_u *fname;
6611
6612 /*
6613 * In a script change <SID>name() and s:name() to K_SNR 123_name().
6614 * Change <SNR>123_name() to K_SNR 123_name().
6615 * Use fname_buf[] when it fits, otherwise allocate memory (slow).
6616 */
6617 cc = name[len];
6618 name[len] = NUL;
6619 llen = eval_fname_script(name);
6620 if (llen > 0)
6621 {
6622 fname_buf[0] = K_SPECIAL;
6623 fname_buf[1] = KS_EXTRA;
6624 fname_buf[2] = (int)KE_SNR;
6625 i = 3;
6626 if (eval_fname_sid(name)) /* "<SID>" or "s:" */
6627 {
6628 if (current_SID <= 0)
6629 error = ERROR_SCRIPT;
6630 else
6631 {
6632 sprintf((char *)fname_buf + 3, "%ld_", (long)current_SID);
6633 i = (int)STRLEN(fname_buf);
6634 }
6635 }
6636 if (i + STRLEN(name + llen) < FLEN_FIXED)
6637 {
6638 STRCPY(fname_buf + i, name + llen);
6639 fname = fname_buf;
6640 }
6641 else
6642 {
6643 fname = alloc((unsigned)(i + STRLEN(name + llen) + 1));
6644 if (fname == NULL)
6645 error = ERROR_OTHER;
6646 else
6647 {
6648 mch_memmove(fname, fname_buf, (size_t)i);
6649 STRCPY(fname + i, name + llen);
6650 }
6651 }
6652 }
6653 else
6654 fname = name;
6655
6656 *doesrange = FALSE;
6657
6658
6659 /* execute the function if no errors detected and executing */
6660 if (evaluate && error == ERROR_NONE)
6661 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006662 rettv->v_type = VAR_NUMBER; /* default is number rettv */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006663 error = ERROR_UNKNOWN;
6664
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +00006665 if (!builtin_function(fname))
Bram Moolenaar071d4272004-06-13 20:20:40 +00006666 {
6667 /*
6668 * User defined function.
6669 */
6670 fp = find_func(fname);
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +00006671
Bram Moolenaar071d4272004-06-13 20:20:40 +00006672#ifdef FEAT_AUTOCMD
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +00006673 /* Trigger FuncUndefined event, may load the function. */
6674 if (fp == NULL
6675 && apply_autocmds(EVENT_FUNCUNDEFINED,
6676 fname, fname, TRUE, NULL)
6677 && !aborting())
Bram Moolenaar071d4272004-06-13 20:20:40 +00006678 {
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +00006679 /* executed an autocommand, search for the function again */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006680 fp = find_func(fname);
6681 }
6682#endif
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +00006683 /* Try loading a package. */
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00006684 if (fp == NULL && script_autoload(fname) && !aborting())
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +00006685 {
6686 /* loaded a package, search for the function again */
6687 fp = find_func(fname);
6688 }
6689
Bram Moolenaar071d4272004-06-13 20:20:40 +00006690 if (fp != NULL)
6691 {
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00006692 if (fp->uf_flags & FC_RANGE)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006693 *doesrange = TRUE;
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00006694 if (argcount < fp->uf_args.ga_len)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006695 error = ERROR_TOOFEW;
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00006696 else if (!fp->uf_varargs && argcount > fp->uf_args.ga_len)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006697 error = ERROR_TOOMANY;
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00006698 else if ((fp->uf_flags & FC_DICT) && selfdict == NULL)
Bram Moolenaare9a41262005-01-15 22:18:47 +00006699 error = ERROR_DICT;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006700 else
6701 {
6702 /*
6703 * Call the user function.
6704 * Save and restore search patterns, script variables and
6705 * redo buffer.
6706 */
6707 save_search_patterns();
6708 saveRedobuff();
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00006709 ++fp->uf_calls;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006710 call_user_func(fp, argcount, argvars, rettv,
Bram Moolenaare9a41262005-01-15 22:18:47 +00006711 firstline, lastline,
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00006712 (fp->uf_flags & FC_DICT) ? selfdict : NULL);
6713 if (--fp->uf_calls <= 0 && isdigit(*fp->uf_name)
6714 && fp->uf_refcount <= 0)
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00006715 /* Function was unreferenced while being used, free it
6716 * now. */
6717 func_free(fp);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006718 restoreRedobuff();
6719 restore_search_patterns();
6720 error = ERROR_NONE;
6721 }
6722 }
6723 }
6724 else
6725 {
6726 /*
6727 * Find the function name in the table, call its implementation.
6728 */
6729 i = find_internal_func(fname);
6730 if (i >= 0)
6731 {
6732 if (argcount < functions[i].f_min_argc)
6733 error = ERROR_TOOFEW;
6734 else if (argcount > functions[i].f_max_argc)
6735 error = ERROR_TOOMANY;
6736 else
6737 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006738 argvars[argcount].v_type = VAR_UNKNOWN;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006739 functions[i].f_func(argvars, rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006740 error = ERROR_NONE;
6741 }
6742 }
6743 }
6744 /*
6745 * The function call (or "FuncUndefined" autocommand sequence) might
6746 * have been aborted by an error, an interrupt, or an explicitly thrown
6747 * exception that has not been caught so far. This situation can be
6748 * tested for by calling aborting(). For an error in an internal
6749 * function or for the "E132" error in call_user_func(), however, the
6750 * throw point at which the "force_abort" flag (temporarily reset by
6751 * emsg()) is normally updated has not been reached yet. We need to
6752 * update that flag first to make aborting() reliable.
6753 */
6754 update_force_abort();
6755 }
6756 if (error == ERROR_NONE)
6757 ret = OK;
6758
6759 /*
6760 * Report an error unless the argument evaluation or function call has been
6761 * cancelled due to an aborting error, an interrupt, or an exception.
6762 */
Bram Moolenaar8c711452005-01-14 21:53:12 +00006763 if (!aborting())
6764 {
6765 switch (error)
6766 {
6767 case ERROR_UNKNOWN:
Bram Moolenaar81bf7082005-02-12 14:31:42 +00006768 emsg_funcname("E117: Unknown function: %s", name);
Bram Moolenaar8c711452005-01-14 21:53:12 +00006769 break;
6770 case ERROR_TOOMANY:
Bram Moolenaar81bf7082005-02-12 14:31:42 +00006771 emsg_funcname(e_toomanyarg, name);
Bram Moolenaar8c711452005-01-14 21:53:12 +00006772 break;
6773 case ERROR_TOOFEW:
Bram Moolenaar81bf7082005-02-12 14:31:42 +00006774 emsg_funcname("E119: Not enough arguments for function: %s",
Bram Moolenaar8c711452005-01-14 21:53:12 +00006775 name);
6776 break;
6777 case ERROR_SCRIPT:
Bram Moolenaar81bf7082005-02-12 14:31:42 +00006778 emsg_funcname("E120: Using <SID> not in a script context: %s",
Bram Moolenaar8c711452005-01-14 21:53:12 +00006779 name);
6780 break;
Bram Moolenaare9a41262005-01-15 22:18:47 +00006781 case ERROR_DICT:
Bram Moolenaar81bf7082005-02-12 14:31:42 +00006782 emsg_funcname("E725: Calling dict function without Dictionary: %s",
Bram Moolenaare9a41262005-01-15 22:18:47 +00006783 name);
6784 break;
Bram Moolenaar8c711452005-01-14 21:53:12 +00006785 }
6786 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00006787
6788 name[len] = cc;
6789 if (fname != name && fname != fname_buf)
6790 vim_free(fname);
6791
6792 return ret;
6793}
6794
Bram Moolenaar81bf7082005-02-12 14:31:42 +00006795/*
6796 * Give an error message with a function name. Handle <SNR> things.
6797 */
6798 static void
6799emsg_funcname(msg, name)
6800 char *msg;
6801 char_u *name;
6802{
6803 char_u *p;
6804
6805 if (*name == K_SPECIAL)
6806 p = concat_str((char_u *)"<SNR>", name + 3);
6807 else
6808 p = name;
6809 EMSG2(_(msg), p);
6810 if (p != name)
6811 vim_free(p);
6812}
6813
Bram Moolenaar071d4272004-06-13 20:20:40 +00006814/*********************************************
6815 * Implementation of the built-in functions
6816 */
6817
6818/*
Bram Moolenaar0d660222005-01-07 21:51:51 +00006819 * "add(list, item)" function
Bram Moolenaar071d4272004-06-13 20:20:40 +00006820 */
6821 static void
Bram Moolenaar0d660222005-01-07 21:51:51 +00006822f_add(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00006823 typval_T *argvars;
6824 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006825{
Bram Moolenaar33570922005-01-25 22:26:29 +00006826 list_T *l;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006827
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006828 rettv->vval.v_number = 1; /* Default: Failed */
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006829 if (argvars[0].v_type == VAR_LIST)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006830 {
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00006831 if ((l = argvars[0].vval.v_list) != NULL
6832 && !tv_check_lock(l->lv_lock, (char_u *)"add()")
6833 && list_append_tv(l, &argvars[1]) == OK)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006834 copy_tv(&argvars[0], rettv);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006835 }
6836 else
Bram Moolenaar0d660222005-01-07 21:51:51 +00006837 EMSG(_(e_listreq));
6838}
6839
6840/*
6841 * "append(lnum, string/list)" function
6842 */
6843 static void
6844f_append(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00006845 typval_T *argvars;
6846 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +00006847{
6848 long lnum;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00006849 char_u *line;
Bram Moolenaar33570922005-01-25 22:26:29 +00006850 list_T *l = NULL;
6851 listitem_T *li = NULL;
6852 typval_T *tv;
Bram Moolenaar0d660222005-01-07 21:51:51 +00006853 long added = 0;
6854
Bram Moolenaar0d660222005-01-07 21:51:51 +00006855 lnum = get_tv_lnum(argvars);
6856 if (lnum >= 0
6857 && lnum <= curbuf->b_ml.ml_line_count
6858 && u_save(lnum, lnum + 1) == OK)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006859 {
Bram Moolenaar0d660222005-01-07 21:51:51 +00006860 if (argvars[1].v_type == VAR_LIST)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006861 {
Bram Moolenaar0d660222005-01-07 21:51:51 +00006862 l = argvars[1].vval.v_list;
6863 if (l == NULL)
6864 return;
6865 li = l->lv_first;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006866 }
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00006867 rettv->vval.v_number = 0; /* Default: Success */
Bram Moolenaar0d660222005-01-07 21:51:51 +00006868 for (;;)
6869 {
6870 if (l == NULL)
6871 tv = &argvars[1]; /* append a string */
6872 else if (li == NULL)
6873 break; /* end of list */
6874 else
6875 tv = &li->li_tv; /* append item from list */
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00006876 line = get_tv_string_chk(tv);
6877 if (line == NULL) /* type error */
6878 {
6879 rettv->vval.v_number = 1; /* Failed */
6880 break;
6881 }
6882 ml_append(lnum + added, line, (colnr_T)0, FALSE);
Bram Moolenaar0d660222005-01-07 21:51:51 +00006883 ++added;
6884 if (l == NULL)
6885 break;
6886 li = li->li_next;
6887 }
6888
6889 appended_lines_mark(lnum, added);
6890 if (curwin->w_cursor.lnum > lnum)
6891 curwin->w_cursor.lnum += added;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006892 }
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00006893 else
6894 rettv->vval.v_number = 1; /* Failed */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006895}
6896
6897/*
6898 * "argc()" function
6899 */
6900/* ARGSUSED */
6901 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006902f_argc(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00006903 typval_T *argvars;
6904 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006905{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006906 rettv->vval.v_number = ARGCOUNT;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006907}
6908
6909/*
6910 * "argidx()" function
6911 */
6912/* ARGSUSED */
6913 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006914f_argidx(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00006915 typval_T *argvars;
6916 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006917{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006918 rettv->vval.v_number = curwin->w_arg_idx;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006919}
6920
6921/*
6922 * "argv(nr)" function
6923 */
6924 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006925f_argv(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00006926 typval_T *argvars;
6927 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006928{
6929 int idx;
6930
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00006931 idx = get_tv_number_chk(&argvars[0], NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006932 if (idx >= 0 && idx < ARGCOUNT)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006933 rettv->vval.v_string = vim_strsave(alist_name(&ARGLIST[idx]));
Bram Moolenaar071d4272004-06-13 20:20:40 +00006934 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006935 rettv->vval.v_string = NULL;
6936 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006937}
6938
6939/*
6940 * "browse(save, title, initdir, default)" function
6941 */
6942/* ARGSUSED */
6943 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006944f_browse(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00006945 typval_T *argvars;
6946 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006947{
6948#ifdef FEAT_BROWSE
6949 int save;
6950 char_u *title;
6951 char_u *initdir;
6952 char_u *defname;
6953 char_u buf[NUMBUFLEN];
6954 char_u buf2[NUMBUFLEN];
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00006955 int error = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006956
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00006957 save = get_tv_number_chk(&argvars[0], &error);
6958 title = get_tv_string_chk(&argvars[1]);
6959 initdir = get_tv_string_buf_chk(&argvars[2], buf);
6960 defname = get_tv_string_buf_chk(&argvars[3], buf2);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006961
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00006962 if (error || title == NULL || initdir == NULL || defname == NULL)
6963 rettv->vval.v_string = NULL;
6964 else
6965 rettv->vval.v_string =
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00006966 do_browse(save ? BROWSE_SAVE : 0,
6967 title, defname, NULL, initdir, NULL, curbuf);
6968#else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006969 rettv->vval.v_string = NULL;
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00006970#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006971 rettv->v_type = VAR_STRING;
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00006972}
6973
6974/*
6975 * "browsedir(title, initdir)" function
6976 */
6977/* ARGSUSED */
6978 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006979f_browsedir(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00006980 typval_T *argvars;
6981 typval_T *rettv;
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00006982{
6983#ifdef FEAT_BROWSE
6984 char_u *title;
6985 char_u *initdir;
6986 char_u buf[NUMBUFLEN];
6987
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00006988 title = get_tv_string_chk(&argvars[0]);
6989 initdir = get_tv_string_buf_chk(&argvars[1], buf);
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00006990
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00006991 if (title == NULL || initdir == NULL)
6992 rettv->vval.v_string = NULL;
6993 else
6994 rettv->vval.v_string = do_browse(BROWSE_DIR,
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00006995 title, NULL, NULL, initdir, NULL, curbuf);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006996#else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006997 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006998#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006999 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007000}
7001
Bram Moolenaar33570922005-01-25 22:26:29 +00007002static buf_T *find_buffer __ARGS((typval_T *avar));
Bram Moolenaar0d660222005-01-07 21:51:51 +00007003
Bram Moolenaar071d4272004-06-13 20:20:40 +00007004/*
7005 * Find a buffer by number or exact name.
7006 */
7007 static buf_T *
7008find_buffer(avar)
Bram Moolenaar33570922005-01-25 22:26:29 +00007009 typval_T *avar;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007010{
7011 buf_T *buf = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007012
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007013 if (avar->v_type == VAR_NUMBER)
7014 buf = buflist_findnr((int)avar->vval.v_number);
Bram Moolenaar758711c2005-02-02 23:11:38 +00007015 else if (avar->v_type == VAR_STRING && avar->vval.v_string != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007016 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007017 buf = buflist_findname_exp(avar->vval.v_string);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00007018 if (buf == NULL)
7019 {
7020 /* No full path name match, try a match with a URL or a "nofile"
7021 * buffer, these don't use the full path. */
7022 for (buf = firstbuf; buf != NULL; buf = buf->b_next)
7023 if (buf->b_fname != NULL
7024 && (path_with_url(buf->b_fname)
7025#ifdef FEAT_QUICKFIX
7026 || bt_nofile(buf)
7027#endif
7028 )
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007029 && STRCMP(buf->b_fname, avar->vval.v_string) == 0)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00007030 break;
7031 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00007032 }
7033 return buf;
7034}
7035
7036/*
7037 * "bufexists(expr)" function
7038 */
7039 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007040f_bufexists(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007041 typval_T *argvars;
7042 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007043{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007044 rettv->vval.v_number = (find_buffer(&argvars[0]) != NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007045}
7046
7047/*
7048 * "buflisted(expr)" function
7049 */
7050 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007051f_buflisted(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007052 typval_T *argvars;
7053 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007054{
7055 buf_T *buf;
7056
7057 buf = find_buffer(&argvars[0]);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007058 rettv->vval.v_number = (buf != NULL && buf->b_p_bl);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007059}
7060
7061/*
7062 * "bufloaded(expr)" function
7063 */
7064 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007065f_bufloaded(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007066 typval_T *argvars;
7067 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007068{
7069 buf_T *buf;
7070
7071 buf = find_buffer(&argvars[0]);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007072 rettv->vval.v_number = (buf != NULL && buf->b_ml.ml_mfp != NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007073}
7074
Bram Moolenaar33570922005-01-25 22:26:29 +00007075static buf_T *get_buf_tv __ARGS((typval_T *tv));
Bram Moolenaar0d660222005-01-07 21:51:51 +00007076
Bram Moolenaar071d4272004-06-13 20:20:40 +00007077/*
7078 * Get buffer by number or pattern.
7079 */
7080 static buf_T *
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007081get_buf_tv(tv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007082 typval_T *tv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007083{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007084 char_u *name = tv->vval.v_string;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007085 int save_magic;
7086 char_u *save_cpo;
7087 buf_T *buf;
7088
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007089 if (tv->v_type == VAR_NUMBER)
7090 return buflist_findnr((int)tv->vval.v_number);
Bram Moolenaar758711c2005-02-02 23:11:38 +00007091 if (tv->v_type != VAR_STRING)
7092 return NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007093 if (name == NULL || *name == NUL)
7094 return curbuf;
7095 if (name[0] == '$' && name[1] == NUL)
7096 return lastbuf;
7097
7098 /* Ignore 'magic' and 'cpoptions' here to make scripts portable */
7099 save_magic = p_magic;
7100 p_magic = TRUE;
7101 save_cpo = p_cpo;
7102 p_cpo = (char_u *)"";
7103
7104 buf = buflist_findnr(buflist_findpat(name, name + STRLEN(name),
7105 TRUE, FALSE));
7106
7107 p_magic = save_magic;
7108 p_cpo = save_cpo;
7109
7110 /* If not found, try expanding the name, like done for bufexists(). */
7111 if (buf == NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007112 buf = find_buffer(tv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007113
7114 return buf;
7115}
7116
7117/*
7118 * "bufname(expr)" function
7119 */
7120 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007121f_bufname(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007122 typval_T *argvars;
7123 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007124{
7125 buf_T *buf;
7126
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00007127 (void)get_tv_number(&argvars[0]); /* issue errmsg if type error */
Bram Moolenaar071d4272004-06-13 20:20:40 +00007128 ++emsg_off;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007129 buf = get_buf_tv(&argvars[0]);
7130 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007131 if (buf != NULL && buf->b_fname != NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007132 rettv->vval.v_string = vim_strsave(buf->b_fname);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007133 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007134 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007135 --emsg_off;
7136}
7137
7138/*
7139 * "bufnr(expr)" function
7140 */
7141 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007142f_bufnr(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007143 typval_T *argvars;
7144 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007145{
7146 buf_T *buf;
7147
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00007148 (void)get_tv_number(&argvars[0]); /* issue errmsg if type error */
Bram Moolenaar071d4272004-06-13 20:20:40 +00007149 ++emsg_off;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007150 buf = get_buf_tv(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007151 if (buf != NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007152 rettv->vval.v_number = buf->b_fnum;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007153 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007154 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007155 --emsg_off;
7156}
7157
7158/*
7159 * "bufwinnr(nr)" function
7160 */
7161 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007162f_bufwinnr(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007163 typval_T *argvars;
7164 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007165{
7166#ifdef FEAT_WINDOWS
7167 win_T *wp;
7168 int winnr = 0;
7169#endif
7170 buf_T *buf;
7171
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00007172 (void)get_tv_number(&argvars[0]); /* issue errmsg if type error */
Bram Moolenaar071d4272004-06-13 20:20:40 +00007173 ++emsg_off;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007174 buf = get_buf_tv(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007175#ifdef FEAT_WINDOWS
7176 for (wp = firstwin; wp; wp = wp->w_next)
7177 {
7178 ++winnr;
7179 if (wp->w_buffer == buf)
7180 break;
7181 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007182 rettv->vval.v_number = (wp != NULL ? winnr : -1);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007183#else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007184 rettv->vval.v_number = (curwin->w_buffer == buf ? 1 : -1);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007185#endif
7186 --emsg_off;
7187}
7188
7189/*
7190 * "byte2line(byte)" function
7191 */
7192/*ARGSUSED*/
7193 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007194f_byte2line(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007195 typval_T *argvars;
7196 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007197{
7198#ifndef FEAT_BYTEOFF
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007199 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007200#else
7201 long boff = 0;
7202
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00007203 boff = get_tv_number(&argvars[0]) - 1; /* boff gets -1 on type error */
Bram Moolenaar071d4272004-06-13 20:20:40 +00007204 if (boff < 0)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007205 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007206 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007207 rettv->vval.v_number = ml_find_line_or_offset(curbuf,
Bram Moolenaar071d4272004-06-13 20:20:40 +00007208 (linenr_T)0, &boff);
7209#endif
7210}
7211
7212/*
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00007213 * "byteidx()" function
7214 */
7215/*ARGSUSED*/
7216 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007217f_byteidx(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007218 typval_T *argvars;
7219 typval_T *rettv;
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00007220{
7221#ifdef FEAT_MBYTE
7222 char_u *t;
7223#endif
7224 char_u *str;
7225 long idx;
7226
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00007227 str = get_tv_string_chk(&argvars[0]);
7228 idx = get_tv_number_chk(&argvars[1], NULL);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007229 rettv->vval.v_number = -1;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00007230 if (str == NULL || idx < 0)
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00007231 return;
7232
7233#ifdef FEAT_MBYTE
7234 t = str;
7235 for ( ; idx > 0; idx--)
7236 {
7237 if (*t == NUL) /* EOL reached */
7238 return;
7239 t += mb_ptr2len_check(t);
7240 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007241 rettv->vval.v_number = t - str;
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00007242#else
7243 if (idx <= STRLEN(str))
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007244 rettv->vval.v_number = idx;
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00007245#endif
7246}
7247
7248/*
Bram Moolenaar8a283e52005-01-06 23:28:25 +00007249 * "call(func, arglist)" function
7250 */
7251 static void
7252f_call(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007253 typval_T *argvars;
7254 typval_T *rettv;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00007255{
7256 char_u *func;
Bram Moolenaar33570922005-01-25 22:26:29 +00007257 typval_T argv[MAX_FUNC_ARGS];
Bram Moolenaar8a283e52005-01-06 23:28:25 +00007258 int argc = 0;
Bram Moolenaar33570922005-01-25 22:26:29 +00007259 listitem_T *item;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00007260 int dummy;
Bram Moolenaar33570922005-01-25 22:26:29 +00007261 dict_T *selfdict = NULL;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00007262
7263 rettv->vval.v_number = 0;
7264 if (argvars[1].v_type != VAR_LIST)
7265 {
7266 EMSG(_(e_listreq));
7267 return;
7268 }
7269 if (argvars[1].vval.v_list == NULL)
7270 return;
7271
7272 if (argvars[0].v_type == VAR_FUNC)
7273 func = argvars[0].vval.v_string;
7274 else
7275 func = get_tv_string(&argvars[0]);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00007276 if (*func == NUL)
7277 return; /* type error or empty name */
Bram Moolenaar8a283e52005-01-06 23:28:25 +00007278
Bram Moolenaare9a41262005-01-15 22:18:47 +00007279 if (argvars[2].v_type != VAR_UNKNOWN)
7280 {
7281 if (argvars[2].v_type != VAR_DICT)
7282 {
7283 EMSG(_(e_dictreq));
7284 return;
7285 }
7286 selfdict = argvars[2].vval.v_dict;
7287 }
7288
Bram Moolenaar8a283e52005-01-06 23:28:25 +00007289 for (item = argvars[1].vval.v_list->lv_first; item != NULL;
7290 item = item->li_next)
7291 {
7292 if (argc == MAX_FUNC_ARGS)
7293 {
Bram Moolenaare49b69a2005-01-08 16:11:57 +00007294 EMSG(_("E699: Too many arguments"));
Bram Moolenaar8a283e52005-01-06 23:28:25 +00007295 break;
7296 }
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00007297 /* Make a copy of each argument. This is needed to be able to set
7298 * v_lock to VAR_FIXED in the copy without changing the original list.
7299 */
Bram Moolenaar8a283e52005-01-06 23:28:25 +00007300 copy_tv(&item->li_tv, &argv[argc++]);
7301 }
7302
7303 if (item == NULL)
7304 (void)call_func(func, STRLEN(func), rettv, argc, argv,
Bram Moolenaare9a41262005-01-15 22:18:47 +00007305 curwin->w_cursor.lnum, curwin->w_cursor.lnum,
7306 &dummy, TRUE, selfdict);
Bram Moolenaar8a283e52005-01-06 23:28:25 +00007307
7308 /* Free the arguments. */
7309 while (argc > 0)
7310 clear_tv(&argv[--argc]);
7311}
7312
7313/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00007314 * "char2nr(string)" function
7315 */
7316 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007317f_char2nr(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007318 typval_T *argvars;
7319 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007320{
7321#ifdef FEAT_MBYTE
7322 if (has_mbyte)
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00007323 rettv->vval.v_number = (*mb_ptr2char)(get_tv_string(&argvars[0]));
Bram Moolenaar071d4272004-06-13 20:20:40 +00007324 else
7325#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007326 rettv->vval.v_number = get_tv_string(&argvars[0])[0];
Bram Moolenaar071d4272004-06-13 20:20:40 +00007327}
7328
7329/*
7330 * "cindent(lnum)" function
7331 */
7332 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007333f_cindent(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007334 typval_T *argvars;
7335 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007336{
7337#ifdef FEAT_CINDENT
7338 pos_T pos;
7339 linenr_T lnum;
7340
7341 pos = curwin->w_cursor;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007342 lnum = get_tv_lnum(argvars);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007343 if (lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count)
7344 {
7345 curwin->w_cursor.lnum = lnum;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007346 rettv->vval.v_number = get_c_indent();
Bram Moolenaar071d4272004-06-13 20:20:40 +00007347 curwin->w_cursor = pos;
7348 }
7349 else
7350#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007351 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007352}
7353
7354/*
7355 * "col(string)" function
7356 */
7357 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007358f_col(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007359 typval_T *argvars;
7360 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007361{
7362 colnr_T col = 0;
7363 pos_T *fp;
7364
7365 fp = var2fpos(&argvars[0], FALSE);
7366 if (fp != NULL)
7367 {
7368 if (fp->col == MAXCOL)
7369 {
7370 /* '> can be MAXCOL, get the length of the line then */
7371 if (fp->lnum <= curbuf->b_ml.ml_line_count)
7372 col = STRLEN(ml_get(fp->lnum)) + 1;
7373 else
7374 col = MAXCOL;
7375 }
7376 else
7377 {
7378 col = fp->col + 1;
7379#ifdef FEAT_VIRTUALEDIT
7380 /* col(".") when the cursor is on the NUL at the end of the line
7381 * because of "coladd" can be seen as an extra column. */
7382 if (virtual_active() && fp == &curwin->w_cursor)
7383 {
7384 char_u *p = ml_get_cursor();
7385
7386 if (curwin->w_cursor.coladd >= (colnr_T)chartabsize(p,
7387 curwin->w_virtcol - curwin->w_cursor.coladd))
7388 {
7389# ifdef FEAT_MBYTE
7390 int l;
7391
7392 if (*p != NUL && p[(l = (*mb_ptr2len_check)(p))] == NUL)
7393 col += l;
7394# else
7395 if (*p != NUL && p[1] == NUL)
7396 ++col;
7397# endif
7398 }
7399 }
7400#endif
7401 }
7402 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007403 rettv->vval.v_number = col;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007404}
7405
7406/*
7407 * "confirm(message, buttons[, default [, type]])" function
7408 */
7409/*ARGSUSED*/
7410 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007411f_confirm(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007412 typval_T *argvars;
7413 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007414{
7415#if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
7416 char_u *message;
7417 char_u *buttons = NULL;
7418 char_u buf[NUMBUFLEN];
7419 char_u buf2[NUMBUFLEN];
7420 int def = 1;
7421 int type = VIM_GENERIC;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00007422 char_u *typestr;
7423 int error = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007424
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00007425 message = get_tv_string_chk(&argvars[0]);
7426 if (message == NULL)
7427 error = TRUE;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007428 if (argvars[1].v_type != VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007429 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00007430 buttons = get_tv_string_buf_chk(&argvars[1], buf);
7431 if (buttons == NULL)
7432 error = TRUE;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007433 if (argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007434 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00007435 def = get_tv_number_chk(&argvars[2], &error);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007436 if (argvars[3].v_type != VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007437 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00007438 typestr = get_tv_string_buf_chk(&argvars[3], buf2);
7439 if (typestr == NULL)
7440 error = TRUE;
7441 else
Bram Moolenaar071d4272004-06-13 20:20:40 +00007442 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00007443 switch (TOUPPER_ASC(*typestr))
7444 {
7445 case 'E': type = VIM_ERROR; break;
7446 case 'Q': type = VIM_QUESTION; break;
7447 case 'I': type = VIM_INFO; break;
7448 case 'W': type = VIM_WARNING; break;
7449 case 'G': type = VIM_GENERIC; break;
7450 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00007451 }
7452 }
7453 }
7454 }
7455
7456 if (buttons == NULL || *buttons == NUL)
7457 buttons = (char_u *)_("&Ok");
7458
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00007459 if (error)
7460 rettv->vval.v_number = 0;
7461 else
7462 rettv->vval.v_number = do_dialog(type, NULL, message, buttons,
Bram Moolenaar071d4272004-06-13 20:20:40 +00007463 def, NULL);
7464#else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007465 rettv->vval.v_number = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007466#endif
7467}
7468
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007469/*
7470 * "copy()" function
7471 */
7472 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007473f_copy(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007474 typval_T *argvars;
7475 typval_T *rettv;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007476{
Bram Moolenaar81bf7082005-02-12 14:31:42 +00007477 item_copy(&argvars[0], rettv, FALSE, 0);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007478}
Bram Moolenaar071d4272004-06-13 20:20:40 +00007479
7480/*
Bram Moolenaar8a283e52005-01-06 23:28:25 +00007481 * "count()" function
7482 */
7483 static void
7484f_count(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007485 typval_T *argvars;
7486 typval_T *rettv;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00007487{
Bram Moolenaar8a283e52005-01-06 23:28:25 +00007488 long n = 0;
7489 int ic = FALSE;
7490
Bram Moolenaare9a41262005-01-15 22:18:47 +00007491 if (argvars[0].v_type == VAR_LIST)
Bram Moolenaar8a283e52005-01-06 23:28:25 +00007492 {
Bram Moolenaar33570922005-01-25 22:26:29 +00007493 listitem_T *li;
7494 list_T *l;
Bram Moolenaare9a41262005-01-15 22:18:47 +00007495 long idx;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00007496
Bram Moolenaare9a41262005-01-15 22:18:47 +00007497 if ((l = argvars[0].vval.v_list) != NULL)
7498 {
7499 li = l->lv_first;
7500 if (argvars[2].v_type != VAR_UNKNOWN)
7501 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00007502 int error = FALSE;
7503
7504 ic = get_tv_number_chk(&argvars[2], &error);
Bram Moolenaare9a41262005-01-15 22:18:47 +00007505 if (argvars[3].v_type != VAR_UNKNOWN)
7506 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00007507 idx = get_tv_number_chk(&argvars[3], &error);
7508 if (!error)
7509 {
7510 li = list_find(l, idx);
7511 if (li == NULL)
7512 EMSGN(_(e_listidx), idx);
7513 }
Bram Moolenaare9a41262005-01-15 22:18:47 +00007514 }
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00007515 if (error)
7516 li = NULL;
Bram Moolenaare9a41262005-01-15 22:18:47 +00007517 }
7518
7519 for ( ; li != NULL; li = li->li_next)
7520 if (tv_equal(&li->li_tv, &argvars[1], ic))
7521 ++n;
7522 }
Bram Moolenaar8a283e52005-01-06 23:28:25 +00007523 }
Bram Moolenaare9a41262005-01-15 22:18:47 +00007524 else if (argvars[0].v_type == VAR_DICT)
7525 {
Bram Moolenaar33570922005-01-25 22:26:29 +00007526 int todo;
7527 dict_T *d;
7528 hashitem_T *hi;
Bram Moolenaare9a41262005-01-15 22:18:47 +00007529
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00007530 if ((d = argvars[0].vval.v_dict) != NULL)
7531 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00007532 int error = FALSE;
7533
Bram Moolenaare9a41262005-01-15 22:18:47 +00007534 if (argvars[2].v_type != VAR_UNKNOWN)
7535 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00007536 ic = get_tv_number_chk(&argvars[2], &error);
Bram Moolenaare9a41262005-01-15 22:18:47 +00007537 if (argvars[3].v_type != VAR_UNKNOWN)
7538 EMSG(_(e_invarg));
7539 }
7540
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00007541 todo = error ? 0 : d->dv_hashtab.ht_used;
Bram Moolenaar33570922005-01-25 22:26:29 +00007542 for (hi = d->dv_hashtab.ht_array; todo > 0; ++hi)
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00007543 {
7544 if (!HASHITEM_EMPTY(hi))
7545 {
7546 --todo;
7547 if (tv_equal(&HI2DI(hi)->di_tv, &argvars[1], ic))
7548 ++n;
7549 }
7550 }
Bram Moolenaare9a41262005-01-15 22:18:47 +00007551 }
7552 }
7553 else
7554 EMSG2(_(e_listdictarg), "count()");
Bram Moolenaar8a283e52005-01-06 23:28:25 +00007555 rettv->vval.v_number = n;
7556}
7557
7558/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00007559 * "cscope_connection([{num} , {dbpath} [, {prepend}]])" function
7560 *
7561 * Checks the existence of a cscope connection.
7562 */
7563/*ARGSUSED*/
7564 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007565f_cscope_connection(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007566 typval_T *argvars;
7567 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007568{
7569#ifdef FEAT_CSCOPE
7570 int num = 0;
7571 char_u *dbpath = NULL;
7572 char_u *prepend = NULL;
7573 char_u buf[NUMBUFLEN];
7574
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007575 if (argvars[0].v_type != VAR_UNKNOWN
7576 && argvars[1].v_type != VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007577 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007578 num = (int)get_tv_number(&argvars[0]);
7579 dbpath = get_tv_string(&argvars[1]);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007580 if (argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007581 prepend = get_tv_string_buf(&argvars[2], buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007582 }
7583
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007584 rettv->vval.v_number = cs_connection(num, dbpath, prepend);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007585#else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007586 rettv->vval.v_number = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007587#endif
7588}
7589
7590/*
7591 * "cursor(lnum, col)" function
7592 *
7593 * Moves the cursor to the specified line and column
7594 */
7595/*ARGSUSED*/
7596 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007597f_cursor(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007598 typval_T *argvars;
7599 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007600{
7601 long line, col;
7602
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007603 line = get_tv_lnum(argvars);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00007604 col = get_tv_number_chk(&argvars[1], NULL);
7605 if (line < 0 || col < 0)
7606 return; /* type error; errmsg already given */
Bram Moolenaar071d4272004-06-13 20:20:40 +00007607 if (line > 0)
7608 curwin->w_cursor.lnum = line;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007609 if (col > 0)
7610 curwin->w_cursor.col = col - 1;
7611#ifdef FEAT_VIRTUALEDIT
7612 curwin->w_cursor.coladd = 0;
7613#endif
7614
7615 /* Make sure the cursor is in a valid position. */
7616 check_cursor();
7617#ifdef FEAT_MBYTE
7618 /* Correct cursor for multi-byte character. */
7619 if (has_mbyte)
7620 mb_adjust_cursor();
7621#endif
Bram Moolenaarf4b8e572004-06-24 15:53:16 +00007622
7623 curwin->w_set_curswant = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007624}
7625
7626/*
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007627 * "deepcopy()" function
Bram Moolenaar071d4272004-06-13 20:20:40 +00007628 */
7629 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007630f_deepcopy(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007631 typval_T *argvars;
7632 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007633{
Bram Moolenaar81bf7082005-02-12 14:31:42 +00007634 static int copyID = 0;
7635 int noref = 0;
7636
7637 if (argvars[1].v_type != VAR_UNKNOWN)
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00007638 noref = get_tv_number_chk(&argvars[1], NULL);
Bram Moolenaar81bf7082005-02-12 14:31:42 +00007639 if (noref < 0 || noref > 1)
7640 EMSG(_(e_invarg));
7641 else
7642 item_copy(&argvars[0], rettv, TRUE, noref == 0 ? ++copyID : 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007643}
7644
7645/*
7646 * "delete()" function
7647 */
7648 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007649f_delete(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007650 typval_T *argvars;
7651 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007652{
7653 if (check_restricted() || check_secure())
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007654 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007655 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007656 rettv->vval.v_number = mch_remove(get_tv_string(&argvars[0]));
Bram Moolenaar071d4272004-06-13 20:20:40 +00007657}
7658
7659/*
7660 * "did_filetype()" function
7661 */
7662/*ARGSUSED*/
7663 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007664f_did_filetype(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007665 typval_T *argvars;
7666 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007667{
7668#ifdef FEAT_AUTOCMD
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007669 rettv->vval.v_number = did_filetype;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007670#else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007671 rettv->vval.v_number = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007672#endif
7673}
7674
7675/*
Bram Moolenaar47136d72004-10-12 20:02:24 +00007676 * "diff_filler()" function
7677 */
7678/*ARGSUSED*/
7679 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007680f_diff_filler(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007681 typval_T *argvars;
7682 typval_T *rettv;
Bram Moolenaar47136d72004-10-12 20:02:24 +00007683{
7684#ifdef FEAT_DIFF
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007685 rettv->vval.v_number = diff_check_fill(curwin, get_tv_lnum(argvars));
Bram Moolenaar47136d72004-10-12 20:02:24 +00007686#endif
7687}
7688
7689/*
7690 * "diff_hlID()" function
7691 */
7692/*ARGSUSED*/
7693 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007694f_diff_hlID(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007695 typval_T *argvars;
7696 typval_T *rettv;
Bram Moolenaar47136d72004-10-12 20:02:24 +00007697{
7698#ifdef FEAT_DIFF
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007699 linenr_T lnum = get_tv_lnum(argvars);
Bram Moolenaar47136d72004-10-12 20:02:24 +00007700 static linenr_T prev_lnum = 0;
7701 static int changedtick = 0;
7702 static int fnum = 0;
7703 static int change_start = 0;
7704 static int change_end = 0;
7705 static enum hlf_value hlID = 0;
7706 int filler_lines;
7707 int col;
7708
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00007709 if (lnum < 0) /* ignore type error in {lnum} arg */
7710 lnum = 0;
Bram Moolenaar47136d72004-10-12 20:02:24 +00007711 if (lnum != prev_lnum
7712 || changedtick != curbuf->b_changedtick
7713 || fnum != curbuf->b_fnum)
7714 {
7715 /* New line, buffer, change: need to get the values. */
7716 filler_lines = diff_check(curwin, lnum);
7717 if (filler_lines < 0)
7718 {
7719 if (filler_lines == -1)
7720 {
7721 change_start = MAXCOL;
7722 change_end = -1;
7723 if (diff_find_change(curwin, lnum, &change_start, &change_end))
7724 hlID = HLF_ADD; /* added line */
7725 else
7726 hlID = HLF_CHD; /* changed line */
7727 }
7728 else
7729 hlID = HLF_ADD; /* added line */
7730 }
7731 else
7732 hlID = (enum hlf_value)0;
7733 prev_lnum = lnum;
7734 changedtick = curbuf->b_changedtick;
7735 fnum = curbuf->b_fnum;
7736 }
7737
7738 if (hlID == HLF_CHD || hlID == HLF_TXD)
7739 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00007740 col = get_tv_number(&argvars[1]) - 1; /* ignore type error in {col} */
Bram Moolenaar47136d72004-10-12 20:02:24 +00007741 if (col >= change_start && col <= change_end)
7742 hlID = HLF_TXD; /* changed text */
7743 else
7744 hlID = HLF_CHD; /* changed line */
7745 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007746 rettv->vval.v_number = hlID == (enum hlf_value)0 ? 0 : (int)hlID;
Bram Moolenaar47136d72004-10-12 20:02:24 +00007747#endif
7748}
7749
7750/*
Bram Moolenaare49b69a2005-01-08 16:11:57 +00007751 * "empty({expr})" function
7752 */
7753 static void
7754f_empty(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007755 typval_T *argvars;
7756 typval_T *rettv;
Bram Moolenaare49b69a2005-01-08 16:11:57 +00007757{
7758 int n;
7759
7760 switch (argvars[0].v_type)
7761 {
7762 case VAR_STRING:
7763 case VAR_FUNC:
7764 n = argvars[0].vval.v_string == NULL
7765 || *argvars[0].vval.v_string == NUL;
7766 break;
7767 case VAR_NUMBER:
7768 n = argvars[0].vval.v_number == 0;
7769 break;
7770 case VAR_LIST:
7771 n = argvars[0].vval.v_list == NULL
7772 || argvars[0].vval.v_list->lv_first == NULL;
7773 break;
Bram Moolenaare9a41262005-01-15 22:18:47 +00007774 case VAR_DICT:
7775 n = argvars[0].vval.v_dict == NULL
Bram Moolenaar33570922005-01-25 22:26:29 +00007776 || argvars[0].vval.v_dict->dv_hashtab.ht_used == 0;
Bram Moolenaare9a41262005-01-15 22:18:47 +00007777 break;
Bram Moolenaare49b69a2005-01-08 16:11:57 +00007778 default:
7779 EMSG2(_(e_intern2), "f_empty()");
7780 n = 0;
7781 }
7782
7783 rettv->vval.v_number = n;
7784}
7785
7786/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00007787 * "escape({string}, {chars})" function
7788 */
7789 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007790f_escape(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007791 typval_T *argvars;
7792 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007793{
7794 char_u buf[NUMBUFLEN];
7795
Bram Moolenaar758711c2005-02-02 23:11:38 +00007796 rettv->vval.v_string = vim_strsave_escaped(get_tv_string(&argvars[0]),
7797 get_tv_string_buf(&argvars[1], buf));
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007798 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007799}
7800
7801/*
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00007802 * "eval()" function
7803 */
7804/*ARGSUSED*/
7805 static void
7806f_eval(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007807 typval_T *argvars;
7808 typval_T *rettv;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00007809{
7810 char_u *s;
7811
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00007812 s = get_tv_string_chk(&argvars[0]);
7813 if (s != NULL)
7814 s = skipwhite(s);
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00007815
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00007816 if (s == NULL || eval1(&s, rettv, TRUE) == FAIL)
7817 {
7818 rettv->v_type = VAR_NUMBER;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00007819 rettv->vval.v_number = 0;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00007820 }
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00007821 else if (*s != NUL)
7822 EMSG(_(e_trailing));
7823}
7824
7825/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00007826 * "eventhandler()" function
7827 */
7828/*ARGSUSED*/
7829 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007830f_eventhandler(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007831 typval_T *argvars;
7832 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007833{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007834 rettv->vval.v_number = vgetc_busy;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007835}
7836
7837/*
7838 * "executable()" function
7839 */
7840 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007841f_executable(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007842 typval_T *argvars;
7843 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007844{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007845 rettv->vval.v_number = mch_can_exe(get_tv_string(&argvars[0]));
Bram Moolenaar071d4272004-06-13 20:20:40 +00007846}
7847
7848/*
7849 * "exists()" function
7850 */
7851 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007852f_exists(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007853 typval_T *argvars;
7854 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007855{
7856 char_u *p;
7857 char_u *name;
7858 int n = FALSE;
7859 int len = 0;
7860
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007861 p = get_tv_string(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007862 if (*p == '$') /* environment variable */
7863 {
7864 /* first try "normal" environment variables (fast) */
7865 if (mch_getenv(p + 1) != NULL)
7866 n = TRUE;
7867 else
7868 {
7869 /* try expanding things like $VIM and ${HOME} */
7870 p = expand_env_save(p);
7871 if (p != NULL && *p != '$')
7872 n = TRUE;
7873 vim_free(p);
7874 }
7875 }
7876 else if (*p == '&' || *p == '+') /* option */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007877 n = (get_option_tv(&p, NULL, TRUE) == OK);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007878 else if (*p == '*') /* internal or user defined function */
7879 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007880 n = function_exists(p + 1);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007881 }
7882 else if (*p == ':')
7883 {
7884 n = cmd_exists(p + 1);
7885 }
7886 else if (*p == '#')
7887 {
7888#ifdef FEAT_AUTOCMD
7889 name = p + 1;
7890 p = vim_strchr(name, '#');
7891 if (p != NULL)
7892 n = au_exists(name, p, p + 1);
7893 else
7894 n = au_exists(name, name + STRLEN(name), NULL);
7895#endif
7896 }
7897 else /* internal variable */
7898 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00007899 char_u *tofree;
7900 typval_T tv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007901
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00007902 /* get_name_len() takes care of expanding curly braces */
7903 name = p;
7904 len = get_name_len(&p, &tofree, TRUE, FALSE);
7905 if (len > 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007906 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00007907 if (tofree != NULL)
7908 name = tofree;
7909 n = (get_var_tv(name, len, &tv, FALSE) == OK);
7910 if (n)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007911 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00007912 /* handle d.key, l[idx], f(expr) */
7913 n = (handle_subscript(&p, &tv, TRUE, FALSE) == OK);
7914 if (n)
7915 clear_tv(&tv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007916 }
7917 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00007918
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00007919 vim_free(tofree);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007920 }
7921
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007922 rettv->vval.v_number = n;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007923}
7924
7925/*
7926 * "expand()" function
7927 */
7928 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007929f_expand(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007930 typval_T *argvars;
7931 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007932{
7933 char_u *s;
7934 int len;
7935 char_u *errormsg;
7936 int flags = WILD_SILENT|WILD_USE_NL|WILD_LIST_NOTFOUND;
7937 expand_T xpc;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00007938 int error = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007939
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007940 rettv->v_type = VAR_STRING;
7941 s = get_tv_string(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007942 if (*s == '%' || *s == '#' || *s == '<')
7943 {
7944 ++emsg_off;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007945 rettv->vval.v_string = eval_vars(s, &len, NULL, &errormsg, s);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007946 --emsg_off;
7947 }
7948 else
7949 {
7950 /* When the optional second argument is non-zero, don't remove matches
7951 * for 'suffixes' and 'wildignore' */
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00007952 if (argvars[1].v_type != VAR_UNKNOWN
7953 && get_tv_number_chk(&argvars[1], &error))
Bram Moolenaar071d4272004-06-13 20:20:40 +00007954 flags |= WILD_KEEP_ALL;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00007955 if (!error)
7956 {
7957 ExpandInit(&xpc);
7958 xpc.xp_context = EXPAND_FILES;
7959 rettv->vval.v_string = ExpandOne(&xpc, s, NULL, flags, WILD_ALL);
7960 ExpandCleanup(&xpc);
7961 }
7962 else
7963 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007964 }
7965}
7966
7967/*
Bram Moolenaar8a283e52005-01-06 23:28:25 +00007968 * "extend(list, list [, idx])" function
Bram Moolenaare9a41262005-01-15 22:18:47 +00007969 * "extend(dict, dict [, action])" function
Bram Moolenaar8a283e52005-01-06 23:28:25 +00007970 */
7971 static void
7972f_extend(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007973 typval_T *argvars;
7974 typval_T *rettv;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00007975{
Bram Moolenaar8a283e52005-01-06 23:28:25 +00007976 rettv->vval.v_number = 0;
Bram Moolenaare9a41262005-01-15 22:18:47 +00007977 if (argvars[0].v_type == VAR_LIST && argvars[1].v_type == VAR_LIST)
Bram Moolenaar8a283e52005-01-06 23:28:25 +00007978 {
Bram Moolenaar33570922005-01-25 22:26:29 +00007979 list_T *l1, *l2;
7980 listitem_T *item;
Bram Moolenaare9a41262005-01-15 22:18:47 +00007981 long before;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00007982 int error = FALSE;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00007983
Bram Moolenaare9a41262005-01-15 22:18:47 +00007984 l1 = argvars[0].vval.v_list;
7985 l2 = argvars[1].vval.v_list;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00007986 if (l1 != NULL && !tv_check_lock(l1->lv_lock, (char_u *)"extend()")
7987 && l2 != NULL)
Bram Moolenaare9a41262005-01-15 22:18:47 +00007988 {
7989 if (argvars[2].v_type != VAR_UNKNOWN)
7990 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00007991 before = get_tv_number_chk(&argvars[2], &error);
7992 if (error)
7993 return; /* type error; errmsg already given */
7994
Bram Moolenaar758711c2005-02-02 23:11:38 +00007995 if (before == l1->lv_len)
7996 item = NULL;
7997 else
Bram Moolenaare9a41262005-01-15 22:18:47 +00007998 {
Bram Moolenaar758711c2005-02-02 23:11:38 +00007999 item = list_find(l1, before);
8000 if (item == NULL)
8001 {
8002 EMSGN(_(e_listidx), before);
8003 return;
8004 }
Bram Moolenaare9a41262005-01-15 22:18:47 +00008005 }
8006 }
8007 else
8008 item = NULL;
8009 list_extend(l1, l2, item);
8010
8011 ++l1->lv_refcount;
8012 copy_tv(&argvars[0], rettv);
8013 }
Bram Moolenaar8a283e52005-01-06 23:28:25 +00008014 }
Bram Moolenaare9a41262005-01-15 22:18:47 +00008015 else if (argvars[0].v_type == VAR_DICT && argvars[1].v_type == VAR_DICT)
8016 {
Bram Moolenaar33570922005-01-25 22:26:29 +00008017 dict_T *d1, *d2;
8018 dictitem_T *di1;
Bram Moolenaare9a41262005-01-15 22:18:47 +00008019 char_u *action;
8020 int i;
Bram Moolenaar33570922005-01-25 22:26:29 +00008021 hashitem_T *hi2;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00008022 int todo;
Bram Moolenaare9a41262005-01-15 22:18:47 +00008023
8024 d1 = argvars[0].vval.v_dict;
8025 d2 = argvars[1].vval.v_dict;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00008026 if (d1 != NULL && !tv_check_lock(d1->dv_lock, (char_u *)"extend()")
8027 && d2 != NULL)
Bram Moolenaare9a41262005-01-15 22:18:47 +00008028 {
8029 /* Check the third argument. */
8030 if (argvars[2].v_type != VAR_UNKNOWN)
8031 {
8032 static char *(av[]) = {"keep", "force", "error"};
8033
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00008034 action = get_tv_string_chk(&argvars[2]);
8035 if (action == NULL)
8036 return; /* type error; errmsg already given */
Bram Moolenaare9a41262005-01-15 22:18:47 +00008037 for (i = 0; i < 3; ++i)
8038 if (STRCMP(action, av[i]) == 0)
8039 break;
8040 if (i == 3)
8041 {
8042 EMSGN(_(e_invarg2), action);
8043 return;
8044 }
8045 }
8046 else
8047 action = (char_u *)"force";
8048
8049 /* Go over all entries in the second dict and add them to the
8050 * first dict. */
Bram Moolenaar33570922005-01-25 22:26:29 +00008051 todo = d2->dv_hashtab.ht_used;
8052 for (hi2 = d2->dv_hashtab.ht_array; todo > 0; ++hi2)
Bram Moolenaare9a41262005-01-15 22:18:47 +00008053 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00008054 if (!HASHITEM_EMPTY(hi2))
Bram Moolenaare9a41262005-01-15 22:18:47 +00008055 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00008056 --todo;
8057 di1 = dict_find(d1, hi2->hi_key, -1);
8058 if (di1 == NULL)
8059 {
8060 di1 = dictitem_copy(HI2DI(hi2));
8061 if (di1 != NULL && dict_add(d1, di1) == FAIL)
8062 dictitem_free(di1);
8063 }
8064 else if (*action == 'e')
8065 {
8066 EMSG2(_("E737: Key already exists: %s"), hi2->hi_key);
8067 break;
8068 }
8069 else if (*action == 'f')
8070 {
8071 clear_tv(&di1->di_tv);
8072 copy_tv(&HI2DI(hi2)->di_tv, &di1->di_tv);
8073 }
Bram Moolenaare9a41262005-01-15 22:18:47 +00008074 }
8075 }
8076
8077 ++d1->dv_refcount;
8078 copy_tv(&argvars[0], rettv);
8079 }
8080 }
8081 else
8082 EMSG2(_(e_listdictarg), "extend()");
Bram Moolenaar8a283e52005-01-06 23:28:25 +00008083}
8084
8085/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00008086 * "filereadable()" function
8087 */
8088 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008089f_filereadable(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008090 typval_T *argvars;
8091 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008092{
8093 FILE *fd;
8094 char_u *p;
8095 int n;
8096
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008097 p = get_tv_string(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008098 if (*p && !mch_isdir(p) && (fd = mch_fopen((char *)p, "r")) != NULL)
8099 {
8100 n = TRUE;
8101 fclose(fd);
8102 }
8103 else
8104 n = FALSE;
8105
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008106 rettv->vval.v_number = n;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008107}
8108
8109/*
Bram Moolenaar0e4d8772005-06-07 21:12:49 +00008110 * Return 0 for not writable, 1 for writable file, 2 for a dir which we have
Bram Moolenaar071d4272004-06-13 20:20:40 +00008111 * rights to write into.
8112 */
8113 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008114f_filewritable(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 Moolenaar0e4d8772005-06-07 21:12:49 +00008118 rettv->vval.v_number = filewritable(get_tv_string(&argvars[0]));
Bram Moolenaar071d4272004-06-13 20:20:40 +00008119}
8120
Bram Moolenaar33570922005-01-25 22:26:29 +00008121static void findfilendir __ARGS((typval_T *argvars, typval_T *rettv, int dir));
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00008122
8123 static void
Bram Moolenaar0d660222005-01-07 21:51:51 +00008124findfilendir(argvars, rettv, dir)
Bram Moolenaar33570922005-01-25 22:26:29 +00008125 typval_T *argvars;
8126 typval_T *rettv;
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00008127 int dir;
8128{
8129#ifdef FEAT_SEARCHPATH
8130 char_u *fname;
8131 char_u *fresult = NULL;
8132 char_u *path = *curbuf->b_p_path == NUL ? p_path : curbuf->b_p_path;
8133 char_u *p;
8134 char_u pathbuf[NUMBUFLEN];
8135 int count = 1;
8136 int first = TRUE;
8137
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008138 fname = get_tv_string(&argvars[0]);
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00008139
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008140 if (argvars[1].v_type != VAR_UNKNOWN)
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00008141 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00008142 p = get_tv_string_buf_chk(&argvars[1], pathbuf);
8143 if (p == NULL)
8144 count = -1; /* error */
8145 else
8146 {
8147 if (*p != NUL)
8148 path = p;
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00008149
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00008150 if (argvars[2].v_type != VAR_UNKNOWN)
8151 count = get_tv_number_chk(&argvars[2], NULL); /* -1: error */
8152 }
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00008153 }
8154
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00008155 if (*fname != NUL && count >= 0)
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00008156 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00008157 do
8158 {
8159 vim_free(fresult);
8160 fresult = find_file_in_path_option(first ? fname : NULL,
8161 first ? (int)STRLEN(fname) : 0,
8162 0, first, path, dir, NULL);
8163 first = FALSE;
8164 } while (--count > 0 && fresult != NULL);
8165 }
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00008166
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008167 rettv->vval.v_string = fresult;
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00008168#else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008169 rettv->vval.v_string = NULL;
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00008170#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008171 rettv->v_type = VAR_STRING;
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00008172}
8173
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00008174static void prepare_vimvar __ARGS((int idx, typval_T *save_tv));
8175static void restore_vimvar __ARGS((int idx, typval_T *save_tv));
Bram Moolenaar33570922005-01-25 22:26:29 +00008176static void filter_map __ARGS((typval_T *argvars, typval_T *rettv, int map));
8177static int filter_map_one __ARGS((typval_T *tv, char_u *expr, int map, int *remp));
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00008178
8179/*
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00008180 * Prepare v: variable "idx" to be used.
8181 * Save the current typeval in "save_tv".
8182 * When not used yet add the variable to the v: hashtable.
8183 */
8184 static void
8185prepare_vimvar(idx, save_tv)
8186 int idx;
8187 typval_T *save_tv;
8188{
8189 *save_tv = vimvars[idx].vv_tv;
8190 if (vimvars[idx].vv_type == VAR_UNKNOWN)
8191 hash_add(&vimvarht, vimvars[idx].vv_di.di_key);
8192}
8193
8194/*
8195 * Restore v: variable "idx" to typeval "save_tv".
8196 * When no longer defined, remove the variable from the v: hashtable.
8197 */
8198 static void
8199restore_vimvar(idx, save_tv)
8200 int idx;
8201 typval_T *save_tv;
8202{
8203 hashitem_T *hi;
8204
8205 clear_tv(&vimvars[idx].vv_tv);
8206 vimvars[idx].vv_tv = *save_tv;
8207 if (vimvars[idx].vv_type == VAR_UNKNOWN)
8208 {
8209 hi = hash_find(&vimvarht, vimvars[idx].vv_di.di_key);
8210 if (HASHITEM_EMPTY(hi))
8211 EMSG2(_(e_intern2), "restore_vimvar()");
8212 else
8213 hash_remove(&vimvarht, hi);
8214 }
8215}
8216
8217/*
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00008218 * Implementation of map() and filter().
8219 */
8220 static void
8221filter_map(argvars, rettv, map)
Bram Moolenaar33570922005-01-25 22:26:29 +00008222 typval_T *argvars;
8223 typval_T *rettv;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00008224 int map;
8225{
8226 char_u buf[NUMBUFLEN];
Bram Moolenaare9a41262005-01-15 22:18:47 +00008227 char_u *expr;
Bram Moolenaar33570922005-01-25 22:26:29 +00008228 listitem_T *li, *nli;
8229 list_T *l = NULL;
8230 dictitem_T *di;
8231 hashtab_T *ht;
8232 hashitem_T *hi;
8233 dict_T *d = NULL;
8234 typval_T save_val;
8235 typval_T save_key;
Bram Moolenaare9a41262005-01-15 22:18:47 +00008236 int rem;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00008237 int todo;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00008238 char_u *msg = map ? (char_u *)"map()" : (char_u *)"filter()";
8239
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00008240
8241 rettv->vval.v_number = 0;
Bram Moolenaare9a41262005-01-15 22:18:47 +00008242 if (argvars[0].v_type == VAR_LIST)
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00008243 {
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00008244 if ((l = argvars[0].vval.v_list) == NULL
8245 || (map && tv_check_lock(l->lv_lock, msg)))
Bram Moolenaare9a41262005-01-15 22:18:47 +00008246 return;
8247 }
8248 else if (argvars[0].v_type == VAR_DICT)
8249 {
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00008250 if ((d = argvars[0].vval.v_dict) == NULL
8251 || (map && tv_check_lock(d->dv_lock, msg)))
Bram Moolenaare9a41262005-01-15 22:18:47 +00008252 return;
8253 }
8254 else
8255 {
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00008256 EMSG2(_(e_listdictarg), msg);
Bram Moolenaare9a41262005-01-15 22:18:47 +00008257 return;
8258 }
8259
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00008260 expr = get_tv_string_buf_chk(&argvars[1], buf);
8261 /* On type errors, the preceding call has already displayed an error
8262 * message. Avoid a misleading error message for an empty string that
8263 * was not passed as argument. */
8264 if (expr != NULL)
Bram Moolenaare9a41262005-01-15 22:18:47 +00008265 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00008266 prepare_vimvar(VV_VAL, &save_val);
8267 expr = skipwhite(expr);
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00008268
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00008269 if (argvars[0].v_type == VAR_DICT)
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00008270 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00008271 prepare_vimvar(VV_KEY, &save_key);
8272 vimvars[VV_KEY].vv_type = VAR_STRING;
8273
8274 ht = &d->dv_hashtab;
8275 hash_lock(ht);
8276 todo = ht->ht_used;
8277 for (hi = ht->ht_array; todo > 0; ++hi)
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00008278 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00008279 if (!HASHITEM_EMPTY(hi))
8280 {
8281 --todo;
8282 di = HI2DI(hi);
8283 if (tv_check_lock(di->di_tv.v_lock, msg))
8284 break;
8285 vimvars[VV_KEY].vv_str = vim_strsave(di->di_key);
8286 if (filter_map_one(&di->di_tv, expr, map, &rem) == FAIL)
8287 break;
8288 if (!map && rem)
8289 dictitem_remove(d, di);
8290 clear_tv(&vimvars[VV_KEY].vv_tv);
8291 }
8292 }
8293 hash_unlock(ht);
8294
8295 restore_vimvar(VV_KEY, &save_key);
8296 }
8297 else
8298 {
8299 for (li = l->lv_first; li != NULL; li = nli)
8300 {
8301 if (tv_check_lock(li->li_tv.v_lock, msg))
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00008302 break;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00008303 nli = li->li_next;
8304 if (filter_map_one(&li->li_tv, expr, map, &rem) == FAIL)
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00008305 break;
8306 if (!map && rem)
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00008307 listitem_remove(l, li);
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00008308 }
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00008309 }
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00008310
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00008311 restore_vimvar(VV_VAL, &save_val);
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00008312 }
Bram Moolenaare9a41262005-01-15 22:18:47 +00008313
8314 copy_tv(&argvars[0], rettv);
8315}
8316
8317 static int
8318filter_map_one(tv, expr, map, remp)
Bram Moolenaar33570922005-01-25 22:26:29 +00008319 typval_T *tv;
Bram Moolenaare9a41262005-01-15 22:18:47 +00008320 char_u *expr;
8321 int map;
8322 int *remp;
8323{
Bram Moolenaar33570922005-01-25 22:26:29 +00008324 typval_T rettv;
Bram Moolenaare9a41262005-01-15 22:18:47 +00008325 char_u *s;
8326
Bram Moolenaar33570922005-01-25 22:26:29 +00008327 copy_tv(tv, &vimvars[VV_VAL].vv_tv);
Bram Moolenaare9a41262005-01-15 22:18:47 +00008328 s = expr;
8329 if (eval1(&s, &rettv, TRUE) == FAIL)
8330 return FAIL;
8331 if (*s != NUL) /* check for trailing chars after expr */
8332 {
8333 EMSG2(_(e_invexpr2), s);
8334 return FAIL;
8335 }
8336 if (map)
8337 {
8338 /* map(): replace the list item value */
8339 clear_tv(tv);
8340 *tv = rettv;
8341 }
8342 else
8343 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00008344 int error = FALSE;
8345
Bram Moolenaare9a41262005-01-15 22:18:47 +00008346 /* filter(): when expr is zero remove the item */
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00008347 *remp = (get_tv_number_chk(&rettv, &error) == 0);
Bram Moolenaare9a41262005-01-15 22:18:47 +00008348 clear_tv(&rettv);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00008349 /* On type error, nothing has been removed; return FAIL to stop the
8350 * loop. The error message was given by get_tv_number_chk(). */
8351 if (error)
8352 return FAIL;
Bram Moolenaare9a41262005-01-15 22:18:47 +00008353 }
Bram Moolenaar33570922005-01-25 22:26:29 +00008354 clear_tv(&vimvars[VV_VAL].vv_tv);
Bram Moolenaare9a41262005-01-15 22:18:47 +00008355 return OK;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00008356}
8357
8358/*
8359 * "filter()" function
8360 */
8361 static void
8362f_filter(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008363 typval_T *argvars;
8364 typval_T *rettv;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00008365{
8366 filter_map(argvars, rettv, FALSE);
8367}
8368
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00008369/*
Bram Moolenaar0d660222005-01-07 21:51:51 +00008370 * "finddir({fname}[, {path}[, {count}]])" function
8371 */
8372 static void
8373f_finddir(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008374 typval_T *argvars;
8375 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +00008376{
8377 findfilendir(argvars, rettv, TRUE);
8378}
8379
8380/*
8381 * "findfile({fname}[, {path}[, {count}]])" function
8382 */
8383 static void
8384f_findfile(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008385 typval_T *argvars;
8386 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +00008387{
8388 findfilendir(argvars, rettv, FALSE);
8389}
8390
8391/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00008392 * "fnamemodify({fname}, {mods})" function
8393 */
8394 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008395f_fnamemodify(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008396 typval_T *argvars;
8397 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008398{
8399 char_u *fname;
8400 char_u *mods;
8401 int usedlen = 0;
8402 int len;
8403 char_u *fbuf = NULL;
8404 char_u buf[NUMBUFLEN];
8405
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00008406 fname = get_tv_string_chk(&argvars[0]);
8407 mods = get_tv_string_buf_chk(&argvars[1], buf);
8408 if (fname == NULL || mods == NULL)
8409 fname = NULL;
8410 else
8411 {
8412 len = (int)STRLEN(fname);
8413 (void)modify_fname(mods, &usedlen, &fname, &fbuf, &len);
8414 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00008415
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008416 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008417 if (fname == NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008418 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008419 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008420 rettv->vval.v_string = vim_strnsave(fname, len);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008421 vim_free(fbuf);
8422}
8423
Bram Moolenaar33570922005-01-25 22:26:29 +00008424static void foldclosed_both __ARGS((typval_T *argvars, typval_T *rettv, int end));
Bram Moolenaar071d4272004-06-13 20:20:40 +00008425
8426/*
8427 * "foldclosed()" function
8428 */
8429 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008430foldclosed_both(argvars, rettv, end)
Bram Moolenaar33570922005-01-25 22:26:29 +00008431 typval_T *argvars;
8432 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008433 int end;
8434{
8435#ifdef FEAT_FOLDING
8436 linenr_T lnum;
8437 linenr_T first, last;
8438
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008439 lnum = get_tv_lnum(argvars);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008440 if (lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count)
8441 {
8442 if (hasFoldingWin(curwin, lnum, &first, &last, FALSE, NULL))
8443 {
8444 if (end)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008445 rettv->vval.v_number = (varnumber_T)last;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008446 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008447 rettv->vval.v_number = (varnumber_T)first;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008448 return;
8449 }
8450 }
8451#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008452 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008453}
8454
8455/*
Bram Moolenaar0d660222005-01-07 21:51:51 +00008456 * "foldclosed()" function
8457 */
8458 static void
8459f_foldclosed(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008460 typval_T *argvars;
8461 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +00008462{
8463 foldclosed_both(argvars, rettv, FALSE);
8464}
8465
8466/*
8467 * "foldclosedend()" function
8468 */
8469 static void
8470f_foldclosedend(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008471 typval_T *argvars;
8472 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +00008473{
8474 foldclosed_both(argvars, rettv, TRUE);
8475}
8476
8477/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00008478 * "foldlevel()" function
8479 */
8480 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008481f_foldlevel(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008482 typval_T *argvars;
8483 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008484{
8485#ifdef FEAT_FOLDING
8486 linenr_T lnum;
8487
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008488 lnum = get_tv_lnum(argvars);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008489 if (lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008490 rettv->vval.v_number = foldLevel(lnum);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008491 else
8492#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008493 rettv->vval.v_number = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008494}
8495
8496/*
8497 * "foldtext()" function
8498 */
8499/*ARGSUSED*/
8500 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008501f_foldtext(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008502 typval_T *argvars;
8503 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008504{
8505#ifdef FEAT_FOLDING
8506 linenr_T lnum;
8507 char_u *s;
8508 char_u *r;
8509 int len;
8510 char *txt;
8511#endif
8512
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008513 rettv->v_type = VAR_STRING;
8514 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008515#ifdef FEAT_FOLDING
Bram Moolenaare9a41262005-01-15 22:18:47 +00008516 if ((linenr_T)vimvars[VV_FOLDSTART].vv_nr > 0
8517 && (linenr_T)vimvars[VV_FOLDEND].vv_nr
8518 <= curbuf->b_ml.ml_line_count
8519 && vimvars[VV_FOLDDASHES].vv_str != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008520 {
8521 /* Find first non-empty line in the fold. */
Bram Moolenaare9a41262005-01-15 22:18:47 +00008522 lnum = (linenr_T)vimvars[VV_FOLDSTART].vv_nr;
8523 while (lnum < (linenr_T)vimvars[VV_FOLDEND].vv_nr)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008524 {
8525 if (!linewhite(lnum))
8526 break;
8527 ++lnum;
8528 }
8529
8530 /* Find interesting text in this line. */
8531 s = skipwhite(ml_get(lnum));
8532 /* skip C comment-start */
8533 if (s[0] == '/' && (s[1] == '*' || s[1] == '/'))
Bram Moolenaar293ee4d2004-12-09 21:34:53 +00008534 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00008535 s = skipwhite(s + 2);
Bram Moolenaar293ee4d2004-12-09 21:34:53 +00008536 if (*skipwhite(s) == NUL
Bram Moolenaare9a41262005-01-15 22:18:47 +00008537 && lnum + 1 < (linenr_T)vimvars[VV_FOLDEND].vv_nr)
Bram Moolenaar293ee4d2004-12-09 21:34:53 +00008538 {
8539 s = skipwhite(ml_get(lnum + 1));
8540 if (*s == '*')
8541 s = skipwhite(s + 1);
8542 }
8543 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00008544 txt = _("+-%s%3ld lines: ");
8545 r = alloc((unsigned)(STRLEN(txt)
Bram Moolenaare9a41262005-01-15 22:18:47 +00008546 + STRLEN(vimvars[VV_FOLDDASHES].vv_str) /* for %s */
Bram Moolenaar071d4272004-06-13 20:20:40 +00008547 + 20 /* for %3ld */
8548 + STRLEN(s))); /* concatenated */
8549 if (r != NULL)
8550 {
Bram Moolenaare9a41262005-01-15 22:18:47 +00008551 sprintf((char *)r, txt, vimvars[VV_FOLDDASHES].vv_str,
8552 (long)((linenr_T)vimvars[VV_FOLDEND].vv_nr
8553 - (linenr_T)vimvars[VV_FOLDSTART].vv_nr + 1));
Bram Moolenaar071d4272004-06-13 20:20:40 +00008554 len = (int)STRLEN(r);
8555 STRCAT(r, s);
8556 /* remove 'foldmarker' and 'commentstring' */
8557 foldtext_cleanup(r + len);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008558 rettv->vval.v_string = r;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008559 }
8560 }
8561#endif
8562}
8563
8564/*
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00008565 * "foldtextresult(lnum)" function
8566 */
8567/*ARGSUSED*/
8568 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008569f_foldtextresult(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008570 typval_T *argvars;
8571 typval_T *rettv;
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00008572{
8573#ifdef FEAT_FOLDING
8574 linenr_T lnum;
8575 char_u *text;
8576 char_u buf[51];
8577 foldinfo_T foldinfo;
8578 int fold_count;
8579#endif
8580
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008581 rettv->v_type = VAR_STRING;
8582 rettv->vval.v_string = NULL;
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00008583#ifdef FEAT_FOLDING
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008584 lnum = get_tv_lnum(argvars);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00008585 /* treat illegal types and illegal string values for {lnum} the same */
8586 if (lnum < 0)
8587 lnum = 0;
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00008588 fold_count = foldedCount(curwin, lnum, &foldinfo);
8589 if (fold_count > 0)
8590 {
8591 text = get_foldtext(curwin, lnum, lnum + fold_count - 1,
8592 &foldinfo, buf);
8593 if (text == buf)
8594 text = vim_strsave(text);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008595 rettv->vval.v_string = text;
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00008596 }
8597#endif
8598}
8599
8600/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00008601 * "foreground()" function
8602 */
8603/*ARGSUSED*/
8604 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008605f_foreground(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008606 typval_T *argvars;
8607 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008608{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008609 rettv->vval.v_number = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008610#ifdef FEAT_GUI
8611 if (gui.in_use)
8612 gui_mch_set_foreground();
8613#else
8614# ifdef WIN32
8615 win32_set_foreground();
8616# endif
8617#endif
8618}
8619
8620/*
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008621 * "function()" function
8622 */
8623/*ARGSUSED*/
8624 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008625f_function(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008626 typval_T *argvars;
8627 typval_T *rettv;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008628{
8629 char_u *s;
8630
Bram Moolenaara7043832005-01-21 11:56:39 +00008631 rettv->vval.v_number = 0;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008632 s = get_tv_string(&argvars[0]);
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00008633 if (s == NULL || *s == NUL || VIM_ISDIGIT(*s))
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008634 EMSG2(_(e_invarg2), s);
8635 else if (!function_exists(s))
Bram Moolenaare49b69a2005-01-08 16:11:57 +00008636 EMSG2(_("E700: Unknown function: %s"), s);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008637 else
8638 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008639 rettv->vval.v_string = vim_strsave(s);
8640 rettv->v_type = VAR_FUNC;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008641 }
8642}
8643
8644/*
Bram Moolenaar0d660222005-01-07 21:51:51 +00008645 * "get()" function
8646 */
8647 static void
8648f_get(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008649 typval_T *argvars;
8650 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +00008651{
Bram Moolenaar33570922005-01-25 22:26:29 +00008652 listitem_T *li;
8653 list_T *l;
8654 dictitem_T *di;
8655 dict_T *d;
8656 typval_T *tv = NULL;
Bram Moolenaar0d660222005-01-07 21:51:51 +00008657
Bram Moolenaare9a41262005-01-15 22:18:47 +00008658 if (argvars[0].v_type == VAR_LIST)
Bram Moolenaar0d660222005-01-07 21:51:51 +00008659 {
Bram Moolenaare9a41262005-01-15 22:18:47 +00008660 if ((l = argvars[0].vval.v_list) != NULL)
Bram Moolenaar0d660222005-01-07 21:51:51 +00008661 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00008662 int error = FALSE;
8663
8664 li = list_find(l, get_tv_number_chk(&argvars[1], &error));
8665 if (!error && li != NULL)
Bram Moolenaare9a41262005-01-15 22:18:47 +00008666 tv = &li->li_tv;
Bram Moolenaar0d660222005-01-07 21:51:51 +00008667 }
Bram Moolenaar0d660222005-01-07 21:51:51 +00008668 }
Bram Moolenaare9a41262005-01-15 22:18:47 +00008669 else if (argvars[0].v_type == VAR_DICT)
8670 {
8671 if ((d = argvars[0].vval.v_dict) != NULL)
8672 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00008673 di = dict_find(d, get_tv_string(&argvars[1]), -1);
Bram Moolenaare9a41262005-01-15 22:18:47 +00008674 if (di != NULL)
8675 tv = &di->di_tv;
8676 }
8677 }
8678 else
8679 EMSG2(_(e_listdictarg), "get()");
8680
8681 if (tv == NULL)
8682 {
8683 if (argvars[2].v_type == VAR_UNKNOWN)
8684 rettv->vval.v_number = 0;
8685 else
8686 copy_tv(&argvars[2], rettv);
8687 }
8688 else
8689 copy_tv(tv, rettv);
Bram Moolenaar0d660222005-01-07 21:51:51 +00008690}
8691
8692/*
8693 * "getbufvar()" function
8694 */
8695 static void
8696f_getbufvar(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008697 typval_T *argvars;
8698 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +00008699{
8700 buf_T *buf;
8701 buf_T *save_curbuf;
8702 char_u *varname;
Bram Moolenaar33570922005-01-25 22:26:29 +00008703 dictitem_T *v;
Bram Moolenaar0d660222005-01-07 21:51:51 +00008704
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00008705 (void)get_tv_number(&argvars[0]); /* issue errmsg if type error */
8706 varname = get_tv_string_chk(&argvars[1]);
Bram Moolenaar0d660222005-01-07 21:51:51 +00008707 ++emsg_off;
8708 buf = get_buf_tv(&argvars[0]);
Bram Moolenaar0d660222005-01-07 21:51:51 +00008709
8710 rettv->v_type = VAR_STRING;
8711 rettv->vval.v_string = NULL;
8712
8713 if (buf != NULL && varname != NULL)
8714 {
8715 if (*varname == '&') /* buffer-local-option */
8716 {
8717 /* set curbuf to be our buf, temporarily */
8718 save_curbuf = curbuf;
8719 curbuf = buf;
8720
8721 get_option_tv(&varname, rettv, TRUE);
8722
8723 /* restore previous notion of curbuf */
8724 curbuf = save_curbuf;
8725 }
8726 else
8727 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00008728 if (*varname == NUL)
8729 /* let getbufvar({nr}, "") return the "b:" dictionary. The
8730 * scope prefix before the NUL byte is required by
8731 * find_var_in_ht(). */
8732 varname = (char_u *)"b:" + 2;
Bram Moolenaar0d660222005-01-07 21:51:51 +00008733 /* look up the variable */
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00008734 v = find_var_in_ht(&buf->b_vars.dv_hashtab, varname, FALSE);
Bram Moolenaar0d660222005-01-07 21:51:51 +00008735 if (v != NULL)
Bram Moolenaar33570922005-01-25 22:26:29 +00008736 copy_tv(&v->di_tv, rettv);
Bram Moolenaar0d660222005-01-07 21:51:51 +00008737 }
8738 }
8739
8740 --emsg_off;
8741}
8742
8743/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00008744 * "getchar()" function
8745 */
8746 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008747f_getchar(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008748 typval_T *argvars;
8749 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008750{
8751 varnumber_T n;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00008752 int error = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008753
8754 ++no_mapping;
8755 ++allow_keys;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008756 if (argvars[0].v_type == VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008757 /* getchar(): blocking wait. */
8758 n = safe_vgetc();
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00008759 else if (get_tv_number_chk(&argvars[0], &error) == 1)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008760 /* getchar(1): only check if char avail */
8761 n = vpeekc();
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00008762 else if (error || vpeekc() == NUL)
8763 /* illegal argument or getchar(0) and no char avail: return zero */
Bram Moolenaar071d4272004-06-13 20:20:40 +00008764 n = 0;
8765 else
8766 /* getchar(0) and char avail: return char */
8767 n = safe_vgetc();
8768 --no_mapping;
8769 --allow_keys;
8770
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008771 rettv->vval.v_number = n;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008772 if (IS_SPECIAL(n) || mod_mask != 0)
8773 {
8774 char_u temp[10]; /* modifier: 3, mbyte-char: 6, NUL: 1 */
8775 int i = 0;
8776
8777 /* Turn a special key into three bytes, plus modifier. */
8778 if (mod_mask != 0)
8779 {
8780 temp[i++] = K_SPECIAL;
8781 temp[i++] = KS_MODIFIER;
8782 temp[i++] = mod_mask;
8783 }
8784 if (IS_SPECIAL(n))
8785 {
8786 temp[i++] = K_SPECIAL;
8787 temp[i++] = K_SECOND(n);
8788 temp[i++] = K_THIRD(n);
8789 }
8790#ifdef FEAT_MBYTE
8791 else if (has_mbyte)
8792 i += (*mb_char2bytes)(n, temp + i);
8793#endif
8794 else
8795 temp[i++] = n;
8796 temp[i++] = NUL;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008797 rettv->v_type = VAR_STRING;
8798 rettv->vval.v_string = vim_strsave(temp);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008799 }
8800}
8801
8802/*
8803 * "getcharmod()" function
8804 */
8805/*ARGSUSED*/
8806 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008807f_getcharmod(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008808 typval_T *argvars;
8809 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008810{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008811 rettv->vval.v_number = mod_mask;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008812}
8813
8814/*
8815 * "getcmdline()" function
8816 */
8817/*ARGSUSED*/
8818 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008819f_getcmdline(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008820 typval_T *argvars;
8821 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008822{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008823 rettv->v_type = VAR_STRING;
8824 rettv->vval.v_string = get_cmdline_str();
Bram Moolenaar071d4272004-06-13 20:20:40 +00008825}
8826
8827/*
8828 * "getcmdpos()" function
8829 */
8830/*ARGSUSED*/
8831 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008832f_getcmdpos(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008833 typval_T *argvars;
8834 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008835{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008836 rettv->vval.v_number = get_cmdline_pos() + 1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008837}
8838
8839/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00008840 * "getcwd()" function
8841 */
8842/*ARGSUSED*/
8843 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008844f_getcwd(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008845 typval_T *argvars;
8846 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008847{
8848 char_u cwd[MAXPATHL];
8849
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008850 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008851 if (mch_dirname(cwd, MAXPATHL) == FAIL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008852 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008853 else
8854 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008855 rettv->vval.v_string = vim_strsave(cwd);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008856#ifdef BACKSLASH_IN_FILENAME
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008857 slash_adjust(rettv->vval.v_string);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008858#endif
8859 }
8860}
8861
8862/*
Bram Moolenaar46c9c732004-12-12 11:37:09 +00008863 * "getfontname()" function
8864 */
Bram Moolenaar1cd871b2004-12-19 22:46:22 +00008865/*ARGSUSED*/
Bram Moolenaar46c9c732004-12-12 11:37:09 +00008866 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008867f_getfontname(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008868 typval_T *argvars;
8869 typval_T *rettv;
Bram Moolenaar46c9c732004-12-12 11:37:09 +00008870{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008871 rettv->v_type = VAR_STRING;
8872 rettv->vval.v_string = NULL;
Bram Moolenaar46c9c732004-12-12 11:37:09 +00008873#ifdef FEAT_GUI
8874 if (gui.in_use)
8875 {
8876 GuiFont font;
8877 char_u *name = NULL;
8878
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008879 if (argvars[0].v_type == VAR_UNKNOWN)
Bram Moolenaar46c9c732004-12-12 11:37:09 +00008880 {
8881 /* Get the "Normal" font. Either the name saved by
8882 * hl_set_font_name() or from the font ID. */
8883 font = gui.norm_font;
8884 name = hl_get_font_name();
8885 }
8886 else
8887 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008888 name = get_tv_string(&argvars[0]);
Bram Moolenaar46c9c732004-12-12 11:37:09 +00008889 if (STRCMP(name, "*") == 0) /* don't use font dialog */
8890 return;
8891 font = gui_mch_get_font(name, FALSE);
8892 if (font == NOFONT)
8893 return; /* Invalid font name, return empty string. */
8894 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008895 rettv->vval.v_string = gui_mch_get_fontname(font, name);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008896 if (argvars[0].v_type != VAR_UNKNOWN)
Bram Moolenaar46c9c732004-12-12 11:37:09 +00008897 gui_mch_free_font(font);
8898 }
8899#endif
8900}
8901
8902/*
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00008903 * "getfperm({fname})" function
8904 */
8905 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008906f_getfperm(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008907 typval_T *argvars;
8908 typval_T *rettv;
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00008909{
8910 char_u *fname;
8911 struct stat st;
8912 char_u *perm = NULL;
8913 char_u flags[] = "rwx";
8914 int i;
8915
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008916 fname = get_tv_string(&argvars[0]);
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00008917
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008918 rettv->v_type = VAR_STRING;
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00008919 if (mch_stat((char *)fname, &st) >= 0)
8920 {
8921 perm = vim_strsave((char_u *)"---------");
8922 if (perm != NULL)
8923 {
8924 for (i = 0; i < 9; i++)
8925 {
8926 if (st.st_mode & (1 << (8 - i)))
8927 perm[i] = flags[i % 3];
8928 }
8929 }
8930 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008931 rettv->vval.v_string = perm;
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00008932}
8933
8934/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00008935 * "getfsize({fname})" function
8936 */
8937 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008938f_getfsize(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008939 typval_T *argvars;
8940 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008941{
8942 char_u *fname;
8943 struct stat st;
8944
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008945 fname = get_tv_string(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008946
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008947 rettv->v_type = VAR_NUMBER;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008948
8949 if (mch_stat((char *)fname, &st) >= 0)
8950 {
8951 if (mch_isdir(fname))
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008952 rettv->vval.v_number = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008953 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008954 rettv->vval.v_number = (varnumber_T)st.st_size;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008955 }
8956 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008957 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008958}
8959
8960/*
8961 * "getftime({fname})" function
8962 */
8963 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008964f_getftime(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008965 typval_T *argvars;
8966 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008967{
8968 char_u *fname;
8969 struct stat st;
8970
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008971 fname = get_tv_string(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008972
8973 if (mch_stat((char *)fname, &st) >= 0)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008974 rettv->vval.v_number = (varnumber_T)st.st_mtime;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008975 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008976 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008977}
8978
8979/*
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00008980 * "getftype({fname})" function
8981 */
8982 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008983f_getftype(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008984 typval_T *argvars;
8985 typval_T *rettv;
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00008986{
8987 char_u *fname;
8988 struct stat st;
8989 char_u *type = NULL;
8990 char *t;
8991
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008992 fname = get_tv_string(&argvars[0]);
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00008993
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008994 rettv->v_type = VAR_STRING;
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00008995 if (mch_lstat((char *)fname, &st) >= 0)
8996 {
8997#ifdef S_ISREG
8998 if (S_ISREG(st.st_mode))
8999 t = "file";
9000 else if (S_ISDIR(st.st_mode))
9001 t = "dir";
9002# ifdef S_ISLNK
9003 else if (S_ISLNK(st.st_mode))
9004 t = "link";
9005# endif
9006# ifdef S_ISBLK
9007 else if (S_ISBLK(st.st_mode))
9008 t = "bdev";
9009# endif
9010# ifdef S_ISCHR
9011 else if (S_ISCHR(st.st_mode))
9012 t = "cdev";
9013# endif
9014# ifdef S_ISFIFO
9015 else if (S_ISFIFO(st.st_mode))
9016 t = "fifo";
9017# endif
9018# ifdef S_ISSOCK
9019 else if (S_ISSOCK(st.st_mode))
9020 t = "fifo";
9021# endif
9022 else
9023 t = "other";
9024#else
9025# ifdef S_IFMT
9026 switch (st.st_mode & S_IFMT)
9027 {
9028 case S_IFREG: t = "file"; break;
9029 case S_IFDIR: t = "dir"; break;
9030# ifdef S_IFLNK
9031 case S_IFLNK: t = "link"; break;
9032# endif
9033# ifdef S_IFBLK
9034 case S_IFBLK: t = "bdev"; break;
9035# endif
9036# ifdef S_IFCHR
9037 case S_IFCHR: t = "cdev"; break;
9038# endif
9039# ifdef S_IFIFO
9040 case S_IFIFO: t = "fifo"; break;
9041# endif
9042# ifdef S_IFSOCK
9043 case S_IFSOCK: t = "socket"; break;
9044# endif
9045 default: t = "other";
9046 }
9047# else
9048 if (mch_isdir(fname))
9049 t = "dir";
9050 else
9051 t = "file";
9052# endif
9053#endif
9054 type = vim_strsave((char_u *)t);
9055 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009056 rettv->vval.v_string = type;
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00009057}
9058
9059/*
Bram Moolenaar0d660222005-01-07 21:51:51 +00009060 * "getline(lnum)" function
9061 */
9062 static void
9063f_getline(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00009064 typval_T *argvars;
9065 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +00009066{
9067 linenr_T lnum;
9068 linenr_T end;
9069 char_u *p;
Bram Moolenaar33570922005-01-25 22:26:29 +00009070 list_T *l;
9071 listitem_T *li;
Bram Moolenaar0d660222005-01-07 21:51:51 +00009072
9073 lnum = get_tv_lnum(argvars);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00009074 if (lnum < 0)
9075 rettv->vval.v_number = 0; /* failure; error message already given */
9076 else if (argvars[1].v_type == VAR_UNKNOWN)
Bram Moolenaar0d660222005-01-07 21:51:51 +00009077 {
9078 if (lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count)
9079 p = ml_get(lnum);
9080 else
9081 p = (char_u *)"";
9082
9083 rettv->v_type = VAR_STRING;
9084 rettv->vval.v_string = vim_strsave(p);
9085 }
9086 else
9087 {
9088 end = get_tv_lnum(&argvars[1]);
9089 if (end < lnum)
9090 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00009091 if (end >= 0) /* else: error message already given */
9092 EMSG(_(e_invrange));
Bram Moolenaar0d660222005-01-07 21:51:51 +00009093 rettv->vval.v_number = 0;
9094 }
9095 else
9096 {
9097 l = list_alloc();
9098 if (l != NULL)
9099 {
9100 if (lnum < 1)
9101 lnum = 1;
9102 if (end > curbuf->b_ml.ml_line_count)
9103 end = curbuf->b_ml.ml_line_count;
9104 while (lnum <= end)
9105 {
9106 li = listitem_alloc();
9107 if (li == NULL)
9108 break;
9109 list_append(l, li);
9110 li->li_tv.v_type = VAR_STRING;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00009111 li->li_tv.v_lock = 0;
Bram Moolenaar0d660222005-01-07 21:51:51 +00009112 li->li_tv.vval.v_string = vim_strsave(ml_get(lnum++));
9113 }
9114 rettv->vval.v_list = l;
9115 rettv->v_type = VAR_LIST;
9116 ++l->lv_refcount;
9117 }
9118 }
9119 }
9120}
9121
9122/*
Bram Moolenaar2641f772005-03-25 21:58:17 +00009123 * "getqflist()" function
9124 */
9125/*ARGSUSED*/
9126 static void
9127f_getqflist(argvars, rettv)
9128 typval_T *argvars;
9129 typval_T *rettv;
9130{
9131#ifdef FEAT_QUICKFIX
9132 list_T *l;
9133#endif
9134
9135 rettv->vval.v_number = FALSE;
9136#ifdef FEAT_QUICKFIX
9137 l = list_alloc();
9138 if (l != NULL)
9139 {
9140 if (get_errorlist(l) != FAIL)
9141 {
9142 rettv->vval.v_list = l;
9143 rettv->v_type = VAR_LIST;
9144 ++l->lv_refcount;
9145 }
9146 else
9147 list_free(l);
9148 }
9149#endif
9150}
9151
9152/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00009153 * "getreg()" function
9154 */
9155 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009156f_getreg(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00009157 typval_T *argvars;
9158 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009159{
9160 char_u *strregname;
9161 int regname;
Bram Moolenaar67fe1a12005-05-22 22:12:58 +00009162 int arg2 = FALSE;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00009163 int error = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009164
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009165 if (argvars[0].v_type != VAR_UNKNOWN)
Bram Moolenaar67fe1a12005-05-22 22:12:58 +00009166 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00009167 strregname = get_tv_string_chk(&argvars[0]);
9168 error = strregname == NULL;
Bram Moolenaar67fe1a12005-05-22 22:12:58 +00009169 if (argvars[1].v_type != VAR_UNKNOWN)
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00009170 arg2 = get_tv_number_chk(&argvars[1], &error);
Bram Moolenaar67fe1a12005-05-22 22:12:58 +00009171 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00009172 else
Bram Moolenaare9a41262005-01-15 22:18:47 +00009173 strregname = vimvars[VV_REG].vv_str;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009174 regname = (strregname == NULL ? '"' : *strregname);
9175 if (regname == 0)
9176 regname = '"';
9177
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009178 rettv->v_type = VAR_STRING;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00009179 rettv->vval.v_string = error ? NULL :
9180 get_reg_contents(regname, TRUE, arg2);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009181}
9182
9183/*
9184 * "getregtype()" function
9185 */
9186 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009187f_getregtype(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00009188 typval_T *argvars;
9189 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009190{
9191 char_u *strregname;
9192 int regname;
9193 char_u buf[NUMBUFLEN + 2];
9194 long reglen = 0;
9195
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009196 if (argvars[0].v_type != VAR_UNKNOWN)
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00009197 {
9198 strregname = get_tv_string_chk(&argvars[0]);
9199 if (strregname == NULL) /* type error; errmsg already given */
9200 {
9201 rettv->v_type = VAR_STRING;
9202 rettv->vval.v_string = NULL;
9203 return;
9204 }
9205 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00009206 else
9207 /* Default to v:register */
Bram Moolenaare9a41262005-01-15 22:18:47 +00009208 strregname = vimvars[VV_REG].vv_str;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009209
9210 regname = (strregname == NULL ? '"' : *strregname);
9211 if (regname == 0)
9212 regname = '"';
9213
9214 buf[0] = NUL;
9215 buf[1] = NUL;
9216 switch (get_reg_type(regname, &reglen))
9217 {
9218 case MLINE: buf[0] = 'V'; break;
9219 case MCHAR: buf[0] = 'v'; break;
9220#ifdef FEAT_VISUAL
9221 case MBLOCK:
9222 buf[0] = Ctrl_V;
9223 sprintf((char *)buf + 1, "%ld", reglen + 1);
9224 break;
9225#endif
9226 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009227 rettv->v_type = VAR_STRING;
9228 rettv->vval.v_string = vim_strsave(buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009229}
9230
9231/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00009232 * "getwinposx()" function
9233 */
9234/*ARGSUSED*/
9235 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009236f_getwinposx(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00009237 typval_T *argvars;
9238 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009239{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009240 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009241#ifdef FEAT_GUI
9242 if (gui.in_use)
9243 {
9244 int x, y;
9245
9246 if (gui_mch_get_winpos(&x, &y) == OK)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009247 rettv->vval.v_number = x;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009248 }
9249#endif
9250}
9251
9252/*
9253 * "getwinposy()" function
9254 */
9255/*ARGSUSED*/
9256 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009257f_getwinposy(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00009258 typval_T *argvars;
9259 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009260{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009261 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009262#ifdef FEAT_GUI
9263 if (gui.in_use)
9264 {
9265 int x, y;
9266
9267 if (gui_mch_get_winpos(&x, &y) == OK)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009268 rettv->vval.v_number = y;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009269 }
9270#endif
9271}
9272
9273/*
9274 * "getwinvar()" function
9275 */
9276 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009277f_getwinvar(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00009278 typval_T *argvars;
9279 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009280{
9281 win_T *win, *oldcurwin;
9282 char_u *varname;
Bram Moolenaar33570922005-01-25 22:26:29 +00009283 dictitem_T *v;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009284
Bram Moolenaar071d4272004-06-13 20:20:40 +00009285 win = find_win_by_nr(&argvars[0]);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00009286 varname = get_tv_string_chk(&argvars[1]);
9287 ++emsg_off;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009288
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009289 rettv->v_type = VAR_STRING;
9290 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009291
9292 if (win != NULL && varname != NULL)
9293 {
9294 if (*varname == '&') /* window-local-option */
9295 {
Bram Moolenaarc0761132005-03-18 20:30:32 +00009296 /* Set curwin to be our win, temporarily. Also set curbuf, so
9297 * that we can get buffer-local options. */
Bram Moolenaar071d4272004-06-13 20:20:40 +00009298 oldcurwin = curwin;
9299 curwin = win;
Bram Moolenaarc0761132005-03-18 20:30:32 +00009300 curbuf = win->w_buffer;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009301
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009302 get_option_tv(&varname, rettv, 1);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009303
9304 /* restore previous notion of curwin */
9305 curwin = oldcurwin;
Bram Moolenaarc0761132005-03-18 20:30:32 +00009306 curbuf = curwin->w_buffer;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009307 }
9308 else
9309 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00009310 if (*varname == NUL)
9311 /* let getwinvar({nr}, "") return the "w:" dictionary. The
9312 * scope prefix before the NUL byte is required by
9313 * find_var_in_ht(). */
9314 varname = (char_u *)"w:" + 2;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009315 /* look up the variable */
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00009316 v = find_var_in_ht(&win->w_vars.dv_hashtab, varname, FALSE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009317 if (v != NULL)
Bram Moolenaar33570922005-01-25 22:26:29 +00009318 copy_tv(&v->di_tv, rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009319 }
9320 }
9321
9322 --emsg_off;
9323}
9324
9325/*
9326 * "glob()" function
9327 */
9328 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009329f_glob(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00009330 typval_T *argvars;
9331 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009332{
9333 expand_T xpc;
9334
9335 ExpandInit(&xpc);
9336 xpc.xp_context = EXPAND_FILES;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009337 rettv->v_type = VAR_STRING;
9338 rettv->vval.v_string = ExpandOne(&xpc, get_tv_string(&argvars[0]),
Bram Moolenaar071d4272004-06-13 20:20:40 +00009339 NULL, WILD_USE_NL|WILD_SILENT, WILD_ALL);
9340 ExpandCleanup(&xpc);
9341}
9342
9343/*
9344 * "globpath()" function
9345 */
9346 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009347f_globpath(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00009348 typval_T *argvars;
9349 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009350{
9351 char_u buf1[NUMBUFLEN];
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00009352 char_u *file = get_tv_string_buf_chk(&argvars[1], buf1);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009353
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009354 rettv->v_type = VAR_STRING;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00009355 if (file == NULL)
9356 rettv->vval.v_string = NULL;
9357 else
9358 rettv->vval.v_string = globpath(get_tv_string(&argvars[0]), file);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009359}
9360
9361/*
9362 * "has()" function
9363 */
9364 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009365f_has(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00009366 typval_T *argvars;
9367 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009368{
9369 int i;
9370 char_u *name;
9371 int n = FALSE;
9372 static char *(has_list[]) =
9373 {
9374#ifdef AMIGA
9375 "amiga",
9376# ifdef FEAT_ARP
9377 "arp",
9378# endif
9379#endif
9380#ifdef __BEOS__
9381 "beos",
9382#endif
9383#ifdef MSDOS
9384# ifdef DJGPP
9385 "dos32",
9386# else
9387 "dos16",
9388# endif
9389#endif
9390#ifdef MACOS /* TODO: Should we add MACOS_CLASSIC, MACOS_X? (Dany) */
9391 "mac",
9392#endif
9393#if defined(MACOS_X_UNIX)
9394 "macunix",
9395#endif
9396#ifdef OS2
9397 "os2",
9398#endif
9399#ifdef __QNX__
9400 "qnx",
9401#endif
9402#ifdef RISCOS
9403 "riscos",
9404#endif
9405#ifdef UNIX
9406 "unix",
9407#endif
9408#ifdef VMS
9409 "vms",
9410#endif
9411#ifdef WIN16
9412 "win16",
9413#endif
9414#ifdef WIN32
9415 "win32",
9416#endif
9417#if defined(UNIX) && (defined(__CYGWIN32__) || defined(__CYGWIN__))
9418 "win32unix",
9419#endif
9420#ifdef WIN64
9421 "win64",
9422#endif
9423#ifdef EBCDIC
9424 "ebcdic",
9425#endif
9426#ifndef CASE_INSENSITIVE_FILENAME
9427 "fname_case",
9428#endif
9429#ifdef FEAT_ARABIC
9430 "arabic",
9431#endif
9432#ifdef FEAT_AUTOCMD
9433 "autocmd",
9434#endif
9435#ifdef FEAT_BEVAL
9436 "balloon_eval",
9437#endif
9438#if defined(SOME_BUILTIN_TCAPS) || defined(ALL_BUILTIN_TCAPS)
9439 "builtin_terms",
9440# ifdef ALL_BUILTIN_TCAPS
9441 "all_builtin_terms",
9442# endif
9443#endif
9444#ifdef FEAT_BYTEOFF
9445 "byte_offset",
9446#endif
9447#ifdef FEAT_CINDENT
9448 "cindent",
9449#endif
9450#ifdef FEAT_CLIENTSERVER
9451 "clientserver",
9452#endif
9453#ifdef FEAT_CLIPBOARD
9454 "clipboard",
9455#endif
9456#ifdef FEAT_CMDL_COMPL
9457 "cmdline_compl",
9458#endif
9459#ifdef FEAT_CMDHIST
9460 "cmdline_hist",
9461#endif
9462#ifdef FEAT_COMMENTS
9463 "comments",
9464#endif
9465#ifdef FEAT_CRYPT
9466 "cryptv",
9467#endif
9468#ifdef FEAT_CSCOPE
9469 "cscope",
9470#endif
9471#ifdef DEBUG
9472 "debug",
9473#endif
9474#ifdef FEAT_CON_DIALOG
9475 "dialog_con",
9476#endif
9477#ifdef FEAT_GUI_DIALOG
9478 "dialog_gui",
9479#endif
9480#ifdef FEAT_DIFF
9481 "diff",
9482#endif
9483#ifdef FEAT_DIGRAPHS
9484 "digraphs",
9485#endif
9486#ifdef FEAT_DND
9487 "dnd",
9488#endif
9489#ifdef FEAT_EMACS_TAGS
9490 "emacs_tags",
9491#endif
9492 "eval", /* always present, of course! */
9493#ifdef FEAT_EX_EXTRA
9494 "ex_extra",
9495#endif
9496#ifdef FEAT_SEARCH_EXTRA
9497 "extra_search",
9498#endif
9499#ifdef FEAT_FKMAP
9500 "farsi",
9501#endif
9502#ifdef FEAT_SEARCHPATH
9503 "file_in_path",
9504#endif
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00009505#if defined(UNIX) && !defined(USE_SYSTEM)
9506 "filterpipe",
9507#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00009508#ifdef FEAT_FIND_ID
9509 "find_in_path",
9510#endif
9511#ifdef FEAT_FOLDING
9512 "folding",
9513#endif
9514#ifdef FEAT_FOOTER
9515 "footer",
9516#endif
9517#if !defined(USE_SYSTEM) && defined(UNIX)
9518 "fork",
9519#endif
9520#ifdef FEAT_GETTEXT
9521 "gettext",
9522#endif
9523#ifdef FEAT_GUI
9524 "gui",
9525#endif
9526#ifdef FEAT_GUI_ATHENA
9527# ifdef FEAT_GUI_NEXTAW
9528 "gui_neXtaw",
9529# else
9530 "gui_athena",
9531# endif
9532#endif
Bram Moolenaar843ee412004-06-30 16:16:41 +00009533#ifdef FEAT_GUI_KDE
9534 "gui_kde",
9535#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00009536#ifdef FEAT_GUI_GTK
9537 "gui_gtk",
9538# ifdef HAVE_GTK2
9539 "gui_gtk2",
9540# endif
9541#endif
9542#ifdef FEAT_GUI_MAC
9543 "gui_mac",
9544#endif
9545#ifdef FEAT_GUI_MOTIF
9546 "gui_motif",
9547#endif
9548#ifdef FEAT_GUI_PHOTON
9549 "gui_photon",
9550#endif
9551#ifdef FEAT_GUI_W16
9552 "gui_win16",
9553#endif
9554#ifdef FEAT_GUI_W32
9555 "gui_win32",
9556#endif
9557#ifdef FEAT_HANGULIN
9558 "hangul_input",
9559#endif
9560#if defined(HAVE_ICONV_H) && defined(USE_ICONV)
9561 "iconv",
9562#endif
9563#ifdef FEAT_INS_EXPAND
9564 "insert_expand",
9565#endif
9566#ifdef FEAT_JUMPLIST
9567 "jumplist",
9568#endif
9569#ifdef FEAT_KEYMAP
9570 "keymap",
9571#endif
9572#ifdef FEAT_LANGMAP
9573 "langmap",
9574#endif
9575#ifdef FEAT_LIBCALL
9576 "libcall",
9577#endif
9578#ifdef FEAT_LINEBREAK
9579 "linebreak",
9580#endif
9581#ifdef FEAT_LISP
9582 "lispindent",
9583#endif
9584#ifdef FEAT_LISTCMDS
9585 "listcmds",
9586#endif
9587#ifdef FEAT_LOCALMAP
9588 "localmap",
9589#endif
9590#ifdef FEAT_MENU
9591 "menu",
9592#endif
9593#ifdef FEAT_SESSION
9594 "mksession",
9595#endif
9596#ifdef FEAT_MODIFY_FNAME
9597 "modify_fname",
9598#endif
9599#ifdef FEAT_MOUSE
9600 "mouse",
9601#endif
9602#ifdef FEAT_MOUSESHAPE
9603 "mouseshape",
9604#endif
9605#if defined(UNIX) || defined(VMS)
9606# ifdef FEAT_MOUSE_DEC
9607 "mouse_dec",
9608# endif
9609# ifdef FEAT_MOUSE_GPM
9610 "mouse_gpm",
9611# endif
9612# ifdef FEAT_MOUSE_JSB
9613 "mouse_jsbterm",
9614# endif
9615# ifdef FEAT_MOUSE_NET
9616 "mouse_netterm",
9617# endif
9618# ifdef FEAT_MOUSE_PTERM
9619 "mouse_pterm",
9620# endif
9621# ifdef FEAT_MOUSE_XTERM
9622 "mouse_xterm",
9623# endif
9624#endif
9625#ifdef FEAT_MBYTE
9626 "multi_byte",
9627#endif
9628#ifdef FEAT_MBYTE_IME
9629 "multi_byte_ime",
9630#endif
9631#ifdef FEAT_MULTI_LANG
9632 "multi_lang",
9633#endif
Bram Moolenaar325b7a22004-07-05 15:58:32 +00009634#ifdef FEAT_MZSCHEME
Bram Moolenaar33570922005-01-25 22:26:29 +00009635#ifndef DYNAMIC_MZSCHEME
Bram Moolenaar325b7a22004-07-05 15:58:32 +00009636 "mzscheme",
9637#endif
Bram Moolenaar33570922005-01-25 22:26:29 +00009638#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00009639#ifdef FEAT_OLE
9640 "ole",
9641#endif
9642#ifdef FEAT_OSFILETYPE
9643 "osfiletype",
9644#endif
9645#ifdef FEAT_PATH_EXTRA
9646 "path_extra",
9647#endif
9648#ifdef FEAT_PERL
9649#ifndef DYNAMIC_PERL
9650 "perl",
9651#endif
9652#endif
9653#ifdef FEAT_PYTHON
9654#ifndef DYNAMIC_PYTHON
9655 "python",
9656#endif
9657#endif
9658#ifdef FEAT_POSTSCRIPT
9659 "postscript",
9660#endif
9661#ifdef FEAT_PRINTER
9662 "printer",
9663#endif
Bram Moolenaar05159a02005-02-26 23:04:13 +00009664#ifdef FEAT_PROFILE
9665 "profile",
9666#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00009667#ifdef FEAT_QUICKFIX
9668 "quickfix",
9669#endif
9670#ifdef FEAT_RIGHTLEFT
9671 "rightleft",
9672#endif
9673#if defined(FEAT_RUBY) && !defined(DYNAMIC_RUBY)
9674 "ruby",
9675#endif
9676#ifdef FEAT_SCROLLBIND
9677 "scrollbind",
9678#endif
9679#ifdef FEAT_CMDL_INFO
9680 "showcmd",
9681 "cmdline_info",
9682#endif
9683#ifdef FEAT_SIGNS
9684 "signs",
9685#endif
9686#ifdef FEAT_SMARTINDENT
9687 "smartindent",
9688#endif
9689#ifdef FEAT_SNIFF
9690 "sniff",
9691#endif
9692#ifdef FEAT_STL_OPT
9693 "statusline",
9694#endif
9695#ifdef FEAT_SUN_WORKSHOP
9696 "sun_workshop",
9697#endif
9698#ifdef FEAT_NETBEANS_INTG
9699 "netbeans_intg",
9700#endif
9701#ifdef FEAT_SYN_HL
Bram Moolenaar0e4d8772005-06-07 21:12:49 +00009702 "spell",
9703#endif
9704#ifdef FEAT_SYN_HL
Bram Moolenaar071d4272004-06-13 20:20:40 +00009705 "syntax",
9706#endif
9707#if defined(USE_SYSTEM) || !defined(UNIX)
9708 "system",
9709#endif
9710#ifdef FEAT_TAG_BINS
9711 "tag_binary",
9712#endif
9713#ifdef FEAT_TAG_OLDSTATIC
9714 "tag_old_static",
9715#endif
9716#ifdef FEAT_TAG_ANYWHITE
9717 "tag_any_white",
9718#endif
9719#ifdef FEAT_TCL
9720# ifndef DYNAMIC_TCL
9721 "tcl",
9722# endif
9723#endif
9724#ifdef TERMINFO
9725 "terminfo",
9726#endif
9727#ifdef FEAT_TERMRESPONSE
9728 "termresponse",
9729#endif
9730#ifdef FEAT_TEXTOBJ
9731 "textobjects",
9732#endif
9733#ifdef HAVE_TGETENT
9734 "tgetent",
9735#endif
9736#ifdef FEAT_TITLE
9737 "title",
9738#endif
9739#ifdef FEAT_TOOLBAR
9740 "toolbar",
9741#endif
9742#ifdef FEAT_USR_CMDS
9743 "user-commands", /* was accidentally included in 5.4 */
9744 "user_commands",
9745#endif
9746#ifdef FEAT_VIMINFO
9747 "viminfo",
9748#endif
9749#ifdef FEAT_VERTSPLIT
9750 "vertsplit",
9751#endif
9752#ifdef FEAT_VIRTUALEDIT
9753 "virtualedit",
9754#endif
9755#ifdef FEAT_VISUAL
9756 "visual",
9757#endif
9758#ifdef FEAT_VISUALEXTRA
9759 "visualextra",
9760#endif
9761#ifdef FEAT_VREPLACE
9762 "vreplace",
9763#endif
9764#ifdef FEAT_WILDIGN
9765 "wildignore",
9766#endif
9767#ifdef FEAT_WILDMENU
9768 "wildmenu",
9769#endif
9770#ifdef FEAT_WINDOWS
9771 "windows",
9772#endif
9773#ifdef FEAT_WAK
9774 "winaltkeys",
9775#endif
9776#ifdef FEAT_WRITEBACKUP
9777 "writebackup",
9778#endif
9779#ifdef FEAT_XIM
9780 "xim",
9781#endif
9782#ifdef FEAT_XFONTSET
9783 "xfontset",
9784#endif
9785#ifdef USE_XSMP
9786 "xsmp",
9787#endif
9788#ifdef USE_XSMP_INTERACT
9789 "xsmp_interact",
9790#endif
9791#ifdef FEAT_XCLIPBOARD
9792 "xterm_clipboard",
9793#endif
9794#ifdef FEAT_XTERM_SAVE
9795 "xterm_save",
9796#endif
9797#if defined(UNIX) && defined(FEAT_X11)
9798 "X11",
9799#endif
9800 NULL
9801 };
9802
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009803 name = get_tv_string(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009804 for (i = 0; has_list[i] != NULL; ++i)
9805 if (STRICMP(name, has_list[i]) == 0)
9806 {
9807 n = TRUE;
9808 break;
9809 }
9810
9811 if (n == FALSE)
9812 {
9813 if (STRNICMP(name, "patch", 5) == 0)
9814 n = has_patch(atoi((char *)name + 5));
9815 else if (STRICMP(name, "vim_starting") == 0)
9816 n = (starting != 0);
9817#ifdef DYNAMIC_TCL
9818 else if (STRICMP(name, "tcl") == 0)
9819 n = tcl_enabled(FALSE);
9820#endif
9821#if defined(USE_ICONV) && defined(DYNAMIC_ICONV)
9822 else if (STRICMP(name, "iconv") == 0)
9823 n = iconv_enabled(FALSE);
9824#endif
Bram Moolenaar33570922005-01-25 22:26:29 +00009825#ifdef DYNAMIC_MZSCHEME
9826 else if (STRICMP(name, "mzscheme") == 0)
9827 n = mzscheme_enabled(FALSE);
9828#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00009829#ifdef DYNAMIC_RUBY
9830 else if (STRICMP(name, "ruby") == 0)
9831 n = ruby_enabled(FALSE);
9832#endif
9833#ifdef DYNAMIC_PYTHON
9834 else if (STRICMP(name, "python") == 0)
9835 n = python_enabled(FALSE);
9836#endif
9837#ifdef DYNAMIC_PERL
9838 else if (STRICMP(name, "perl") == 0)
9839 n = perl_enabled(FALSE);
9840#endif
9841#ifdef FEAT_GUI
9842 else if (STRICMP(name, "gui_running") == 0)
9843 n = (gui.in_use || gui.starting);
9844# ifdef FEAT_GUI_W32
9845 else if (STRICMP(name, "gui_win32s") == 0)
9846 n = gui_is_win32s();
9847# endif
9848# ifdef FEAT_BROWSE
9849 else if (STRICMP(name, "browse") == 0)
9850 n = gui.in_use; /* gui_mch_browse() works when GUI is running */
9851# endif
9852#endif
9853#ifdef FEAT_SYN_HL
9854 else if (STRICMP(name, "syntax_items") == 0)
9855 n = syntax_present(curbuf);
9856#endif
9857#if defined(WIN3264)
9858 else if (STRICMP(name, "win95") == 0)
9859 n = mch_windows95();
9860#endif
Bram Moolenaar35a9aaa2004-10-24 19:23:07 +00009861#ifdef FEAT_NETBEANS_INTG
9862 else if (STRICMP(name, "netbeans_enabled") == 0)
9863 n = usingNetbeans;
9864#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00009865 }
9866
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009867 rettv->vval.v_number = n;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009868}
9869
9870/*
Bram Moolenaare9a41262005-01-15 22:18:47 +00009871 * "has_key()" function
9872 */
9873 static void
9874f_has_key(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00009875 typval_T *argvars;
9876 typval_T *rettv;
Bram Moolenaare9a41262005-01-15 22:18:47 +00009877{
9878 rettv->vval.v_number = 0;
9879 if (argvars[0].v_type != VAR_DICT)
9880 {
9881 EMSG(_(e_dictreq));
9882 return;
9883 }
9884 if (argvars[0].vval.v_dict == NULL)
9885 return;
9886
9887 rettv->vval.v_number = dict_find(argvars[0].vval.v_dict,
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00009888 get_tv_string(&argvars[1]), -1) != NULL;
Bram Moolenaare9a41262005-01-15 22:18:47 +00009889}
9890
9891/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00009892 * "hasmapto()" function
9893 */
9894 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009895f_hasmapto(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00009896 typval_T *argvars;
9897 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009898{
9899 char_u *name;
9900 char_u *mode;
9901 char_u buf[NUMBUFLEN];
9902
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009903 name = get_tv_string(&argvars[0]);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009904 if (argvars[1].v_type == VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009905 mode = (char_u *)"nvo";
9906 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009907 mode = get_tv_string_buf(&argvars[1], buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009908
9909 if (map_to_exists(name, mode))
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009910 rettv->vval.v_number = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009911 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009912 rettv->vval.v_number = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009913}
9914
9915/*
9916 * "histadd()" function
9917 */
9918/*ARGSUSED*/
9919 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009920f_histadd(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00009921 typval_T *argvars;
9922 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009923{
9924#ifdef FEAT_CMDHIST
9925 int histype;
9926 char_u *str;
9927 char_u buf[NUMBUFLEN];
9928#endif
9929
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009930 rettv->vval.v_number = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009931 if (check_restricted() || check_secure())
9932 return;
9933#ifdef FEAT_CMDHIST
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00009934 str = get_tv_string_chk(&argvars[0]); /* NULL on type error */
9935 histype = str != NULL ? get_histtype(str) : -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009936 if (histype >= 0)
9937 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009938 str = get_tv_string_buf(&argvars[1], buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009939 if (*str != NUL)
9940 {
9941 add_to_history(histype, str, FALSE, NUL);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009942 rettv->vval.v_number = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009943 return;
9944 }
9945 }
9946#endif
9947}
9948
9949/*
9950 * "histdel()" function
9951 */
9952/*ARGSUSED*/
9953 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009954f_histdel(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00009955 typval_T *argvars;
9956 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009957{
9958#ifdef FEAT_CMDHIST
9959 int n;
9960 char_u buf[NUMBUFLEN];
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00009961 char_u *str;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009962
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00009963 str = get_tv_string_chk(&argvars[0]); /* NULL on type error */
9964 if (str == NULL)
9965 n = 0;
9966 else if (argvars[1].v_type == VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009967 /* only one argument: clear entire history */
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00009968 n = clr_history(get_histtype(str));
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009969 else if (argvars[1].v_type == VAR_NUMBER)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009970 /* index given: remove that entry */
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00009971 n = del_history_idx(get_histtype(str),
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009972 (int)get_tv_number(&argvars[1]));
Bram Moolenaar071d4272004-06-13 20:20:40 +00009973 else
9974 /* string given: remove all matching entries */
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00009975 n = del_history_entry(get_histtype(str),
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009976 get_tv_string_buf(&argvars[1], buf));
9977 rettv->vval.v_number = n;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009978#else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009979 rettv->vval.v_number = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009980#endif
9981}
9982
9983/*
9984 * "histget()" function
9985 */
9986/*ARGSUSED*/
9987 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009988f_histget(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00009989 typval_T *argvars;
9990 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009991{
9992#ifdef FEAT_CMDHIST
9993 int type;
9994 int idx;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00009995 char_u *str;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009996
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00009997 str = get_tv_string_chk(&argvars[0]); /* NULL on type error */
9998 if (str == NULL)
9999 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010000 else
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010001 {
10002 type = get_histtype(str);
10003 if (argvars[1].v_type == VAR_UNKNOWN)
10004 idx = get_history_idx(type);
10005 else
10006 idx = (int)get_tv_number_chk(&argvars[1], NULL);
10007 /* -1 on type error */
10008 rettv->vval.v_string = vim_strsave(get_history_entry(type, idx));
10009 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000010010#else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010011 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010012#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010013 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010014}
10015
10016/*
10017 * "histnr()" function
10018 */
10019/*ARGSUSED*/
10020 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010021f_histnr(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010022 typval_T *argvars;
10023 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010024{
10025 int i;
10026
10027#ifdef FEAT_CMDHIST
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010028 char_u *history = get_tv_string_chk(&argvars[0]);
10029
10030 i = history == NULL ? HIST_CMD - 1 : get_histtype(history);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010031 if (i >= HIST_CMD && i < HIST_COUNT)
10032 i = get_history_idx(i);
10033 else
10034#endif
10035 i = -1;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010036 rettv->vval.v_number = i;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010037}
10038
10039/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000010040 * "highlightID(name)" function
10041 */
10042 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010043f_hlID(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010044 typval_T *argvars;
10045 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010046{
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010047 rettv->vval.v_number = syn_name2id(get_tv_string(&argvars[0]));
Bram Moolenaar071d4272004-06-13 20:20:40 +000010048}
10049
10050/*
Bram Moolenaar0d660222005-01-07 21:51:51 +000010051 * "highlight_exists()" function
10052 */
10053 static void
10054f_hlexists(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010055 typval_T *argvars;
10056 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000010057{
10058 rettv->vval.v_number = highlight_exists(get_tv_string(&argvars[0]));
10059}
10060
10061/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000010062 * "hostname()" function
10063 */
10064/*ARGSUSED*/
10065 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010066f_hostname(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010067 typval_T *argvars;
10068 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010069{
10070 char_u hostname[256];
10071
10072 mch_get_host_name(hostname, 256);
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010073 rettv->v_type = VAR_STRING;
10074 rettv->vval.v_string = vim_strsave(hostname);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010075}
10076
10077/*
10078 * iconv() function
10079 */
10080/*ARGSUSED*/
10081 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010082f_iconv(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010083 typval_T *argvars;
10084 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010085{
10086#ifdef FEAT_MBYTE
10087 char_u buf1[NUMBUFLEN];
10088 char_u buf2[NUMBUFLEN];
10089 char_u *from, *to, *str;
10090 vimconv_T vimconv;
10091#endif
10092
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010093 rettv->v_type = VAR_STRING;
10094 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010095
10096#ifdef FEAT_MBYTE
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010097 str = get_tv_string(&argvars[0]);
10098 from = enc_canonize(enc_skip(get_tv_string_buf(&argvars[1], buf1)));
10099 to = enc_canonize(enc_skip(get_tv_string_buf(&argvars[2], buf2)));
Bram Moolenaar071d4272004-06-13 20:20:40 +000010100 vimconv.vc_type = CONV_NONE;
10101 convert_setup(&vimconv, from, to);
10102
10103 /* If the encodings are equal, no conversion needed. */
10104 if (vimconv.vc_type == CONV_NONE)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010105 rettv->vval.v_string = vim_strsave(str);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010106 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010107 rettv->vval.v_string = string_convert(&vimconv, str, NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010108
10109 convert_setup(&vimconv, NULL, NULL);
10110 vim_free(from);
10111 vim_free(to);
10112#endif
10113}
10114
10115/*
10116 * "indent()" function
10117 */
10118 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010119f_indent(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010120 typval_T *argvars;
10121 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010122{
10123 linenr_T lnum;
10124
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010125 lnum = get_tv_lnum(argvars);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010126 if (lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010127 rettv->vval.v_number = get_indent_lnum(lnum);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010128 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010129 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010130}
10131
Bram Moolenaar8a283e52005-01-06 23:28:25 +000010132/*
10133 * "index()" function
10134 */
10135 static void
10136f_index(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010137 typval_T *argvars;
10138 typval_T *rettv;
Bram Moolenaar8a283e52005-01-06 23:28:25 +000010139{
Bram Moolenaar33570922005-01-25 22:26:29 +000010140 list_T *l;
10141 listitem_T *item;
Bram Moolenaar8a283e52005-01-06 23:28:25 +000010142 long idx = 0;
10143 int ic = FALSE;
10144
10145 rettv->vval.v_number = -1;
10146 if (argvars[0].v_type != VAR_LIST)
10147 {
10148 EMSG(_(e_listreq));
10149 return;
10150 }
10151 l = argvars[0].vval.v_list;
10152 if (l != NULL)
10153 {
Bram Moolenaar758711c2005-02-02 23:11:38 +000010154 item = l->lv_first;
Bram Moolenaar8a283e52005-01-06 23:28:25 +000010155 if (argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000010156 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010157 int error = FALSE;
10158
Bram Moolenaar758711c2005-02-02 23:11:38 +000010159 /* Start at specified item. Use the cached index that list_find()
10160 * sets, so that a negative number also works. */
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010161 item = list_find(l, get_tv_number_chk(&argvars[2], &error));
Bram Moolenaar758711c2005-02-02 23:11:38 +000010162 idx = l->lv_idx;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000010163 if (argvars[3].v_type != VAR_UNKNOWN)
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010164 ic = get_tv_number_chk(&argvars[3], &error);
10165 if (error)
10166 item = NULL;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000010167 }
Bram Moolenaar8a283e52005-01-06 23:28:25 +000010168
Bram Moolenaar758711c2005-02-02 23:11:38 +000010169 for ( ; item != NULL; item = item->li_next, ++idx)
10170 if (tv_equal(&item->li_tv, &argvars[1], ic))
Bram Moolenaar8a283e52005-01-06 23:28:25 +000010171 {
10172 rettv->vval.v_number = idx;
10173 break;
10174 }
10175 }
10176}
10177
Bram Moolenaar071d4272004-06-13 20:20:40 +000010178static int inputsecret_flag = 0;
10179
10180/*
10181 * "input()" function
10182 * Also handles inputsecret() when inputsecret is set.
10183 */
10184 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010185f_input(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010186 typval_T *argvars;
10187 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010188{
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010189 char_u *prompt = get_tv_string_chk(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010190 char_u *p = NULL;
10191 int c;
10192 char_u buf[NUMBUFLEN];
10193 int cmd_silent_save = cmd_silent;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010194 char_u *defstr = (char_u *)"";
Bram Moolenaar071d4272004-06-13 20:20:40 +000010195
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010196 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010197
10198#ifdef NO_CONSOLE_INPUT
10199 /* While starting up, there is no place to enter text. */
10200 if (no_console_input())
10201 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010202 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010203 return;
10204 }
10205#endif
10206
10207 cmd_silent = FALSE; /* Want to see the prompt. */
10208 if (prompt != NULL)
10209 {
10210 /* Only the part of the message after the last NL is considered as
10211 * prompt for the command line */
10212 p = vim_strrchr(prompt, '\n');
10213 if (p == NULL)
10214 p = prompt;
10215 else
10216 {
10217 ++p;
10218 c = *p;
10219 *p = NUL;
10220 msg_start();
10221 msg_clr_eos();
10222 msg_puts_attr(prompt, echo_attr);
10223 msg_didout = FALSE;
10224 msg_starthere();
10225 *p = c;
10226 }
10227 cmdline_row = msg_row;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010228
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010229 if (argvars[1].v_type != VAR_UNKNOWN)
10230 {
10231 defstr = get_tv_string_buf_chk(&argvars[1], buf);
10232 if (defstr != NULL)
10233 stuffReadbuffSpec(defstr);
10234 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000010235
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010236 if (defstr != NULL)
10237 rettv->vval.v_string =
Bram Moolenaar071d4272004-06-13 20:20:40 +000010238 getcmdline_prompt(inputsecret_flag ? NUL : '@', p, echo_attr);
10239
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010240 /* since the user typed this, no need to wait for return */
10241 need_wait_return = FALSE;
10242 msg_didout = FALSE;
10243 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000010244 cmd_silent = cmd_silent_save;
10245}
10246
10247/*
10248 * "inputdialog()" function
10249 */
10250 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010251f_inputdialog(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010252 typval_T *argvars;
10253 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010254{
10255#if defined(FEAT_GUI_TEXTDIALOG)
10256 /* Use a GUI dialog if the GUI is running and 'c' is not in 'guioptions' */
10257 if (gui.in_use && vim_strchr(p_go, GO_CONDIALOG) == NULL)
10258 {
10259 char_u *message;
10260 char_u buf[NUMBUFLEN];
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010261 char_u *defstr = (char_u *)"";
Bram Moolenaar071d4272004-06-13 20:20:40 +000010262
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010263 message = get_tv_string_chk(&argvars[0]);
10264 if (argvars[1].v_type != VAR_UNKNOWN
10265 && (defstr = get_tv_string_buf_chk(&argvars[1], buf)) != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000010266 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010267 STRNCPY(IObuff, defstr, IOSIZE);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010268 IObuff[IOSIZE - 1] = NUL;
10269 }
10270 else
10271 IObuff[0] = NUL;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010272 if (message != NULL && defstr != NULL
10273 && do_dialog(VIM_QUESTION, NULL, message,
10274 (char_u *)_("&OK\n&Cancel"), 1, IObuff) == 1)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010275 rettv->vval.v_string = vim_strsave(IObuff);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010276 else
10277 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010278 if (message != NULL && defstr != NULL
10279 && argvars[1].v_type != VAR_UNKNOWN
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010280 && argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010281 rettv->vval.v_string = vim_strsave(
10282 get_tv_string_buf(&argvars[2], buf));
Bram Moolenaar071d4272004-06-13 20:20:40 +000010283 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010284 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010285 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010286 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010287 }
10288 else
10289#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010290 f_input(argvars, rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010291}
10292
10293static garray_T ga_userinput = {0, 0, sizeof(tasave_T), 4, NULL};
10294
10295/*
10296 * "inputrestore()" function
10297 */
10298/*ARGSUSED*/
10299 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010300f_inputrestore(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010301 typval_T *argvars;
10302 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010303{
10304 if (ga_userinput.ga_len > 0)
10305 {
10306 --ga_userinput.ga_len;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010307 restore_typeahead((tasave_T *)(ga_userinput.ga_data)
10308 + ga_userinput.ga_len);
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010309 rettv->vval.v_number = 0; /* OK */
Bram Moolenaar071d4272004-06-13 20:20:40 +000010310 }
10311 else if (p_verbose > 1)
10312 {
Bram Moolenaar54ee7752005-05-31 22:22:17 +000010313 verb_msg((char_u *)_("called inputrestore() more often than inputsave()"));
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010314 rettv->vval.v_number = 1; /* Failed */
Bram Moolenaar071d4272004-06-13 20:20:40 +000010315 }
10316}
10317
10318/*
10319 * "inputsave()" function
10320 */
10321/*ARGSUSED*/
10322 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010323f_inputsave(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010324 typval_T *argvars;
10325 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010326{
10327 /* Add an entry to the stack of typehead storage. */
10328 if (ga_grow(&ga_userinput, 1) == OK)
10329 {
10330 save_typeahead((tasave_T *)(ga_userinput.ga_data)
10331 + ga_userinput.ga_len);
10332 ++ga_userinput.ga_len;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010333 rettv->vval.v_number = 0; /* OK */
Bram Moolenaar071d4272004-06-13 20:20:40 +000010334 }
10335 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010336 rettv->vval.v_number = 1; /* Failed */
Bram Moolenaar071d4272004-06-13 20:20:40 +000010337}
10338
10339/*
10340 * "inputsecret()" function
10341 */
10342 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010343f_inputsecret(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010344 typval_T *argvars;
10345 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010346{
10347 ++cmdline_star;
10348 ++inputsecret_flag;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010349 f_input(argvars, rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010350 --cmdline_star;
10351 --inputsecret_flag;
10352}
10353
10354/*
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010355 * "insert()" function
10356 */
10357 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010358f_insert(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010359 typval_T *argvars;
10360 typval_T *rettv;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010361{
10362 long before = 0;
Bram Moolenaar33570922005-01-25 22:26:29 +000010363 listitem_T *item;
10364 list_T *l;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010365 int error = FALSE;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010366
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000010367 rettv->vval.v_number = 0;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010368 if (argvars[0].v_type != VAR_LIST)
Bram Moolenaar0d660222005-01-07 21:51:51 +000010369 EMSG2(_(e_listarg), "insert()");
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000010370 else if ((l = argvars[0].vval.v_list) != NULL
10371 && !tv_check_lock(l->lv_lock, (char_u *)"insert()"))
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010372 {
10373 if (argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010374 before = get_tv_number_chk(&argvars[2], &error);
10375 if (error)
10376 return; /* type error; errmsg already given */
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010377
Bram Moolenaar758711c2005-02-02 23:11:38 +000010378 if (before == l->lv_len)
10379 item = NULL;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010380 else
10381 {
Bram Moolenaar758711c2005-02-02 23:11:38 +000010382 item = list_find(l, before);
10383 if (item == NULL)
10384 {
10385 EMSGN(_(e_listidx), before);
10386 l = NULL;
10387 }
10388 }
10389 if (l != NULL)
10390 {
Bram Moolenaar8a283e52005-01-06 23:28:25 +000010391 list_insert_tv(l, &argvars[1], item);
10392 ++l->lv_refcount;
10393 copy_tv(&argvars[0], rettv);
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010394 }
10395 }
10396}
10397
10398/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000010399 * "isdirectory()" function
10400 */
10401 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010402f_isdirectory(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{
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010406 rettv->vval.v_number = mch_isdir(get_tv_string(&argvars[0]));
Bram Moolenaar071d4272004-06-13 20:20:40 +000010407}
10408
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000010409/*
10410 * Return TRUE if typeval "tv" is locked: Either tha value is locked itself or
10411 * it refers to a List or Dictionary that is locked.
10412 */
10413 static int
10414tv_islocked(tv)
10415 typval_T *tv;
10416{
10417 return (tv->v_lock & VAR_LOCKED)
10418 || (tv->v_type == VAR_LIST
10419 && tv->vval.v_list != NULL
10420 && (tv->vval.v_list->lv_lock & VAR_LOCKED))
10421 || (tv->v_type == VAR_DICT
10422 && tv->vval.v_dict != NULL
10423 && (tv->vval.v_dict->dv_lock & VAR_LOCKED));
10424}
10425
10426/*
10427 * "islocked()" function
10428 */
10429 static void
10430f_islocked(argvars, rettv)
10431 typval_T *argvars;
10432 typval_T *rettv;
10433{
10434 lval_T lv;
10435 char_u *end;
10436 dictitem_T *di;
10437
10438 rettv->vval.v_number = -1;
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +000010439 end = get_lval(get_tv_string(&argvars[0]), NULL, &lv, FALSE, FALSE, FALSE,
10440 FNE_CHECK_START);
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000010441 if (end != NULL && lv.ll_name != NULL)
10442 {
10443 if (*end != NUL)
10444 EMSG(_(e_trailing));
10445 else
10446 {
10447 if (lv.ll_tv == NULL)
10448 {
10449 if (check_changedtick(lv.ll_name))
10450 rettv->vval.v_number = 1; /* always locked */
10451 else
10452 {
10453 di = find_var(lv.ll_name, NULL);
10454 if (di != NULL)
10455 {
10456 /* Consider a variable locked when:
10457 * 1. the variable itself is locked
10458 * 2. the value of the variable is locked.
10459 * 3. the List or Dict value is locked.
10460 */
10461 rettv->vval.v_number = ((di->di_flags & DI_FLAGS_LOCK)
10462 || tv_islocked(&di->di_tv));
10463 }
10464 }
10465 }
10466 else if (lv.ll_range)
10467 EMSG(_("E745: Range not allowed"));
10468 else if (lv.ll_newkey != NULL)
10469 EMSG2(_(e_dictkey), lv.ll_newkey);
10470 else if (lv.ll_list != NULL)
10471 /* List item. */
10472 rettv->vval.v_number = tv_islocked(&lv.ll_li->li_tv);
10473 else
10474 /* Dictionary item. */
10475 rettv->vval.v_number = tv_islocked(&lv.ll_di->di_tv);
10476 }
10477 }
10478
10479 clear_lval(&lv);
10480}
10481
Bram Moolenaar33570922005-01-25 22:26:29 +000010482static void dict_list __ARGS((typval_T *argvars, typval_T *rettv, int what));
Bram Moolenaar8c711452005-01-14 21:53:12 +000010483
10484/*
10485 * Turn a dict into a list:
10486 * "what" == 0: list of keys
10487 * "what" == 1: list of values
10488 * "what" == 2: list of items
10489 */
10490 static void
10491dict_list(argvars, rettv, what)
Bram Moolenaar33570922005-01-25 22:26:29 +000010492 typval_T *argvars;
10493 typval_T *rettv;
Bram Moolenaar8c711452005-01-14 21:53:12 +000010494 int what;
10495{
Bram Moolenaar33570922005-01-25 22:26:29 +000010496 list_T *l;
10497 list_T *l2;
10498 dictitem_T *di;
10499 hashitem_T *hi;
10500 listitem_T *li;
10501 listitem_T *li2;
10502 dict_T *d;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000010503 int todo;
Bram Moolenaar8c711452005-01-14 21:53:12 +000010504
10505 rettv->vval.v_number = 0;
10506 if (argvars[0].v_type != VAR_DICT)
10507 {
10508 EMSG(_(e_dictreq));
10509 return;
10510 }
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000010511 if ((d = argvars[0].vval.v_dict) == NULL)
Bram Moolenaar8c711452005-01-14 21:53:12 +000010512 return;
10513
10514 l = list_alloc();
10515 if (l == NULL)
10516 return;
10517 rettv->v_type = VAR_LIST;
10518 rettv->vval.v_list = l;
10519 ++l->lv_refcount;
10520
Bram Moolenaar33570922005-01-25 22:26:29 +000010521 todo = d->dv_hashtab.ht_used;
10522 for (hi = d->dv_hashtab.ht_array; todo > 0; ++hi)
Bram Moolenaar8c711452005-01-14 21:53:12 +000010523 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000010524 if (!HASHITEM_EMPTY(hi))
Bram Moolenaar8c711452005-01-14 21:53:12 +000010525 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000010526 --todo;
10527 di = HI2DI(hi);
Bram Moolenaar8c711452005-01-14 21:53:12 +000010528
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000010529 li = listitem_alloc();
10530 if (li == NULL)
Bram Moolenaar8c711452005-01-14 21:53:12 +000010531 break;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000010532 list_append(l, li);
Bram Moolenaar8c711452005-01-14 21:53:12 +000010533
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000010534 if (what == 0)
10535 {
10536 /* keys() */
10537 li->li_tv.v_type = VAR_STRING;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000010538 li->li_tv.v_lock = 0;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000010539 li->li_tv.vval.v_string = vim_strsave(di->di_key);
10540 }
10541 else if (what == 1)
10542 {
10543 /* values() */
10544 copy_tv(&di->di_tv, &li->li_tv);
10545 }
10546 else
10547 {
10548 /* items() */
10549 l2 = list_alloc();
10550 li->li_tv.v_type = VAR_LIST;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000010551 li->li_tv.v_lock = 0;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000010552 li->li_tv.vval.v_list = l2;
10553 if (l2 == NULL)
10554 break;
10555 ++l2->lv_refcount;
10556
10557 li2 = listitem_alloc();
10558 if (li2 == NULL)
10559 break;
10560 list_append(l2, li2);
10561 li2->li_tv.v_type = VAR_STRING;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000010562 li2->li_tv.v_lock = 0;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000010563 li2->li_tv.vval.v_string = vim_strsave(di->di_key);
10564
10565 li2 = listitem_alloc();
10566 if (li2 == NULL)
10567 break;
10568 list_append(l2, li2);
10569 copy_tv(&di->di_tv, &li2->li_tv);
10570 }
Bram Moolenaar8c711452005-01-14 21:53:12 +000010571 }
10572 }
10573}
10574
10575/*
10576 * "items(dict)" function
10577 */
10578 static void
10579f_items(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010580 typval_T *argvars;
10581 typval_T *rettv;
Bram Moolenaar8c711452005-01-14 21:53:12 +000010582{
10583 dict_list(argvars, rettv, 2);
10584}
10585
Bram Moolenaar071d4272004-06-13 20:20:40 +000010586/*
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000010587 * "join()" function
10588 */
10589 static void
10590f_join(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010591 typval_T *argvars;
10592 typval_T *rettv;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000010593{
10594 garray_T ga;
10595 char_u *sep;
10596
10597 rettv->vval.v_number = 0;
10598 if (argvars[0].v_type != VAR_LIST)
10599 {
10600 EMSG(_(e_listreq));
10601 return;
10602 }
10603 if (argvars[0].vval.v_list == NULL)
10604 return;
10605 if (argvars[1].v_type == VAR_UNKNOWN)
10606 sep = (char_u *)" ";
10607 else
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010608 sep = get_tv_string_chk(&argvars[1]);
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000010609
10610 rettv->v_type = VAR_STRING;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010611
10612 if (sep != NULL)
10613 {
10614 ga_init2(&ga, (int)sizeof(char), 80);
10615 list_join(&ga, argvars[0].vval.v_list, sep, TRUE);
10616 ga_append(&ga, NUL);
10617 rettv->vval.v_string = (char_u *)ga.ga_data;
10618 }
10619 else
10620 rettv->vval.v_string = NULL;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000010621}
10622
10623/*
Bram Moolenaar8c711452005-01-14 21:53:12 +000010624 * "keys()" function
10625 */
10626 static void
10627f_keys(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010628 typval_T *argvars;
10629 typval_T *rettv;
Bram Moolenaar8c711452005-01-14 21:53:12 +000010630{
10631 dict_list(argvars, rettv, 0);
10632}
10633
10634/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000010635 * "last_buffer_nr()" function.
10636 */
10637/*ARGSUSED*/
10638 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010639f_last_buffer_nr(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010640 typval_T *argvars;
10641 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010642{
10643 int n = 0;
10644 buf_T *buf;
10645
10646 for (buf = firstbuf; buf != NULL; buf = buf->b_next)
10647 if (n < buf->b_fnum)
10648 n = buf->b_fnum;
10649
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010650 rettv->vval.v_number = n;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010651}
10652
10653/*
10654 * "len()" function
10655 */
10656 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010657f_len(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010658 typval_T *argvars;
10659 typval_T *rettv;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010660{
10661 switch (argvars[0].v_type)
10662 {
10663 case VAR_STRING:
10664 case VAR_NUMBER:
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010665 rettv->vval.v_number = (varnumber_T)STRLEN(
10666 get_tv_string(&argvars[0]));
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010667 break;
10668 case VAR_LIST:
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010669 rettv->vval.v_number = list_len(argvars[0].vval.v_list);
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010670 break;
Bram Moolenaare9a41262005-01-15 22:18:47 +000010671 case VAR_DICT:
10672 rettv->vval.v_number = dict_len(argvars[0].vval.v_dict);
10673 break;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010674 default:
Bram Moolenaare49b69a2005-01-08 16:11:57 +000010675 EMSG(_("E701: Invalid type for len()"));
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010676 break;
10677 }
10678}
10679
Bram Moolenaar33570922005-01-25 22:26:29 +000010680static void libcall_common __ARGS((typval_T *argvars, typval_T *rettv, int type));
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010681
10682 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010683libcall_common(argvars, rettv, type)
Bram Moolenaar33570922005-01-25 22:26:29 +000010684 typval_T *argvars;
10685 typval_T *rettv;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010686 int type;
10687{
10688#ifdef FEAT_LIBCALL
10689 char_u *string_in;
10690 char_u **string_result;
10691 int nr_result;
10692#endif
10693
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010694 rettv->v_type = type;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010695 if (type == VAR_NUMBER)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010696 rettv->vval.v_number = 0;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010697 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010698 rettv->vval.v_string = NULL;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010699
10700 if (check_restricted() || check_secure())
10701 return;
10702
10703#ifdef FEAT_LIBCALL
10704 /* The first two args must be strings, otherwise its meaningless */
10705 if (argvars[0].v_type == VAR_STRING && argvars[1].v_type == VAR_STRING)
10706 {
Bram Moolenaar758711c2005-02-02 23:11:38 +000010707 string_in = NULL;
10708 if (argvars[2].v_type == VAR_STRING)
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010709 string_in = argvars[2].vval.v_string;
10710 if (type == VAR_NUMBER)
10711 string_result = NULL;
10712 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010713 string_result = &rettv->vval.v_string;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010714 if (mch_libcall(argvars[0].vval.v_string,
10715 argvars[1].vval.v_string,
10716 string_in,
10717 argvars[2].vval.v_number,
10718 string_result,
10719 &nr_result) == OK
10720 && type == VAR_NUMBER)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010721 rettv->vval.v_number = nr_result;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010722 }
10723#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000010724}
10725
10726/*
Bram Moolenaar0d660222005-01-07 21:51:51 +000010727 * "libcall()" function
10728 */
10729 static void
10730f_libcall(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010731 typval_T *argvars;
10732 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000010733{
10734 libcall_common(argvars, rettv, VAR_STRING);
10735}
10736
10737/*
10738 * "libcallnr()" function
10739 */
10740 static void
10741f_libcallnr(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010742 typval_T *argvars;
10743 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000010744{
10745 libcall_common(argvars, rettv, VAR_NUMBER);
10746}
10747
10748/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000010749 * "line(string)" function
10750 */
10751 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010752f_line(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010753 typval_T *argvars;
10754 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010755{
10756 linenr_T lnum = 0;
10757 pos_T *fp;
10758
10759 fp = var2fpos(&argvars[0], TRUE);
10760 if (fp != NULL)
10761 lnum = fp->lnum;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010762 rettv->vval.v_number = lnum;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010763}
10764
10765/*
10766 * "line2byte(lnum)" function
10767 */
10768/*ARGSUSED*/
10769 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010770f_line2byte(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010771 typval_T *argvars;
10772 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010773{
10774#ifndef FEAT_BYTEOFF
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010775 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010776#else
10777 linenr_T lnum;
10778
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010779 lnum = get_tv_lnum(argvars);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010780 if (lnum < 1 || lnum > curbuf->b_ml.ml_line_count + 1)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010781 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010782 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010783 rettv->vval.v_number = ml_find_line_or_offset(curbuf, lnum, NULL);
10784 if (rettv->vval.v_number >= 0)
10785 ++rettv->vval.v_number;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010786#endif
10787}
10788
10789/*
10790 * "lispindent(lnum)" function
10791 */
10792 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010793f_lispindent(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010794 typval_T *argvars;
10795 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010796{
10797#ifdef FEAT_LISP
10798 pos_T pos;
10799 linenr_T lnum;
10800
10801 pos = curwin->w_cursor;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010802 lnum = get_tv_lnum(argvars);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010803 if (lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count)
10804 {
10805 curwin->w_cursor.lnum = lnum;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010806 rettv->vval.v_number = get_lisp_indent();
Bram Moolenaar071d4272004-06-13 20:20:40 +000010807 curwin->w_cursor = pos;
10808 }
10809 else
10810#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010811 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010812}
10813
10814/*
10815 * "localtime()" function
10816 */
10817/*ARGSUSED*/
10818 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010819f_localtime(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010820 typval_T *argvars;
10821 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010822{
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010823 rettv->vval.v_number = (varnumber_T)time(NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010824}
10825
Bram Moolenaar33570922005-01-25 22:26:29 +000010826static void get_maparg __ARGS((typval_T *argvars, typval_T *rettv, int exact));
Bram Moolenaar071d4272004-06-13 20:20:40 +000010827
10828 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010829get_maparg(argvars, rettv, exact)
Bram Moolenaar33570922005-01-25 22:26:29 +000010830 typval_T *argvars;
10831 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010832 int exact;
10833{
10834 char_u *keys;
10835 char_u *which;
10836 char_u buf[NUMBUFLEN];
10837 char_u *keys_buf = NULL;
10838 char_u *rhs;
10839 int mode;
10840 garray_T ga;
10841
10842 /* return empty string for failure */
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010843 rettv->v_type = VAR_STRING;
10844 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010845
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010846 keys = get_tv_string(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010847 if (*keys == NUL)
10848 return;
10849
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010850 if (argvars[1].v_type != VAR_UNKNOWN)
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010851 which = get_tv_string_buf_chk(&argvars[1], buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010852 else
10853 which = (char_u *)"";
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010854 if (which == NULL)
10855 return;
10856
Bram Moolenaar071d4272004-06-13 20:20:40 +000010857 mode = get_map_mode(&which, 0);
10858
10859 keys = replace_termcodes(keys, &keys_buf, TRUE, TRUE);
Bram Moolenaarf4630b62005-05-20 21:31:17 +000010860 rhs = check_map(keys, mode, exact, FALSE);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010861 vim_free(keys_buf);
10862 if (rhs != NULL)
10863 {
10864 ga_init(&ga);
10865 ga.ga_itemsize = 1;
10866 ga.ga_growsize = 40;
10867
10868 while (*rhs != NUL)
10869 ga_concat(&ga, str2special(&rhs, FALSE));
10870
10871 ga_append(&ga, NUL);
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010872 rettv->vval.v_string = (char_u *)ga.ga_data;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010873 }
10874}
10875
10876/*
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000010877 * "map()" function
10878 */
10879 static void
10880f_map(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010881 typval_T *argvars;
10882 typval_T *rettv;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000010883{
10884 filter_map(argvars, rettv, TRUE);
10885}
10886
10887/*
Bram Moolenaar0d660222005-01-07 21:51:51 +000010888 * "maparg()" function
Bram Moolenaar071d4272004-06-13 20:20:40 +000010889 */
10890 static void
Bram Moolenaar0d660222005-01-07 21:51:51 +000010891f_maparg(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010892 typval_T *argvars;
10893 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010894{
Bram Moolenaar0d660222005-01-07 21:51:51 +000010895 get_maparg(argvars, rettv, TRUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010896}
10897
10898/*
Bram Moolenaar0d660222005-01-07 21:51:51 +000010899 * "mapcheck()" function
Bram Moolenaar071d4272004-06-13 20:20:40 +000010900 */
10901 static void
Bram Moolenaar0d660222005-01-07 21:51:51 +000010902f_mapcheck(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010903 typval_T *argvars;
10904 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010905{
Bram Moolenaar0d660222005-01-07 21:51:51 +000010906 get_maparg(argvars, rettv, FALSE);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010907}
10908
Bram Moolenaar33570922005-01-25 22:26:29 +000010909static void find_some_match __ARGS((typval_T *argvars, typval_T *rettv, int start));
Bram Moolenaar071d4272004-06-13 20:20:40 +000010910
10911 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010912find_some_match(argvars, rettv, type)
Bram Moolenaar33570922005-01-25 22:26:29 +000010913 typval_T *argvars;
10914 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010915 int type;
10916{
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000010917 char_u *str = NULL;
10918 char_u *expr = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010919 char_u *pat;
10920 regmatch_T regmatch;
10921 char_u patbuf[NUMBUFLEN];
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000010922 char_u strbuf[NUMBUFLEN];
Bram Moolenaar071d4272004-06-13 20:20:40 +000010923 char_u *save_cpo;
10924 long start = 0;
Bram Moolenaar89cb5e02004-07-19 20:55:54 +000010925 long nth = 1;
Bram Moolenaar81bf7082005-02-12 14:31:42 +000010926 int match = 0;
Bram Moolenaar33570922005-01-25 22:26:29 +000010927 list_T *l = NULL;
10928 listitem_T *li = NULL;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000010929 long idx = 0;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000010930 char_u *tofree = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010931
10932 /* Make 'cpoptions' empty, the 'l' flag should not be used here. */
10933 save_cpo = p_cpo;
10934 p_cpo = (char_u *)"";
10935
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000010936 rettv->vval.v_number = -1;
10937 if (type == 3)
10938 {
10939 /* return empty list when there are no matches */
10940 if ((rettv->vval.v_list = list_alloc()) == NULL)
10941 goto theend;
10942 rettv->v_type = VAR_LIST;
10943 ++rettv->vval.v_list->lv_refcount;
10944 }
10945 else if (type == 2)
Bram Moolenaar071d4272004-06-13 20:20:40 +000010946 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010947 rettv->v_type = VAR_STRING;
10948 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010949 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000010950
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000010951 if (argvars[0].v_type == VAR_LIST)
10952 {
10953 if ((l = argvars[0].vval.v_list) == NULL)
10954 goto theend;
10955 li = l->lv_first;
10956 }
10957 else
10958 expr = str = get_tv_string(&argvars[0]);
10959
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010960 pat = get_tv_string_buf_chk(&argvars[1], patbuf);
10961 if (pat == NULL)
10962 goto theend;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000010963
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010964 if (argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +000010965 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010966 int error = FALSE;
10967
10968 start = get_tv_number_chk(&argvars[2], &error);
10969 if (error)
10970 goto theend;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000010971 if (l != NULL)
10972 {
10973 li = list_find(l, start);
10974 if (li == NULL)
10975 goto theend;
Bram Moolenaar758711c2005-02-02 23:11:38 +000010976 idx = l->lv_idx; /* use the cached index */
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000010977 }
10978 else
10979 {
10980 if (start < 0)
10981 start = 0;
10982 if (start > (long)STRLEN(str))
10983 goto theend;
10984 str += start;
10985 }
Bram Moolenaar89cb5e02004-07-19 20:55:54 +000010986
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010987 if (argvars[3].v_type != VAR_UNKNOWN)
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010988 nth = get_tv_number_chk(&argvars[3], &error);
10989 if (error)
10990 goto theend;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010991 }
10992
10993 regmatch.regprog = vim_regcomp(pat, RE_MAGIC + RE_STRING);
10994 if (regmatch.regprog != NULL)
10995 {
10996 regmatch.rm_ic = p_ic;
Bram Moolenaar89cb5e02004-07-19 20:55:54 +000010997
10998 while (1)
10999 {
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000011000 if (l != NULL)
11001 {
11002 if (li == NULL)
11003 {
11004 match = FALSE;
11005 break;
11006 }
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000011007 vim_free(tofree);
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000011008 str = echo_string(&li->li_tv, &tofree, strbuf);
Bram Moolenaar81bf7082005-02-12 14:31:42 +000011009 if (str == NULL)
11010 break;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000011011 }
11012
Bram Moolenaar89cb5e02004-07-19 20:55:54 +000011013 match = vim_regexec_nl(&regmatch, str, (colnr_T)0);
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000011014
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000011015 if (match && --nth <= 0)
Bram Moolenaar89cb5e02004-07-19 20:55:54 +000011016 break;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000011017 if (l == NULL && !match)
11018 break;
11019
Bram Moolenaar89cb5e02004-07-19 20:55:54 +000011020 /* Advance to just after the match. */
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000011021 if (l != NULL)
11022 {
11023 li = li->li_next;
11024 ++idx;
11025 }
11026 else
11027 {
Bram Moolenaar89cb5e02004-07-19 20:55:54 +000011028#ifdef FEAT_MBYTE
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000011029 str = regmatch.startp[0] + mb_ptr2len_check(regmatch.startp[0]);
Bram Moolenaar89cb5e02004-07-19 20:55:54 +000011030#else
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000011031 str = regmatch.startp[0] + 1;
Bram Moolenaar89cb5e02004-07-19 20:55:54 +000011032#endif
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000011033 }
Bram Moolenaar89cb5e02004-07-19 20:55:54 +000011034 }
11035
11036 if (match)
Bram Moolenaar071d4272004-06-13 20:20:40 +000011037 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000011038 if (type == 3)
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000011039 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000011040 int i;
11041
11042 /* return list with matched string and submatches */
11043 for (i = 0; i < NSUBEXP; ++i)
11044 {
11045 if (regmatch.endp[i] == NULL)
11046 break;
11047 li = listitem_alloc();
11048 if (li == NULL)
11049 break;
11050 li->li_tv.v_type = VAR_STRING;
11051 li->li_tv.v_lock = 0;
11052 li->li_tv.vval.v_string = vim_strnsave(regmatch.startp[i],
11053 (int)(regmatch.endp[i] - regmatch.startp[i]));
11054 list_append(rettv->vval.v_list, li);
11055 }
11056 }
11057 else if (type == 2)
11058 {
11059 /* return matched string */
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000011060 if (l != NULL)
11061 copy_tv(&li->li_tv, rettv);
11062 else
11063 rettv->vval.v_string = vim_strnsave(regmatch.startp[0],
Bram Moolenaar071d4272004-06-13 20:20:40 +000011064 (int)(regmatch.endp[0] - regmatch.startp[0]));
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000011065 }
11066 else if (l != NULL)
11067 rettv->vval.v_number = idx;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011068 else
11069 {
11070 if (type != 0)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011071 rettv->vval.v_number =
Bram Moolenaar071d4272004-06-13 20:20:40 +000011072 (varnumber_T)(regmatch.startp[0] - str);
11073 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011074 rettv->vval.v_number =
Bram Moolenaar071d4272004-06-13 20:20:40 +000011075 (varnumber_T)(regmatch.endp[0] - str);
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011076 rettv->vval.v_number += str - expr;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011077 }
11078 }
11079 vim_free(regmatch.regprog);
11080 }
11081
11082theend:
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000011083 vim_free(tofree);
Bram Moolenaar071d4272004-06-13 20:20:40 +000011084 p_cpo = save_cpo;
11085}
11086
11087/*
Bram Moolenaar0d660222005-01-07 21:51:51 +000011088 * "match()" function
11089 */
11090 static void
11091f_match(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000011092 typval_T *argvars;
11093 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000011094{
11095 find_some_match(argvars, rettv, 1);
11096}
11097
11098/*
11099 * "matchend()" function
11100 */
11101 static void
11102f_matchend(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000011103 typval_T *argvars;
11104 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000011105{
11106 find_some_match(argvars, rettv, 0);
11107}
11108
11109/*
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000011110 * "matchlist()" function
11111 */
11112 static void
11113f_matchlist(argvars, rettv)
11114 typval_T *argvars;
11115 typval_T *rettv;
11116{
11117 find_some_match(argvars, rettv, 3);
11118}
11119
11120/*
Bram Moolenaar0d660222005-01-07 21:51:51 +000011121 * "matchstr()" function
11122 */
11123 static void
11124f_matchstr(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000011125 typval_T *argvars;
11126 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000011127{
11128 find_some_match(argvars, rettv, 2);
11129}
11130
Bram Moolenaar33570922005-01-25 22:26:29 +000011131static void max_min __ARGS((typval_T *argvars, typval_T *rettv, int domax));
Bram Moolenaar6cc16192005-01-08 21:49:45 +000011132
11133 static void
11134max_min(argvars, rettv, domax)
Bram Moolenaar33570922005-01-25 22:26:29 +000011135 typval_T *argvars;
11136 typval_T *rettv;
Bram Moolenaar6cc16192005-01-08 21:49:45 +000011137 int domax;
11138{
Bram Moolenaar6cc16192005-01-08 21:49:45 +000011139 long n = 0;
11140 long i;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000011141 int error = FALSE;
Bram Moolenaar6cc16192005-01-08 21:49:45 +000011142
11143 if (argvars[0].v_type == VAR_LIST)
11144 {
Bram Moolenaar33570922005-01-25 22:26:29 +000011145 list_T *l;
11146 listitem_T *li;
Bram Moolenaare9a41262005-01-15 22:18:47 +000011147
Bram Moolenaar6cc16192005-01-08 21:49:45 +000011148 l = argvars[0].vval.v_list;
11149 if (l != NULL)
11150 {
11151 li = l->lv_first;
11152 if (li != NULL)
11153 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000011154 n = get_tv_number_chk(&li->li_tv, &error);
Bram Moolenaar6cc16192005-01-08 21:49:45 +000011155 while (1)
11156 {
11157 li = li->li_next;
11158 if (li == NULL)
11159 break;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000011160 i = get_tv_number_chk(&li->li_tv, &error);
Bram Moolenaar6cc16192005-01-08 21:49:45 +000011161 if (domax ? i > n : i < n)
11162 n = i;
11163 }
11164 }
11165 }
11166 }
Bram Moolenaare9a41262005-01-15 22:18:47 +000011167 else if (argvars[0].v_type == VAR_DICT)
11168 {
Bram Moolenaar33570922005-01-25 22:26:29 +000011169 dict_T *d;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000011170 int first = TRUE;
Bram Moolenaar33570922005-01-25 22:26:29 +000011171 hashitem_T *hi;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000011172 int todo;
Bram Moolenaare9a41262005-01-15 22:18:47 +000011173
11174 d = argvars[0].vval.v_dict;
11175 if (d != NULL)
11176 {
Bram Moolenaar33570922005-01-25 22:26:29 +000011177 todo = d->dv_hashtab.ht_used;
11178 for (hi = d->dv_hashtab.ht_array; todo > 0; ++hi)
Bram Moolenaare9a41262005-01-15 22:18:47 +000011179 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000011180 if (!HASHITEM_EMPTY(hi))
Bram Moolenaare9a41262005-01-15 22:18:47 +000011181 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000011182 --todo;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000011183 i = get_tv_number_chk(&HI2DI(hi)->di_tv, &error);
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000011184 if (first)
11185 {
11186 n = i;
11187 first = FALSE;
11188 }
11189 else if (domax ? i > n : i < n)
Bram Moolenaare9a41262005-01-15 22:18:47 +000011190 n = i;
11191 }
11192 }
11193 }
11194 }
Bram Moolenaar6cc16192005-01-08 21:49:45 +000011195 else
Bram Moolenaar758711c2005-02-02 23:11:38 +000011196 EMSG(_(e_listdictarg));
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000011197 rettv->vval.v_number = error ? 0 : n;
Bram Moolenaar6cc16192005-01-08 21:49:45 +000011198}
11199
11200/*
11201 * "max()" function
11202 */
11203 static void
11204f_max(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000011205 typval_T *argvars;
11206 typval_T *rettv;
Bram Moolenaar6cc16192005-01-08 21:49:45 +000011207{
11208 max_min(argvars, rettv, TRUE);
11209}
11210
11211/*
11212 * "min()" function
11213 */
11214 static void
11215f_min(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000011216 typval_T *argvars;
11217 typval_T *rettv;
Bram Moolenaar6cc16192005-01-08 21:49:45 +000011218{
11219 max_min(argvars, rettv, FALSE);
11220}
11221
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000011222static int mkdir_recurse __ARGS((char_u *dir, int prot));
11223
11224/*
11225 * Create the directory in which "dir" is located, and higher levels when
11226 * needed.
11227 */
11228 static int
11229mkdir_recurse(dir, prot)
11230 char_u *dir;
11231 int prot;
11232{
11233 char_u *p;
11234 char_u *updir;
11235 int r = FAIL;
11236
11237 /* Get end of directory name in "dir".
11238 * We're done when it's "/" or "c:/". */
11239 p = gettail_sep(dir);
11240 if (p <= get_past_head(dir))
11241 return OK;
11242
11243 /* If the directory exists we're done. Otherwise: create it.*/
11244 updir = vim_strnsave(dir, (int)(p - dir));
11245 if (updir == NULL)
11246 return FAIL;
11247 if (mch_isdir(updir))
11248 r = OK;
11249 else if (mkdir_recurse(updir, prot) == OK)
11250 r = vim_mkdir_emsg(updir, prot);
11251 vim_free(updir);
11252 return r;
11253}
11254
11255#ifdef vim_mkdir
11256/*
11257 * "mkdir()" function
11258 */
11259 static void
11260f_mkdir(argvars, rettv)
11261 typval_T *argvars;
11262 typval_T *rettv;
11263{
11264 char_u *dir;
11265 char_u buf[NUMBUFLEN];
11266 int prot = 0755;
11267
11268 rettv->vval.v_number = FAIL;
11269 if (check_restricted() || check_secure())
11270 return;
11271
11272 dir = get_tv_string_buf(&argvars[0], buf);
11273 if (argvars[1].v_type != VAR_UNKNOWN)
11274 {
11275 if (argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000011276 prot = get_tv_number_chk(&argvars[2], NULL);
11277 if (prot != -1 && STRCMP(get_tv_string(&argvars[1]), "p") == 0)
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000011278 mkdir_recurse(dir, prot);
11279 }
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000011280 rettv->vval.v_number = prot != -1 ? vim_mkdir_emsg(dir, prot) : 0;
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000011281}
11282#endif
11283
Bram Moolenaar0d660222005-01-07 21:51:51 +000011284/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000011285 * "mode()" function
11286 */
11287/*ARGSUSED*/
11288 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011289f_mode(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000011290 typval_T *argvars;
11291 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011292{
11293 char_u buf[2];
11294
11295#ifdef FEAT_VISUAL
11296 if (VIsual_active)
11297 {
11298 if (VIsual_select)
11299 buf[0] = VIsual_mode + 's' - 'v';
11300 else
11301 buf[0] = VIsual_mode;
11302 }
11303 else
11304#endif
11305 if (State == HITRETURN || State == ASKMORE || State == SETWSIZE)
11306 buf[0] = 'r';
11307 else if (State & INSERT)
11308 {
11309 if (State & REPLACE_FLAG)
11310 buf[0] = 'R';
11311 else
11312 buf[0] = 'i';
11313 }
11314 else if (State & CMDLINE)
11315 buf[0] = 'c';
11316 else
11317 buf[0] = 'n';
11318
11319 buf[1] = NUL;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011320 rettv->vval.v_string = vim_strsave(buf);
11321 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011322}
11323
11324/*
Bram Moolenaar0d660222005-01-07 21:51:51 +000011325 * "nextnonblank()" function
11326 */
11327 static void
11328f_nextnonblank(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000011329 typval_T *argvars;
11330 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000011331{
11332 linenr_T lnum;
11333
11334 for (lnum = get_tv_lnum(argvars); ; ++lnum)
11335 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000011336 if (lnum < 0 || lnum > curbuf->b_ml.ml_line_count)
Bram Moolenaar0d660222005-01-07 21:51:51 +000011337 {
11338 lnum = 0;
11339 break;
11340 }
11341 if (*skipwhite(ml_get(lnum)) != NUL)
11342 break;
11343 }
11344 rettv->vval.v_number = lnum;
11345}
11346
11347/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000011348 * "nr2char()" function
11349 */
11350 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011351f_nr2char(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000011352 typval_T *argvars;
11353 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011354{
11355 char_u buf[NUMBUFLEN];
11356
11357#ifdef FEAT_MBYTE
11358 if (has_mbyte)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011359 buf[(*mb_char2bytes)((int)get_tv_number(&argvars[0]), buf)] = NUL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011360 else
11361#endif
11362 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011363 buf[0] = (char_u)get_tv_number(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +000011364 buf[1] = NUL;
11365 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011366 rettv->v_type = VAR_STRING;
11367 rettv->vval.v_string = vim_strsave(buf);
Bram Moolenaar49cd9572005-01-03 21:06:01 +000011368}
11369
11370/*
Bram Moolenaar0d660222005-01-07 21:51:51 +000011371 * "prevnonblank()" function
11372 */
11373 static void
11374f_prevnonblank(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000011375 typval_T *argvars;
11376 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000011377{
11378 linenr_T lnum;
11379
11380 lnum = get_tv_lnum(argvars);
11381 if (lnum < 1 || lnum > curbuf->b_ml.ml_line_count)
11382 lnum = 0;
11383 else
11384 while (lnum >= 1 && *skipwhite(ml_get(lnum)) == NUL)
11385 --lnum;
11386 rettv->vval.v_number = lnum;
11387}
11388
Bram Moolenaar8c711452005-01-14 21:53:12 +000011389/*
11390 * "range()" function
11391 */
11392 static void
11393f_range(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000011394 typval_T *argvars;
11395 typval_T *rettv;
Bram Moolenaar8c711452005-01-14 21:53:12 +000011396{
11397 long start;
11398 long end;
11399 long stride = 1;
11400 long i;
Bram Moolenaar33570922005-01-25 22:26:29 +000011401 list_T *l;
11402 listitem_T *li;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000011403 int error = FALSE;
Bram Moolenaar8c711452005-01-14 21:53:12 +000011404
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000011405 start = get_tv_number_chk(&argvars[0], &error);
Bram Moolenaar8c711452005-01-14 21:53:12 +000011406 if (argvars[1].v_type == VAR_UNKNOWN)
11407 {
11408 end = start - 1;
11409 start = 0;
11410 }
11411 else
11412 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000011413 end = get_tv_number_chk(&argvars[1], &error);
Bram Moolenaar8c711452005-01-14 21:53:12 +000011414 if (argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000011415 stride = get_tv_number_chk(&argvars[2], &error);
Bram Moolenaar8c711452005-01-14 21:53:12 +000011416 }
11417
11418 rettv->vval.v_number = 0;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000011419 if (error)
11420 return; /* type error; errmsg already given */
Bram Moolenaar8c711452005-01-14 21:53:12 +000011421 if (stride == 0)
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000011422 EMSG(_("E726: Stride is zero"));
Bram Moolenaar92124a32005-06-17 22:03:40 +000011423 else if (stride > 0 ? end + 1 < start : end - 1 > start)
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000011424 EMSG(_("E727: Start past end"));
Bram Moolenaar8c711452005-01-14 21:53:12 +000011425 else
11426 {
11427 l = list_alloc();
11428 if (l != NULL)
11429 {
11430 rettv->v_type = VAR_LIST;
11431 rettv->vval.v_list = l;
11432 ++l->lv_refcount;
11433
11434 for (i = start; stride > 0 ? i <= end : i >= end; i += stride)
11435 {
11436 li = listitem_alloc();
11437 if (li == NULL)
11438 break;
11439 li->li_tv.v_type = VAR_NUMBER;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000011440 li->li_tv.v_lock = 0;
Bram Moolenaar8c711452005-01-14 21:53:12 +000011441 li->li_tv.vval.v_number = i;
11442 list_append(l, li);
11443 }
11444 }
11445 }
11446}
11447
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000011448/*
11449 * "readfile()" function
11450 */
11451 static void
11452f_readfile(argvars, rettv)
11453 typval_T *argvars;
11454 typval_T *rettv;
11455{
11456 int binary = FALSE;
11457 char_u *fname;
11458 FILE *fd;
11459 list_T *l;
11460 listitem_T *li;
11461#define FREAD_SIZE 200 /* optimized for text lines */
11462 char_u buf[FREAD_SIZE];
11463 int readlen; /* size of last fread() */
11464 int buflen; /* nr of valid chars in buf[] */
11465 int filtd; /* how much in buf[] was NUL -> '\n' filtered */
11466 int tolist; /* first byte in buf[] still to be put in list */
11467 int chop; /* how many CR to chop off */
11468 char_u *prev = NULL; /* previously read bytes, if any */
11469 int prevlen = 0; /* length of "prev" if not NULL */
11470 char_u *s;
11471 int len;
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000011472 long maxline = MAXLNUM;
11473 long cnt = 0;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000011474
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000011475 if (argvars[1].v_type != VAR_UNKNOWN)
11476 {
11477 if (STRCMP(get_tv_string(&argvars[1]), "b") == 0)
11478 binary = TRUE;
11479 if (argvars[2].v_type != VAR_UNKNOWN)
11480 maxline = get_tv_number(&argvars[2]);
11481 }
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000011482
11483 l = list_alloc();
11484 if (l == NULL)
11485 return;
11486 rettv->v_type = VAR_LIST;
11487 rettv->vval.v_list = l;
11488 l->lv_refcount = 1;
11489
11490 /* Always open the file in binary mode, library functions have a mind of
11491 * their own about CR-LF conversion. */
11492 fname = get_tv_string(&argvars[0]);
11493 if (*fname == NUL || (fd = mch_fopen((char *)fname, READBIN)) == NULL)
11494 {
11495 EMSG2(_(e_notopen), *fname == NUL ? (char_u *)_("<empty>") : fname);
11496 return;
11497 }
11498
11499 filtd = 0;
Bram Moolenaarb982ca52005-03-28 21:02:15 +000011500 while (cnt < maxline || maxline < 0)
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000011501 {
11502 readlen = fread(buf + filtd, 1, FREAD_SIZE - filtd, fd);
11503 buflen = filtd + readlen;
11504 tolist = 0;
11505 for ( ; filtd < buflen || readlen <= 0; ++filtd)
11506 {
11507 if (buf[filtd] == '\n' || readlen <= 0)
11508 {
11509 /* Only when in binary mode add an empty list item when the
11510 * last line ends in a '\n'. */
11511 if (!binary && readlen == 0 && filtd == 0)
11512 break;
11513
11514 /* Found end-of-line or end-of-file: add a text line to the
11515 * list. */
11516 chop = 0;
11517 if (!binary)
11518 while (filtd - chop - 1 >= tolist
11519 && buf[filtd - chop - 1] == '\r')
11520 ++chop;
11521 len = filtd - tolist - chop;
11522 if (prev == NULL)
11523 s = vim_strnsave(buf + tolist, len);
11524 else
11525 {
11526 s = alloc((unsigned)(prevlen + len + 1));
11527 if (s != NULL)
11528 {
11529 mch_memmove(s, prev, prevlen);
11530 vim_free(prev);
11531 prev = NULL;
11532 mch_memmove(s + prevlen, buf + tolist, len);
11533 s[prevlen + len] = NUL;
11534 }
11535 }
11536 tolist = filtd + 1;
11537
11538 li = listitem_alloc();
11539 if (li == NULL)
11540 {
11541 vim_free(s);
11542 break;
11543 }
11544 li->li_tv.v_type = VAR_STRING;
11545 li->li_tv.v_lock = 0;
11546 li->li_tv.vval.v_string = s;
11547 list_append(l, li);
11548
Bram Moolenaarb982ca52005-03-28 21:02:15 +000011549 if (++cnt >= maxline && maxline >= 0)
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000011550 break;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000011551 if (readlen <= 0)
11552 break;
11553 }
11554 else if (buf[filtd] == NUL)
11555 buf[filtd] = '\n';
11556 }
11557 if (readlen <= 0)
11558 break;
11559
11560 if (tolist == 0)
11561 {
11562 /* "buf" is full, need to move text to an allocated buffer */
11563 if (prev == NULL)
11564 {
11565 prev = vim_strnsave(buf, buflen);
11566 prevlen = buflen;
11567 }
11568 else
11569 {
11570 s = alloc((unsigned)(prevlen + buflen));
11571 if (s != NULL)
11572 {
11573 mch_memmove(s, prev, prevlen);
11574 mch_memmove(s + prevlen, buf, buflen);
11575 vim_free(prev);
11576 prev = s;
11577 prevlen += buflen;
11578 }
11579 }
11580 filtd = 0;
11581 }
11582 else
11583 {
11584 mch_memmove(buf, buf + tolist, buflen - tolist);
11585 filtd -= tolist;
11586 }
11587 }
11588
Bram Moolenaarb982ca52005-03-28 21:02:15 +000011589 /*
11590 * For a negative line count use only the lines at the end of the file,
11591 * free the rest.
11592 */
11593 if (maxline < 0)
11594 while (cnt > -maxline)
11595 {
11596 listitem_remove(l, l->lv_first);
11597 --cnt;
11598 }
11599
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000011600 vim_free(prev);
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000011601 fclose(fd);
11602}
11603
11604
Bram Moolenaar0d660222005-01-07 21:51:51 +000011605#if defined(FEAT_CLIENTSERVER) && defined(FEAT_X11)
11606static void make_connection __ARGS((void));
11607static int check_connection __ARGS((void));
11608
11609 static void
11610make_connection()
11611{
11612 if (X_DISPLAY == NULL
11613# ifdef FEAT_GUI
11614 && !gui.in_use
11615# endif
11616 )
11617 {
11618 x_force_connect = TRUE;
11619 setup_term_clip();
11620 x_force_connect = FALSE;
11621 }
11622}
11623
11624 static int
11625check_connection()
11626{
11627 make_connection();
11628 if (X_DISPLAY == NULL)
11629 {
11630 EMSG(_("E240: No connection to Vim server"));
11631 return FAIL;
11632 }
11633 return OK;
11634}
11635#endif
11636
11637#ifdef FEAT_CLIENTSERVER
Bram Moolenaar33570922005-01-25 22:26:29 +000011638static void remote_common __ARGS((typval_T *argvars, typval_T *rettv, int expr));
Bram Moolenaar0d660222005-01-07 21:51:51 +000011639
11640 static void
11641remote_common(argvars, rettv, expr)
Bram Moolenaar33570922005-01-25 22:26:29 +000011642 typval_T *argvars;
11643 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000011644 int expr;
11645{
11646 char_u *server_name;
11647 char_u *keys;
11648 char_u *r = NULL;
11649 char_u buf[NUMBUFLEN];
11650# ifdef WIN32
11651 HWND w;
11652# else
11653 Window w;
11654# endif
11655
11656 if (check_restricted() || check_secure())
11657 return;
11658
11659# ifdef FEAT_X11
11660 if (check_connection() == FAIL)
11661 return;
11662# endif
11663
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000011664 server_name = get_tv_string_chk(&argvars[0]);
11665 if (server_name == NULL)
11666 return; /* type error; errmsg already given */
Bram Moolenaar0d660222005-01-07 21:51:51 +000011667 keys = get_tv_string_buf(&argvars[1], buf);
11668# ifdef WIN32
11669 if (serverSendToVim(server_name, keys, &r, &w, expr, TRUE) < 0)
11670# else
11671 if (serverSendToVim(X_DISPLAY, server_name, keys, &r, &w, expr, 0, TRUE)
11672 < 0)
11673# endif
11674 {
11675 if (r != NULL)
11676 EMSG(r); /* sending worked but evaluation failed */
11677 else
11678 EMSG2(_("E241: Unable to send to %s"), server_name);
11679 return;
11680 }
11681
11682 rettv->vval.v_string = r;
11683
11684 if (argvars[2].v_type != VAR_UNKNOWN)
11685 {
Bram Moolenaar33570922005-01-25 22:26:29 +000011686 dictitem_T v;
Bram Moolenaar555b2802005-05-19 21:08:39 +000011687 char_u str[30];
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000011688 char_u *idvar;
Bram Moolenaar0d660222005-01-07 21:51:51 +000011689
11690 sprintf((char *)str, "0x%x", (unsigned int)w);
Bram Moolenaar33570922005-01-25 22:26:29 +000011691 v.di_tv.v_type = VAR_STRING;
11692 v.di_tv.vval.v_string = vim_strsave(str);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000011693 idvar = get_tv_string_chk(&argvars[2]);
11694 if (idvar != NULL)
11695 set_var(idvar, &v.di_tv, FALSE);
Bram Moolenaar33570922005-01-25 22:26:29 +000011696 vim_free(v.di_tv.vval.v_string);
Bram Moolenaar0d660222005-01-07 21:51:51 +000011697 }
11698}
11699#endif
11700
11701/*
11702 * "remote_expr()" function
11703 */
11704/*ARGSUSED*/
11705 static void
11706f_remote_expr(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000011707 typval_T *argvars;
11708 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000011709{
11710 rettv->v_type = VAR_STRING;
11711 rettv->vval.v_string = NULL;
11712#ifdef FEAT_CLIENTSERVER
11713 remote_common(argvars, rettv, TRUE);
11714#endif
11715}
11716
11717/*
11718 * "remote_foreground()" function
11719 */
11720/*ARGSUSED*/
11721 static void
11722f_remote_foreground(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000011723 typval_T *argvars;
11724 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000011725{
11726 rettv->vval.v_number = 0;
11727#ifdef FEAT_CLIENTSERVER
11728# ifdef WIN32
11729 /* On Win32 it's done in this application. */
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000011730 {
11731 char_u *server_name = get_tv_string_chk(&argvars[0]);
11732
11733 if (server_name != NULL)
11734 serverForeground(server_name);
11735 }
Bram Moolenaar0d660222005-01-07 21:51:51 +000011736# else
11737 /* Send a foreground() expression to the server. */
11738 argvars[1].v_type = VAR_STRING;
11739 argvars[1].vval.v_string = vim_strsave((char_u *)"foreground()");
11740 argvars[2].v_type = VAR_UNKNOWN;
11741 remote_common(argvars, rettv, TRUE);
11742 vim_free(argvars[1].vval.v_string);
11743# endif
11744#endif
11745}
11746
11747/*ARGSUSED*/
11748 static void
11749f_remote_peek(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000011750 typval_T *argvars;
11751 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000011752{
11753#ifdef FEAT_CLIENTSERVER
Bram Moolenaar33570922005-01-25 22:26:29 +000011754 dictitem_T v;
Bram Moolenaar0d660222005-01-07 21:51:51 +000011755 char_u *s = NULL;
11756# ifdef WIN32
11757 int n = 0;
11758# endif
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000011759 char_u *serverid;
Bram Moolenaar0d660222005-01-07 21:51:51 +000011760
11761 if (check_restricted() || check_secure())
11762 {
11763 rettv->vval.v_number = -1;
11764 return;
11765 }
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000011766 serverid = get_tv_string_chk(&argvars[0]);
11767 if (serverid == NULL)
11768 {
11769 rettv->vval.v_number = -1;
11770 return; /* type error; errmsg already given */
11771 }
Bram Moolenaar0d660222005-01-07 21:51:51 +000011772# ifdef WIN32
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000011773 sscanf(serverid, "%x", &n);
Bram Moolenaar0d660222005-01-07 21:51:51 +000011774 if (n == 0)
11775 rettv->vval.v_number = -1;
11776 else
11777 {
11778 s = serverGetReply((HWND)n, FALSE, FALSE, FALSE);
11779 rettv->vval.v_number = (s != NULL);
11780 }
11781# else
11782 rettv->vval.v_number = 0;
11783 if (check_connection() == FAIL)
11784 return;
11785
11786 rettv->vval.v_number = serverPeekReply(X_DISPLAY,
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000011787 serverStrToWin(serverid), &s);
Bram Moolenaar0d660222005-01-07 21:51:51 +000011788# endif
11789
11790 if (argvars[1].v_type != VAR_UNKNOWN && rettv->vval.v_number > 0)
11791 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000011792 char_u *retvar;
11793
Bram Moolenaar33570922005-01-25 22:26:29 +000011794 v.di_tv.v_type = VAR_STRING;
11795 v.di_tv.vval.v_string = vim_strsave(s);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000011796 retvar = get_tv_string_chk(&argvars[1]);
11797 if (retvar != NULL)
11798 set_var(retvar, &v.di_tv, FALSE);
Bram Moolenaar33570922005-01-25 22:26:29 +000011799 vim_free(v.di_tv.vval.v_string);
Bram Moolenaar0d660222005-01-07 21:51:51 +000011800 }
11801#else
11802 rettv->vval.v_number = -1;
11803#endif
11804}
11805
11806/*ARGSUSED*/
11807 static void
11808f_remote_read(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000011809 typval_T *argvars;
11810 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000011811{
11812 char_u *r = NULL;
11813
11814#ifdef FEAT_CLIENTSERVER
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000011815 char_u *serverid = get_tv_string_chk(&argvars[0]);
11816
11817 if (serverid != NULL && !check_restricted() && !check_secure())
Bram Moolenaar0d660222005-01-07 21:51:51 +000011818 {
11819# ifdef WIN32
11820 /* The server's HWND is encoded in the 'id' parameter */
11821 int n = 0;
11822
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000011823 sscanf(serverid, "%x", &n);
Bram Moolenaar0d660222005-01-07 21:51:51 +000011824 if (n != 0)
11825 r = serverGetReply((HWND)n, FALSE, TRUE, TRUE);
11826 if (r == NULL)
11827# else
11828 if (check_connection() == FAIL || serverReadReply(X_DISPLAY,
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000011829 serverStrToWin(serverid), &r, FALSE) < 0)
Bram Moolenaar0d660222005-01-07 21:51:51 +000011830# endif
11831 EMSG(_("E277: Unable to read a server reply"));
11832 }
11833#endif
11834 rettv->v_type = VAR_STRING;
11835 rettv->vval.v_string = r;
11836}
11837
11838/*
11839 * "remote_send()" function
11840 */
11841/*ARGSUSED*/
11842 static void
11843f_remote_send(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000011844 typval_T *argvars;
11845 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000011846{
11847 rettv->v_type = VAR_STRING;
11848 rettv->vval.v_string = NULL;
11849#ifdef FEAT_CLIENTSERVER
11850 remote_common(argvars, rettv, FALSE);
11851#endif
11852}
11853
11854/*
Bram Moolenaar8c711452005-01-14 21:53:12 +000011855 * "remove()" function
Bram Moolenaar49cd9572005-01-03 21:06:01 +000011856 */
11857 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011858f_remove(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000011859 typval_T *argvars;
11860 typval_T *rettv;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000011861{
Bram Moolenaar33570922005-01-25 22:26:29 +000011862 list_T *l;
11863 listitem_T *item, *item2;
11864 listitem_T *li;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000011865 long idx;
Bram Moolenaar8a283e52005-01-06 23:28:25 +000011866 long end;
Bram Moolenaar8c711452005-01-14 21:53:12 +000011867 char_u *key;
Bram Moolenaar33570922005-01-25 22:26:29 +000011868 dict_T *d;
11869 dictitem_T *di;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000011870
Bram Moolenaar8a283e52005-01-06 23:28:25 +000011871 rettv->vval.v_number = 0;
Bram Moolenaar8c711452005-01-14 21:53:12 +000011872 if (argvars[0].v_type == VAR_DICT)
11873 {
11874 if (argvars[2].v_type != VAR_UNKNOWN)
11875 EMSG2(_(e_toomanyarg), "remove()");
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000011876 else if ((d = argvars[0].vval.v_dict) != NULL
Bram Moolenaar758711c2005-02-02 23:11:38 +000011877 && !tv_check_lock(d->dv_lock, (char_u *)"remove()"))
Bram Moolenaar8c711452005-01-14 21:53:12 +000011878 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000011879 key = get_tv_string_chk(&argvars[1]);
11880 if (key != NULL)
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000011881 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000011882 di = dict_find(d, key, -1);
11883 if (di == NULL)
11884 EMSG2(_(e_dictkey), key);
11885 else
11886 {
11887 *rettv = di->di_tv;
11888 init_tv(&di->di_tv);
11889 dictitem_remove(d, di);
11890 }
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000011891 }
Bram Moolenaar8c711452005-01-14 21:53:12 +000011892 }
11893 }
11894 else if (argvars[0].v_type != VAR_LIST)
11895 EMSG2(_(e_listdictarg), "remove()");
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000011896 else if ((l = argvars[0].vval.v_list) != NULL
11897 && !tv_check_lock(l->lv_lock, (char_u *)"remove()"))
Bram Moolenaar49cd9572005-01-03 21:06:01 +000011898 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000011899 int error = FALSE;
11900
11901 idx = get_tv_number_chk(&argvars[1], &error);
11902 if (error)
11903 ; /* type error: do nothing, errmsg already given */
11904 else if ((item = list_find(l, idx)) == NULL)
Bram Moolenaar49cd9572005-01-03 21:06:01 +000011905 EMSGN(_(e_listidx), idx);
11906 else
11907 {
Bram Moolenaar8a283e52005-01-06 23:28:25 +000011908 if (argvars[2].v_type == VAR_UNKNOWN)
11909 {
11910 /* Remove one item, return its value. */
Bram Moolenaar7480b5c2005-01-16 22:07:38 +000011911 list_remove(l, item, item);
Bram Moolenaar8a283e52005-01-06 23:28:25 +000011912 *rettv = item->li_tv;
11913 vim_free(item);
11914 }
11915 else
11916 {
11917 /* Remove range of items, return list with values. */
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000011918 end = get_tv_number_chk(&argvars[2], &error);
11919 if (error)
11920 ; /* type error: do nothing */
11921 else if ((item2 = list_find(l, end)) == NULL)
Bram Moolenaar8a283e52005-01-06 23:28:25 +000011922 EMSGN(_(e_listidx), end);
11923 else
11924 {
Bram Moolenaar758711c2005-02-02 23:11:38 +000011925 int cnt = 0;
11926
11927 for (li = item; li != NULL; li = li->li_next)
11928 {
11929 ++cnt;
11930 if (li == item2)
11931 break;
11932 }
Bram Moolenaar8a283e52005-01-06 23:28:25 +000011933 if (li == NULL) /* didn't find "item2" after "item" */
11934 EMSG(_(e_invrange));
11935 else
11936 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +000011937 list_remove(l, item, item2);
Bram Moolenaar8a283e52005-01-06 23:28:25 +000011938 l = list_alloc();
11939 if (l != NULL)
11940 {
11941 rettv->v_type = VAR_LIST;
11942 rettv->vval.v_list = l;
11943 l->lv_first = item;
11944 l->lv_last = item2;
11945 l->lv_refcount = 1;
11946 item->li_prev = NULL;
11947 item2->li_next = NULL;
Bram Moolenaar758711c2005-02-02 23:11:38 +000011948 l->lv_len = cnt;
Bram Moolenaar8a283e52005-01-06 23:28:25 +000011949 }
11950 }
11951 }
11952 }
Bram Moolenaar49cd9572005-01-03 21:06:01 +000011953 }
11954 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000011955}
11956
11957/*
11958 * "rename({from}, {to})" function
11959 */
11960 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011961f_rename(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000011962 typval_T *argvars;
11963 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011964{
11965 char_u buf[NUMBUFLEN];
11966
11967 if (check_restricted() || check_secure())
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011968 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011969 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011970 rettv->vval.v_number = vim_rename(get_tv_string(&argvars[0]),
11971 get_tv_string_buf(&argvars[1], buf));
Bram Moolenaar071d4272004-06-13 20:20:40 +000011972}
11973
11974/*
Bram Moolenaar8a283e52005-01-06 23:28:25 +000011975 * "repeat()" function
11976 */
11977/*ARGSUSED*/
11978 static void
11979f_repeat(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000011980 typval_T *argvars;
11981 typval_T *rettv;
Bram Moolenaar8a283e52005-01-06 23:28:25 +000011982{
11983 char_u *p;
11984 int n;
11985 int slen;
11986 int len;
11987 char_u *r;
11988 int i;
Bram Moolenaar33570922005-01-25 22:26:29 +000011989 list_T *l;
Bram Moolenaar8a283e52005-01-06 23:28:25 +000011990
11991 n = get_tv_number(&argvars[1]);
11992 if (argvars[0].v_type == VAR_LIST)
11993 {
11994 l = list_alloc();
11995 if (l != NULL && argvars[0].vval.v_list != NULL)
11996 {
11997 l->lv_refcount = 1;
11998 while (n-- > 0)
11999 if (list_extend(l, argvars[0].vval.v_list, NULL) == FAIL)
12000 break;
12001 }
12002 rettv->v_type = VAR_LIST;
12003 rettv->vval.v_list = l;
12004 }
12005 else
12006 {
12007 p = get_tv_string(&argvars[0]);
12008 rettv->v_type = VAR_STRING;
12009 rettv->vval.v_string = NULL;
12010
12011 slen = (int)STRLEN(p);
12012 len = slen * n;
12013 if (len <= 0)
12014 return;
12015
12016 r = alloc(len + 1);
12017 if (r != NULL)
12018 {
12019 for (i = 0; i < n; i++)
12020 mch_memmove(r + i * slen, p, (size_t)slen);
12021 r[len] = NUL;
12022 }
12023
12024 rettv->vval.v_string = r;
12025 }
12026}
12027
12028/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000012029 * "resolve()" function
12030 */
12031 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012032f_resolve(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000012033 typval_T *argvars;
12034 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012035{
12036 char_u *p;
12037
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012038 p = get_tv_string(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +000012039#ifdef FEAT_SHORTCUT
12040 {
12041 char_u *v = NULL;
12042
12043 v = mch_resolve_shortcut(p);
12044 if (v != NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012045 rettv->vval.v_string = v;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012046 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012047 rettv->vval.v_string = vim_strsave(p);
Bram Moolenaar071d4272004-06-13 20:20:40 +000012048 }
12049#else
12050# ifdef HAVE_READLINK
12051 {
12052 char_u buf[MAXPATHL + 1];
12053 char_u *cpy;
12054 int len;
12055 char_u *remain = NULL;
12056 char_u *q;
12057 int is_relative_to_current = FALSE;
12058 int has_trailing_pathsep = FALSE;
12059 int limit = 100;
12060
12061 p = vim_strsave(p);
12062
12063 if (p[0] == '.' && (vim_ispathsep(p[1])
12064 || (p[1] == '.' && (vim_ispathsep(p[2])))))
12065 is_relative_to_current = TRUE;
12066
12067 len = STRLEN(p);
Bram Moolenaar1cd871b2004-12-19 22:46:22 +000012068 if (len > 0 && after_pathsep(p, p + len))
Bram Moolenaar071d4272004-06-13 20:20:40 +000012069 has_trailing_pathsep = TRUE;
12070
12071 q = getnextcomp(p);
12072 if (*q != NUL)
12073 {
12074 /* Separate the first path component in "p", and keep the
12075 * remainder (beginning with the path separator). */
12076 remain = vim_strsave(q - 1);
12077 q[-1] = NUL;
12078 }
12079
12080 for (;;)
12081 {
12082 for (;;)
12083 {
12084 len = readlink((char *)p, (char *)buf, MAXPATHL);
12085 if (len <= 0)
12086 break;
12087 buf[len] = NUL;
12088
12089 if (limit-- == 0)
12090 {
12091 vim_free(p);
12092 vim_free(remain);
12093 EMSG(_("E655: Too many symbolic links (cycle?)"));
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012094 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012095 goto fail;
12096 }
12097
12098 /* Ensure that the result will have a trailing path separator
12099 * if the argument has one. */
12100 if (remain == NULL && has_trailing_pathsep)
12101 add_pathsep(buf);
12102
12103 /* Separate the first path component in the link value and
12104 * concatenate the remainders. */
12105 q = getnextcomp(vim_ispathsep(*buf) ? buf + 1 : buf);
12106 if (*q != NUL)
12107 {
12108 if (remain == NULL)
12109 remain = vim_strsave(q - 1);
12110 else
12111 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000012112 cpy = vim_strnsave(q-1, STRLEN(q-1) + STRLEN(remain));
Bram Moolenaar071d4272004-06-13 20:20:40 +000012113 if (cpy != NULL)
12114 {
12115 STRCAT(cpy, remain);
12116 vim_free(remain);
12117 remain = cpy;
12118 }
12119 }
12120 q[-1] = NUL;
12121 }
12122
12123 q = gettail(p);
12124 if (q > p && *q == NUL)
12125 {
12126 /* Ignore trailing path separator. */
12127 q[-1] = NUL;
12128 q = gettail(p);
12129 }
12130 if (q > p && !mch_isFullName(buf))
12131 {
12132 /* symlink is relative to directory of argument */
12133 cpy = alloc((unsigned)(STRLEN(p) + STRLEN(buf) + 1));
12134 if (cpy != NULL)
12135 {
12136 STRCPY(cpy, p);
12137 STRCPY(gettail(cpy), buf);
12138 vim_free(p);
12139 p = cpy;
12140 }
12141 }
12142 else
12143 {
12144 vim_free(p);
12145 p = vim_strsave(buf);
12146 }
12147 }
12148
12149 if (remain == NULL)
12150 break;
12151
12152 /* Append the first path component of "remain" to "p". */
12153 q = getnextcomp(remain + 1);
12154 len = q - remain - (*q != NUL);
12155 cpy = vim_strnsave(p, STRLEN(p) + len);
12156 if (cpy != NULL)
12157 {
12158 STRNCAT(cpy, remain, len);
12159 vim_free(p);
12160 p = cpy;
12161 }
12162 /* Shorten "remain". */
12163 if (*q != NUL)
12164 STRCPY(remain, q - 1);
12165 else
12166 {
12167 vim_free(remain);
12168 remain = NULL;
12169 }
12170 }
12171
12172 /* If the result is a relative path name, make it explicitly relative to
12173 * the current directory if and only if the argument had this form. */
12174 if (!vim_ispathsep(*p))
12175 {
12176 if (is_relative_to_current
12177 && *p != NUL
12178 && !(p[0] == '.'
12179 && (p[1] == NUL
12180 || vim_ispathsep(p[1])
12181 || (p[1] == '.'
12182 && (p[2] == NUL
12183 || vim_ispathsep(p[2]))))))
12184 {
12185 /* Prepend "./". */
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000012186 cpy = concat_str((char_u *)"./", p);
Bram Moolenaar071d4272004-06-13 20:20:40 +000012187 if (cpy != NULL)
12188 {
Bram Moolenaar071d4272004-06-13 20:20:40 +000012189 vim_free(p);
12190 p = cpy;
12191 }
12192 }
12193 else if (!is_relative_to_current)
12194 {
12195 /* Strip leading "./". */
12196 q = p;
12197 while (q[0] == '.' && vim_ispathsep(q[1]))
12198 q += 2;
12199 if (q > p)
12200 mch_memmove(p, p + 2, STRLEN(p + 2) + (size_t)1);
12201 }
12202 }
12203
12204 /* Ensure that the result will have no trailing path separator
12205 * if the argument had none. But keep "/" or "//". */
12206 if (!has_trailing_pathsep)
12207 {
12208 q = p + STRLEN(p);
Bram Moolenaar1cd871b2004-12-19 22:46:22 +000012209 if (after_pathsep(p, q))
12210 *gettail_sep(p) = NUL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012211 }
12212
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012213 rettv->vval.v_string = p;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012214 }
12215# else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012216 rettv->vval.v_string = vim_strsave(p);
Bram Moolenaar071d4272004-06-13 20:20:40 +000012217# endif
12218#endif
12219
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012220 simplify_filename(rettv->vval.v_string);
Bram Moolenaar071d4272004-06-13 20:20:40 +000012221
12222#ifdef HAVE_READLINK
12223fail:
12224#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012225 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012226}
12227
12228/*
Bram Moolenaar0d660222005-01-07 21:51:51 +000012229 * "reverse({list})" function
Bram Moolenaar071d4272004-06-13 20:20:40 +000012230 */
12231 static void
Bram Moolenaar0d660222005-01-07 21:51:51 +000012232f_reverse(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000012233 typval_T *argvars;
12234 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012235{
Bram Moolenaar33570922005-01-25 22:26:29 +000012236 list_T *l;
12237 listitem_T *li, *ni;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012238
Bram Moolenaar0d660222005-01-07 21:51:51 +000012239 rettv->vval.v_number = 0;
12240 if (argvars[0].v_type != VAR_LIST)
12241 EMSG2(_(e_listarg), "reverse()");
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000012242 else if ((l = argvars[0].vval.v_list) != NULL
12243 && !tv_check_lock(l->lv_lock, (char_u *)"reverse()"))
Bram Moolenaar0d660222005-01-07 21:51:51 +000012244 {
12245 li = l->lv_last;
Bram Moolenaar81bf7082005-02-12 14:31:42 +000012246 l->lv_first = l->lv_last = NULL;
Bram Moolenaar758711c2005-02-02 23:11:38 +000012247 l->lv_len = 0;
Bram Moolenaar0d660222005-01-07 21:51:51 +000012248 while (li != NULL)
12249 {
12250 ni = li->li_prev;
12251 list_append(l, li);
12252 li = ni;
12253 }
12254 rettv->vval.v_list = l;
12255 rettv->v_type = VAR_LIST;
12256 ++l->lv_refcount;
12257 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000012258}
12259
Bram Moolenaar5eb86f92004-07-26 12:53:41 +000012260#define SP_NOMOVE 1 /* don't move cursor */
12261#define SP_REPEAT 2 /* repeat to find outer pair */
12262#define SP_RETCOUNT 4 /* return matchcount */
12263
Bram Moolenaar33570922005-01-25 22:26:29 +000012264static int get_search_arg __ARGS((typval_T *varp, int *flagsp));
Bram Moolenaar0d660222005-01-07 21:51:51 +000012265
12266/*
12267 * Get flags for a search function.
12268 * Possibly sets "p_ws".
12269 * Returns BACKWARD, FORWARD or zero (for an error).
12270 */
12271 static int
12272get_search_arg(varp, flagsp)
Bram Moolenaar33570922005-01-25 22:26:29 +000012273 typval_T *varp;
Bram Moolenaar0d660222005-01-07 21:51:51 +000012274 int *flagsp;
12275{
12276 int dir = FORWARD;
12277 char_u *flags;
12278 char_u nbuf[NUMBUFLEN];
12279 int mask;
12280
12281 if (varp->v_type != VAR_UNKNOWN)
12282 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000012283 flags = get_tv_string_buf_chk(varp, nbuf);
12284 if (flags == NULL)
12285 return 0; /* type error; errmsg already given */
Bram Moolenaar0d660222005-01-07 21:51:51 +000012286 while (*flags != NUL)
12287 {
12288 switch (*flags)
12289 {
12290 case 'b': dir = BACKWARD; break;
12291 case 'w': p_ws = TRUE; break;
12292 case 'W': p_ws = FALSE; break;
12293 default: mask = 0;
12294 if (flagsp != NULL)
12295 switch (*flags)
12296 {
12297 case 'n': mask = SP_NOMOVE; break;
12298 case 'r': mask = SP_REPEAT; break;
12299 case 'm': mask = SP_RETCOUNT; break;
12300 }
12301 if (mask == 0)
12302 {
12303 EMSG2(_(e_invarg2), flags);
12304 dir = 0;
12305 }
12306 else
12307 *flagsp |= mask;
12308 }
12309 if (dir == 0)
12310 break;
12311 ++flags;
12312 }
12313 }
12314 return dir;
12315}
12316
Bram Moolenaar071d4272004-06-13 20:20:40 +000012317/*
12318 * "search()" function
12319 */
12320 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012321f_search(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000012322 typval_T *argvars;
12323 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012324{
12325 char_u *pat;
12326 pos_T pos;
Bram Moolenaar5eb86f92004-07-26 12:53:41 +000012327 pos_T save_cursor;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012328 int save_p_ws = p_ws;
12329 int dir;
Bram Moolenaar5eb86f92004-07-26 12:53:41 +000012330 int flags = 0;
12331
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012332 rettv->vval.v_number = 0; /* default: FAIL */
Bram Moolenaar071d4272004-06-13 20:20:40 +000012333
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012334 pat = get_tv_string(&argvars[0]);
Bram Moolenaar5eb86f92004-07-26 12:53:41 +000012335 dir = get_search_arg(&argvars[1], &flags); /* may set p_ws */
12336 if (dir == 0)
12337 goto theend;
12338 if ((flags & ~SP_NOMOVE) != 0)
12339 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012340 EMSG2(_(e_invarg2), get_tv_string(&argvars[1]));
Bram Moolenaar5eb86f92004-07-26 12:53:41 +000012341 goto theend;
12342 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000012343
Bram Moolenaar5eb86f92004-07-26 12:53:41 +000012344 pos = save_cursor = curwin->w_cursor;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012345 if (searchit(curwin, curbuf, &pos, dir, pat, 1L,
12346 SEARCH_KEEP, RE_SEARCH) != FAIL)
12347 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012348 rettv->vval.v_number = pos.lnum;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012349 curwin->w_cursor = pos;
12350 /* "/$" will put the cursor after the end of the line, may need to
12351 * correct that here */
12352 check_cursor();
12353 }
Bram Moolenaar5eb86f92004-07-26 12:53:41 +000012354
12355 /* If 'n' flag is used: restore cursor position. */
12356 if (flags & SP_NOMOVE)
12357 curwin->w_cursor = save_cursor;
12358theend:
Bram Moolenaar071d4272004-06-13 20:20:40 +000012359 p_ws = save_p_ws;
12360}
12361
Bram Moolenaar071d4272004-06-13 20:20:40 +000012362/*
12363 * "searchpair()" function
12364 */
12365 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012366f_searchpair(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000012367 typval_T *argvars;
12368 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012369{
12370 char_u *spat, *mpat, *epat;
12371 char_u *skip;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000012372 char_u *pat, *pat2 = NULL, *pat3 = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012373 pos_T pos;
12374 pos_T firstpos;
Bram Moolenaarc9a2d2e2005-04-24 22:09:56 +000012375 pos_T foundpos;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012376 pos_T save_cursor;
12377 pos_T save_pos;
12378 int save_p_ws = p_ws;
12379 char_u *save_cpo;
12380 int dir;
12381 int flags = 0;
12382 char_u nbuf1[NUMBUFLEN];
12383 char_u nbuf2[NUMBUFLEN];
12384 char_u nbuf3[NUMBUFLEN];
12385 int n;
12386 int r;
12387 int nest = 1;
12388 int err;
12389
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012390 rettv->vval.v_number = 0; /* default: FAIL */
Bram Moolenaar071d4272004-06-13 20:20:40 +000012391
12392 /* Make 'cpoptions' empty, the 'l' flag should not be used here. */
12393 save_cpo = p_cpo;
12394 p_cpo = (char_u *)"";
12395
12396 /* Get the three pattern arguments: start, middle, end. */
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000012397 spat = get_tv_string_chk(&argvars[0]);
12398 mpat = get_tv_string_buf_chk(&argvars[1], nbuf1);
12399 epat = get_tv_string_buf_chk(&argvars[2], nbuf2);
12400 if (spat == NULL || mpat == NULL || epat == NULL)
12401 goto theend; /* type error */
Bram Moolenaar071d4272004-06-13 20:20:40 +000012402
12403 /* Make two search patterns: start/end (pat2, for in nested pairs) and
12404 * start/middle/end (pat3, for the top pair). */
12405 pat2 = alloc((unsigned)(STRLEN(spat) + STRLEN(epat) + 15));
12406 pat3 = alloc((unsigned)(STRLEN(spat) + STRLEN(mpat) + STRLEN(epat) + 23));
12407 if (pat2 == NULL || pat3 == NULL)
12408 goto theend;
12409 sprintf((char *)pat2, "\\(%s\\m\\)\\|\\(%s\\m\\)", spat, epat);
12410 if (*mpat == NUL)
12411 STRCPY(pat3, pat2);
12412 else
12413 sprintf((char *)pat3, "\\(%s\\m\\)\\|\\(%s\\m\\)\\|\\(%s\\m\\)",
12414 spat, epat, mpat);
12415
12416 /* Handle the optional fourth argument: flags */
12417 dir = get_search_arg(&argvars[3], &flags); /* may set p_ws */
Bram Moolenaar5eb86f92004-07-26 12:53:41 +000012418 if (dir == 0)
12419 goto theend;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012420
12421 /* Optional fifth argument: skip expresion */
Bram Moolenaar49cd9572005-01-03 21:06:01 +000012422 if (argvars[3].v_type == VAR_UNKNOWN
12423 || argvars[4].v_type == VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +000012424 skip = (char_u *)"";
12425 else
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000012426 skip = get_tv_string_buf_chk(&argvars[4], nbuf3);
12427 if (skip == NULL)
12428 goto theend; /* type error */
Bram Moolenaar071d4272004-06-13 20:20:40 +000012429
12430 save_cursor = curwin->w_cursor;
12431 pos = curwin->w_cursor;
12432 firstpos.lnum = 0;
Bram Moolenaarc9a2d2e2005-04-24 22:09:56 +000012433 foundpos.lnum = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012434 pat = pat3;
12435 for (;;)
12436 {
12437 n = searchit(curwin, curbuf, &pos, dir, pat, 1L,
12438 SEARCH_KEEP, RE_SEARCH);
12439 if (n == FAIL || (firstpos.lnum != 0 && equalpos(pos, firstpos)))
12440 /* didn't find it or found the first match again: FAIL */
12441 break;
12442
12443 if (firstpos.lnum == 0)
12444 firstpos = pos;
Bram Moolenaarc9a2d2e2005-04-24 22:09:56 +000012445 if (equalpos(pos, foundpos))
12446 {
12447 /* Found the same position again. Can happen with a pattern that
12448 * has "\zs" at the end and searching backwards. Advance one
12449 * character and try again. */
12450 if (dir == BACKWARD)
12451 decl(&pos);
12452 else
12453 incl(&pos);
12454 }
12455 foundpos = pos;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012456
12457 /* If the skip pattern matches, ignore this match. */
12458 if (*skip != NUL)
12459 {
12460 save_pos = curwin->w_cursor;
12461 curwin->w_cursor = pos;
12462 r = eval_to_bool(skip, &err, NULL, FALSE);
12463 curwin->w_cursor = save_pos;
12464 if (err)
12465 {
12466 /* Evaluating {skip} caused an error, break here. */
12467 curwin->w_cursor = save_cursor;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012468 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012469 break;
12470 }
12471 if (r)
12472 continue;
12473 }
12474
12475 if ((dir == BACKWARD && n == 3) || (dir == FORWARD && n == 2))
12476 {
12477 /* Found end when searching backwards or start when searching
12478 * forward: nested pair. */
12479 ++nest;
12480 pat = pat2; /* nested, don't search for middle */
12481 }
12482 else
12483 {
12484 /* Found end when searching forward or start when searching
12485 * backward: end of (nested) pair; or found middle in outer pair. */
12486 if (--nest == 1)
12487 pat = pat3; /* outer level, search for middle */
12488 }
12489
12490 if (nest == 0)
12491 {
12492 /* Found the match: return matchcount or line number. */
12493 if (flags & SP_RETCOUNT)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012494 ++rettv->vval.v_number;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012495 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012496 rettv->vval.v_number = pos.lnum;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012497 curwin->w_cursor = pos;
12498 if (!(flags & SP_REPEAT))
12499 break;
12500 nest = 1; /* search for next unmatched */
12501 }
12502 }
12503
12504 /* If 'n' flag is used or search failed: restore cursor position. */
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012505 if ((flags & SP_NOMOVE) || rettv->vval.v_number == 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +000012506 curwin->w_cursor = save_cursor;
12507
12508theend:
12509 vim_free(pat2);
12510 vim_free(pat3);
12511 p_ws = save_p_ws;
12512 p_cpo = save_cpo;
12513}
12514
Bram Moolenaar0d660222005-01-07 21:51:51 +000012515/*ARGSUSED*/
12516 static void
12517f_server2client(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000012518 typval_T *argvars;
12519 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012520{
Bram Moolenaar0d660222005-01-07 21:51:51 +000012521#ifdef FEAT_CLIENTSERVER
12522 char_u buf[NUMBUFLEN];
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000012523 char_u *server = get_tv_string_chk(&argvars[0]);
12524 char_u *reply = get_tv_string_buf_chk(&argvars[1], buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +000012525
Bram Moolenaar0d660222005-01-07 21:51:51 +000012526 rettv->vval.v_number = -1;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000012527 if (server == NULL || reply == NULL)
12528 return;
Bram Moolenaar0d660222005-01-07 21:51:51 +000012529 if (check_restricted() || check_secure())
12530 return;
12531# ifdef FEAT_X11
12532 if (check_connection() == FAIL)
12533 return;
12534# endif
12535
12536 if (serverSendReply(server, reply) < 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +000012537 {
Bram Moolenaar0d660222005-01-07 21:51:51 +000012538 EMSG(_("E258: Unable to send to client"));
12539 return;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012540 }
Bram Moolenaar0d660222005-01-07 21:51:51 +000012541 rettv->vval.v_number = 0;
12542#else
12543 rettv->vval.v_number = -1;
12544#endif
12545}
12546
12547/*ARGSUSED*/
12548 static void
12549f_serverlist(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000012550 typval_T *argvars;
12551 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000012552{
12553 char_u *r = NULL;
12554
12555#ifdef FEAT_CLIENTSERVER
12556# ifdef WIN32
12557 r = serverGetVimNames();
12558# else
12559 make_connection();
12560 if (X_DISPLAY != NULL)
12561 r = serverGetVimNames(X_DISPLAY);
12562# endif
12563#endif
12564 rettv->v_type = VAR_STRING;
12565 rettv->vval.v_string = r;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012566}
12567
12568/*
12569 * "setbufvar()" function
12570 */
12571/*ARGSUSED*/
12572 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012573f_setbufvar(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000012574 typval_T *argvars;
12575 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012576{
12577 buf_T *buf;
12578#ifdef FEAT_AUTOCMD
12579 aco_save_T aco;
12580#else
12581 buf_T *save_curbuf;
12582#endif
12583 char_u *varname, *bufvarname;
Bram Moolenaar33570922005-01-25 22:26:29 +000012584 typval_T *varp;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012585 char_u nbuf[NUMBUFLEN];
12586
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000012587 rettv->vval.v_number = 0;
12588
Bram Moolenaar071d4272004-06-13 20:20:40 +000012589 if (check_restricted() || check_secure())
12590 return;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000012591 (void)get_tv_number(&argvars[0]); /* issue errmsg if type error */
12592 varname = get_tv_string_chk(&argvars[1]);
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012593 buf = get_buf_tv(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +000012594 varp = &argvars[2];
12595
12596 if (buf != NULL && varname != NULL && varp != NULL)
12597 {
12598 /* set curbuf to be our buf, temporarily */
12599#ifdef FEAT_AUTOCMD
12600 aucmd_prepbuf(&aco, buf);
12601#else
12602 save_curbuf = curbuf;
12603 curbuf = buf;
12604#endif
12605
12606 if (*varname == '&')
12607 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000012608 long numval;
12609 char_u *strval;
12610 int error = FALSE;
12611
Bram Moolenaar071d4272004-06-13 20:20:40 +000012612 ++varname;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000012613 numval = get_tv_number_chk(varp, &error);
12614 strval = get_tv_string_buf_chk(varp, nbuf);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000012615 if (!error && strval != NULL)
12616 set_option_value(varname, numval, strval, OPT_LOCAL);
Bram Moolenaar071d4272004-06-13 20:20:40 +000012617 }
12618 else
12619 {
12620 bufvarname = alloc((unsigned)STRLEN(varname) + 3);
12621 if (bufvarname != NULL)
12622 {
12623 STRCPY(bufvarname, "b:");
12624 STRCPY(bufvarname + 2, varname);
Bram Moolenaar1c2fda22005-01-02 11:43:19 +000012625 set_var(bufvarname, varp, TRUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +000012626 vim_free(bufvarname);
12627 }
12628 }
12629
12630 /* reset notion of buffer */
12631#ifdef FEAT_AUTOCMD
12632 aucmd_restbuf(&aco);
12633#else
12634 curbuf = save_curbuf;
12635#endif
12636 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000012637}
12638
12639/*
12640 * "setcmdpos()" function
12641 */
12642 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012643f_setcmdpos(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000012644 typval_T *argvars;
12645 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012646{
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000012647 int pos = (int)get_tv_number(&argvars[0]) - 1;
12648
12649 if (pos >= 0)
12650 rettv->vval.v_number = set_cmdline_pos(pos);
Bram Moolenaar071d4272004-06-13 20:20:40 +000012651}
12652
12653/*
12654 * "setline()" function
12655 */
12656 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012657f_setline(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000012658 typval_T *argvars;
12659 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012660{
12661 linenr_T lnum;
Bram Moolenaar0e6830e2005-05-27 20:23:44 +000012662 char_u *line = NULL;
Bram Moolenaar67fe1a12005-05-22 22:12:58 +000012663 list_T *l = NULL;
12664 listitem_T *li = NULL;
12665 long added = 0;
12666 linenr_T lcount = curbuf->b_ml.ml_line_count;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012667
Bram Moolenaar67fe1a12005-05-22 22:12:58 +000012668 lnum = get_tv_lnum(&argvars[0]);
12669 if (argvars[1].v_type == VAR_LIST)
Bram Moolenaar071d4272004-06-13 20:20:40 +000012670 {
Bram Moolenaar67fe1a12005-05-22 22:12:58 +000012671 l = argvars[1].vval.v_list;
12672 li = l->lv_first;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012673 }
Bram Moolenaar67fe1a12005-05-22 22:12:58 +000012674 else
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000012675 line = get_tv_string_chk(&argvars[1]);
Bram Moolenaar67fe1a12005-05-22 22:12:58 +000012676
12677 rettv->vval.v_number = 0; /* OK */
12678 for (;;)
12679 {
12680 if (l != NULL)
12681 {
12682 /* list argument, get next string */
12683 if (li == NULL)
12684 break;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000012685 line = get_tv_string_chk(&li->li_tv);
Bram Moolenaar67fe1a12005-05-22 22:12:58 +000012686 li = li->li_next;
12687 }
12688
12689 rettv->vval.v_number = 1; /* FAIL */
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000012690 if (line == NULL || lnum < 1 || lnum > curbuf->b_ml.ml_line_count + 1)
Bram Moolenaar67fe1a12005-05-22 22:12:58 +000012691 break;
12692 if (lnum <= curbuf->b_ml.ml_line_count)
12693 {
12694 /* existing line, replace it */
12695 if (u_savesub(lnum) == OK && ml_replace(lnum, line, TRUE) == OK)
12696 {
12697 changed_bytes(lnum, 0);
12698 check_cursor_col();
12699 rettv->vval.v_number = 0; /* OK */
12700 }
12701 }
12702 else if (added > 0 || u_save(lnum - 1, lnum) == OK)
12703 {
12704 /* lnum is one past the last line, append the line */
12705 ++added;
12706 if (ml_append(lnum - 1, line, (colnr_T)0, FALSE) == OK)
12707 rettv->vval.v_number = 0; /* OK */
12708 }
12709
12710 if (l == NULL) /* only one string argument */
12711 break;
12712 ++lnum;
12713 }
12714
12715 if (added > 0)
12716 appended_lines_mark(lcount, added);
Bram Moolenaar071d4272004-06-13 20:20:40 +000012717}
12718
12719/*
Bram Moolenaar2641f772005-03-25 21:58:17 +000012720 * "setqflist()" function
12721 */
12722/*ARGSUSED*/
12723 static void
12724f_setqflist(argvars, rettv)
12725 typval_T *argvars;
12726 typval_T *rettv;
12727{
Bram Moolenaarf4630b62005-05-20 21:31:17 +000012728 char_u *act;
12729 int action = ' ';
12730
Bram Moolenaar2641f772005-03-25 21:58:17 +000012731 rettv->vval.v_number = -1;
12732
12733#ifdef FEAT_QUICKFIX
12734 if (argvars[0].v_type != VAR_LIST)
12735 EMSG(_(e_listreq));
12736 else
12737 {
12738 list_T *l = argvars[0].vval.v_list;
12739
Bram Moolenaarf4630b62005-05-20 21:31:17 +000012740 if (argvars[1].v_type == VAR_STRING)
12741 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000012742 act = get_tv_string_chk(&argvars[1]);
12743 if (act == NULL)
12744 return; /* type error; errmsg already given */
Bram Moolenaarf4630b62005-05-20 21:31:17 +000012745 if (*act == 'a' || *act == 'r')
12746 action = *act;
12747 }
12748
12749 if (l != NULL && set_errorlist(l, action) == OK)
Bram Moolenaar2641f772005-03-25 21:58:17 +000012750 rettv->vval.v_number = 0;
12751 }
12752#endif
12753}
12754
12755/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000012756 * "setreg()" function
12757 */
12758 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012759f_setreg(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000012760 typval_T *argvars;
12761 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012762{
12763 int regname;
12764 char_u *strregname;
12765 char_u *stropt;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000012766 char_u *strval;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012767 int append;
12768 char_u yank_type;
12769 long block_len;
12770
12771 block_len = -1;
12772 yank_type = MAUTO;
12773 append = FALSE;
12774
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000012775 strregname = get_tv_string_chk(argvars);
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012776 rettv->vval.v_number = 1; /* FAIL is default */
Bram Moolenaar071d4272004-06-13 20:20:40 +000012777
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000012778 if (strregname == NULL)
12779 return; /* type error; errmsg already given */
12780 regname = *strregname;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012781 if (regname == 0 || regname == '@')
12782 regname = '"';
12783 else if (regname == '=')
12784 return;
12785
Bram Moolenaar49cd9572005-01-03 21:06:01 +000012786 if (argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +000012787 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000012788 stropt = get_tv_string_chk(&argvars[2]);
12789 if (stropt == NULL)
12790 return; /* type error */
12791 for (; *stropt != NUL; ++stropt)
Bram Moolenaar071d4272004-06-13 20:20:40 +000012792 switch (*stropt)
12793 {
12794 case 'a': case 'A': /* append */
12795 append = TRUE;
12796 break;
12797 case 'v': case 'c': /* character-wise selection */
12798 yank_type = MCHAR;
12799 break;
12800 case 'V': case 'l': /* line-wise selection */
12801 yank_type = MLINE;
12802 break;
12803#ifdef FEAT_VISUAL
12804 case 'b': case Ctrl_V: /* block-wise selection */
12805 yank_type = MBLOCK;
12806 if (VIM_ISDIGIT(stropt[1]))
12807 {
12808 ++stropt;
12809 block_len = getdigits(&stropt) - 1;
12810 --stropt;
12811 }
12812 break;
12813#endif
12814 }
12815 }
12816
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000012817 strval = get_tv_string_chk(&argvars[1]);
12818 if (strval != NULL)
12819 write_reg_contents_ex(regname, strval, -1,
Bram Moolenaar071d4272004-06-13 20:20:40 +000012820 append, yank_type, block_len);
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012821 rettv->vval.v_number = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012822}
12823
12824
12825/*
12826 * "setwinvar(expr)" function
12827 */
12828/*ARGSUSED*/
12829 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012830f_setwinvar(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000012831 typval_T *argvars;
12832 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012833{
12834 win_T *win;
12835#ifdef FEAT_WINDOWS
12836 win_T *save_curwin;
12837#endif
12838 char_u *varname, *winvarname;
Bram Moolenaar33570922005-01-25 22:26:29 +000012839 typval_T *varp;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012840 char_u nbuf[NUMBUFLEN];
12841
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000012842 rettv->vval.v_number = 0;
12843
Bram Moolenaar071d4272004-06-13 20:20:40 +000012844 if (check_restricted() || check_secure())
12845 return;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012846 win = find_win_by_nr(&argvars[0]);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000012847 varname = get_tv_string_chk(&argvars[1]);
Bram Moolenaar071d4272004-06-13 20:20:40 +000012848 varp = &argvars[2];
12849
12850 if (win != NULL && varname != NULL && varp != NULL)
12851 {
12852#ifdef FEAT_WINDOWS
12853 /* set curwin to be our win, temporarily */
12854 save_curwin = curwin;
12855 curwin = win;
12856 curbuf = curwin->w_buffer;
12857#endif
12858
12859 if (*varname == '&')
12860 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000012861 long numval;
12862 char_u *strval;
12863 int error = FALSE;
12864
Bram Moolenaar071d4272004-06-13 20:20:40 +000012865 ++varname;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000012866 numval = get_tv_number_chk(varp, &error);
12867 strval = get_tv_string_buf_chk(varp, nbuf);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000012868 if (!error && strval != NULL)
12869 set_option_value(varname, numval, strval, OPT_LOCAL);
Bram Moolenaar071d4272004-06-13 20:20:40 +000012870 }
12871 else
12872 {
12873 winvarname = alloc((unsigned)STRLEN(varname) + 3);
12874 if (winvarname != NULL)
12875 {
12876 STRCPY(winvarname, "w:");
12877 STRCPY(winvarname + 2, varname);
Bram Moolenaar1c2fda22005-01-02 11:43:19 +000012878 set_var(winvarname, varp, TRUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +000012879 vim_free(winvarname);
12880 }
12881 }
12882
12883#ifdef FEAT_WINDOWS
12884 /* Restore current window, if it's still valid (autocomands can make
12885 * it invalid). */
12886 if (win_valid(save_curwin))
12887 {
12888 curwin = save_curwin;
12889 curbuf = curwin->w_buffer;
12890 }
12891#endif
12892 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000012893}
12894
12895/*
Bram Moolenaar0d660222005-01-07 21:51:51 +000012896 * "simplify()" function
Bram Moolenaar071d4272004-06-13 20:20:40 +000012897 */
12898 static void
Bram Moolenaar0d660222005-01-07 21:51:51 +000012899f_simplify(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000012900 typval_T *argvars;
12901 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012902{
Bram Moolenaar0d660222005-01-07 21:51:51 +000012903 char_u *p;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012904
Bram Moolenaar0d660222005-01-07 21:51:51 +000012905 p = get_tv_string(&argvars[0]);
12906 rettv->vval.v_string = vim_strsave(p);
12907 simplify_filename(rettv->vval.v_string); /* simplify in place */
12908 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012909}
12910
Bram Moolenaar0d660222005-01-07 21:51:51 +000012911static int
12912#ifdef __BORLANDC__
12913 _RTLENTRYF
12914#endif
12915 item_compare __ARGS((const void *s1, const void *s2));
12916static int
12917#ifdef __BORLANDC__
12918 _RTLENTRYF
12919#endif
12920 item_compare2 __ARGS((const void *s1, const void *s2));
12921
12922static int item_compare_ic;
12923static char_u *item_compare_func;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000012924static int item_compare_func_err;
Bram Moolenaar0d660222005-01-07 21:51:51 +000012925#define ITEM_COMPARE_FAIL 999
12926
Bram Moolenaar071d4272004-06-13 20:20:40 +000012927/*
Bram Moolenaar0d660222005-01-07 21:51:51 +000012928 * Compare functions for f_sort() below.
Bram Moolenaar071d4272004-06-13 20:20:40 +000012929 */
Bram Moolenaar0d660222005-01-07 21:51:51 +000012930 static int
12931#ifdef __BORLANDC__
12932_RTLENTRYF
12933#endif
12934item_compare(s1, s2)
12935 const void *s1;
12936 const void *s2;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012937{
Bram Moolenaar0d660222005-01-07 21:51:51 +000012938 char_u *p1, *p2;
12939 char_u *tofree1, *tofree2;
12940 int res;
12941 char_u numbuf1[NUMBUFLEN];
12942 char_u numbuf2[NUMBUFLEN];
Bram Moolenaar071d4272004-06-13 20:20:40 +000012943
Bram Moolenaar33570922005-01-25 22:26:29 +000012944 p1 = tv2string(&(*(listitem_T **)s1)->li_tv, &tofree1, numbuf1);
12945 p2 = tv2string(&(*(listitem_T **)s2)->li_tv, &tofree2, numbuf2);
Bram Moolenaar0d660222005-01-07 21:51:51 +000012946 if (item_compare_ic)
12947 res = STRICMP(p1, p2);
Bram Moolenaar071d4272004-06-13 20:20:40 +000012948 else
Bram Moolenaar0d660222005-01-07 21:51:51 +000012949 res = STRCMP(p1, p2);
12950 vim_free(tofree1);
12951 vim_free(tofree2);
12952 return res;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012953}
12954
12955 static int
Bram Moolenaar0d660222005-01-07 21:51:51 +000012956#ifdef __BORLANDC__
12957_RTLENTRYF
Bram Moolenaar071d4272004-06-13 20:20:40 +000012958#endif
Bram Moolenaar0d660222005-01-07 21:51:51 +000012959item_compare2(s1, s2)
12960 const void *s1;
12961 const void *s2;
12962{
12963 int res;
Bram Moolenaar33570922005-01-25 22:26:29 +000012964 typval_T rettv;
12965 typval_T argv[2];
Bram Moolenaar0d660222005-01-07 21:51:51 +000012966 int dummy;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012967
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000012968 /* shortcut after failure in previous call; compare all items equal */
12969 if (item_compare_func_err)
12970 return 0;
12971
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000012972 /* copy the values. This is needed to be able to set v_lock to VAR_FIXED
12973 * in the copy without changing the original list items. */
Bram Moolenaar33570922005-01-25 22:26:29 +000012974 copy_tv(&(*(listitem_T **)s1)->li_tv, &argv[0]);
12975 copy_tv(&(*(listitem_T **)s2)->li_tv, &argv[1]);
Bram Moolenaar0d660222005-01-07 21:51:51 +000012976
12977 rettv.v_type = VAR_UNKNOWN; /* clear_tv() uses this */
12978 res = call_func(item_compare_func, STRLEN(item_compare_func),
Bram Moolenaare9a41262005-01-15 22:18:47 +000012979 &rettv, 2, argv, 0L, 0L, &dummy, TRUE, NULL);
Bram Moolenaar0d660222005-01-07 21:51:51 +000012980 clear_tv(&argv[0]);
12981 clear_tv(&argv[1]);
12982
12983 if (res == FAIL)
12984 res = ITEM_COMPARE_FAIL;
12985 else
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000012986 /* return value has wrong type */
12987 res = get_tv_number_chk(&rettv, &item_compare_func_err);
12988 if (item_compare_func_err)
12989 res = ITEM_COMPARE_FAIL;
Bram Moolenaar0d660222005-01-07 21:51:51 +000012990 clear_tv(&rettv);
12991 return res;
12992}
12993
12994/*
12995 * "sort({list})" function
12996 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000012997 static void
Bram Moolenaar0d660222005-01-07 21:51:51 +000012998f_sort(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000012999 typval_T *argvars;
13000 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013001{
Bram Moolenaar33570922005-01-25 22:26:29 +000013002 list_T *l;
13003 listitem_T *li;
13004 listitem_T **ptrs;
Bram Moolenaar0d660222005-01-07 21:51:51 +000013005 long len;
13006 long i;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013007
Bram Moolenaar0d660222005-01-07 21:51:51 +000013008 rettv->vval.v_number = 0;
13009 if (argvars[0].v_type != VAR_LIST)
13010 EMSG2(_(e_listarg), "sort()");
Bram Moolenaar071d4272004-06-13 20:20:40 +000013011 else
13012 {
Bram Moolenaar0d660222005-01-07 21:51:51 +000013013 l = argvars[0].vval.v_list;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000013014 if (l == NULL || tv_check_lock(l->lv_lock, (char_u *)"sort()"))
Bram Moolenaar0d660222005-01-07 21:51:51 +000013015 return;
13016 rettv->vval.v_list = l;
13017 rettv->v_type = VAR_LIST;
13018 ++l->lv_refcount;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013019
Bram Moolenaar0d660222005-01-07 21:51:51 +000013020 len = list_len(l);
13021 if (len <= 1)
13022 return; /* short list sorts pretty quickly */
Bram Moolenaar071d4272004-06-13 20:20:40 +000013023
Bram Moolenaar0d660222005-01-07 21:51:51 +000013024 item_compare_ic = FALSE;
13025 item_compare_func = NULL;
13026 if (argvars[1].v_type != VAR_UNKNOWN)
13027 {
13028 if (argvars[1].v_type == VAR_FUNC)
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013029 item_compare_func = argvars[1].vval.v_string;
Bram Moolenaar0d660222005-01-07 21:51:51 +000013030 else
13031 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013032 int error = FALSE;
13033
13034 i = get_tv_number_chk(&argvars[1], &error);
13035 if (error)
13036 return; /* type error; errmsg already given */
Bram Moolenaar0d660222005-01-07 21:51:51 +000013037 if (i == 1)
13038 item_compare_ic = TRUE;
13039 else
13040 item_compare_func = get_tv_string(&argvars[1]);
13041 }
13042 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000013043
Bram Moolenaar0d660222005-01-07 21:51:51 +000013044 /* Make an array with each entry pointing to an item in the List. */
Bram Moolenaar33570922005-01-25 22:26:29 +000013045 ptrs = (listitem_T **)alloc((int)(len * sizeof(listitem_T *)));
Bram Moolenaar0d660222005-01-07 21:51:51 +000013046 if (ptrs == NULL)
13047 return;
13048 i = 0;
13049 for (li = l->lv_first; li != NULL; li = li->li_next)
13050 ptrs[i++] = li;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013051
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013052 item_compare_func_err = FALSE;
Bram Moolenaar0d660222005-01-07 21:51:51 +000013053 /* test the compare function */
13054 if (item_compare_func != NULL
13055 && item_compare2((void *)&ptrs[0], (void *)&ptrs[1])
13056 == ITEM_COMPARE_FAIL)
Bram Moolenaare49b69a2005-01-08 16:11:57 +000013057 EMSG(_("E702: Sort compare function failed"));
Bram Moolenaar071d4272004-06-13 20:20:40 +000013058 else
Bram Moolenaar0d660222005-01-07 21:51:51 +000013059 {
13060 /* Sort the array with item pointers. */
Bram Moolenaar33570922005-01-25 22:26:29 +000013061 qsort((void *)ptrs, (size_t)len, sizeof(listitem_T *),
Bram Moolenaar0d660222005-01-07 21:51:51 +000013062 item_compare_func == NULL ? item_compare : item_compare2);
13063
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013064 if (!item_compare_func_err)
13065 {
13066 /* Clear the List and append the items in the sorted order. */
13067 l->lv_first = l->lv_last = NULL;
13068 l->lv_len = 0;
13069 for (i = 0; i < len; ++i)
13070 list_append(l, ptrs[i]);
13071 }
Bram Moolenaar0d660222005-01-07 21:51:51 +000013072 }
13073
13074 vim_free(ptrs);
13075 }
13076}
13077
Bram Moolenaard857f0e2005-06-21 22:37:39 +000013078/*
13079 * "spellbadword()" function
13080 */
13081/* ARGSUSED */
13082 static void
13083f_spellbadword(argvars, rettv)
13084 typval_T *argvars;
13085 typval_T *rettv;
13086{
13087 int attr;
13088 char_u *ptr;
13089 int len;
13090
13091 rettv->vval.v_string = NULL;
13092 rettv->v_type = VAR_STRING;
13093
13094#ifdef FEAT_SYN_HL
13095 /* Find the start of the badly spelled word. */
13096 if (spell_move_to(FORWARD, TRUE, TRUE) == FAIL)
13097 return;
13098
13099 /* Get the length of the word and copy it. */
13100 ptr = ml_get_cursor();
13101 len = spell_check(curwin, ptr, &attr);
13102 rettv->vval.v_string = vim_strnsave(ptr, len);
13103#endif
13104}
13105
13106/*
13107 * "spellsuggest()" function
13108 */
13109 static void
13110f_spellsuggest(argvars, rettv)
13111 typval_T *argvars;
13112 typval_T *rettv;
13113{
13114 char_u *str;
13115 int maxcount;
13116 garray_T ga;
13117 list_T *l;
13118 listitem_T *li;
13119 int i;
13120
13121 l = list_alloc();
13122 if (l == NULL)
13123 return;
13124 rettv->v_type = VAR_LIST;
13125 rettv->vval.v_list = l;
13126 ++l->lv_refcount;
13127
13128#ifdef FEAT_SYN_HL
13129 if (curwin->w_p_spell && *curbuf->b_p_spl != NUL)
13130 {
13131 str = get_tv_string(&argvars[0]);
13132 if (argvars[1].v_type != VAR_UNKNOWN)
13133 {
13134 maxcount = get_tv_number(&argvars[1]);
13135 if (maxcount <= 0)
13136 return;
13137 }
13138 else
13139 maxcount = 25;
13140
13141 spell_suggest_list(&ga, str, maxcount);
13142
13143 for (i = 0; i < ga.ga_len; ++i)
13144 {
13145 str = ((char_u **)ga.ga_data)[i];
13146
13147 li = listitem_alloc();
13148 if (li == NULL)
13149 vim_free(str);
13150 else
13151 {
13152 li->li_tv.v_type = VAR_STRING;
13153 li->li_tv.v_lock = 0;
13154 li->li_tv.vval.v_string = str;
13155 list_append(l, li);
13156 }
13157 }
13158 ga_clear(&ga);
13159 }
13160#endif
13161}
13162
Bram Moolenaar0d660222005-01-07 21:51:51 +000013163 static void
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000013164f_split(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000013165 typval_T *argvars;
13166 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000013167{
13168 char_u *str;
13169 char_u *end;
Bram Moolenaar67fe1a12005-05-22 22:12:58 +000013170 char_u *pat = NULL;
Bram Moolenaar0d660222005-01-07 21:51:51 +000013171 regmatch_T regmatch;
13172 char_u patbuf[NUMBUFLEN];
13173 char_u *save_cpo;
13174 int match;
Bram Moolenaar33570922005-01-25 22:26:29 +000013175 listitem_T *ni;
13176 list_T *l;
Bram Moolenaar0d660222005-01-07 21:51:51 +000013177 colnr_T col = 0;
Bram Moolenaar67fe1a12005-05-22 22:12:58 +000013178 int keepempty = FALSE;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013179 int typeerr = FALSE;
Bram Moolenaar0d660222005-01-07 21:51:51 +000013180
13181 /* Make 'cpoptions' empty, the 'l' flag should not be used here. */
13182 save_cpo = p_cpo;
13183 p_cpo = (char_u *)"";
13184
13185 str = get_tv_string(&argvars[0]);
Bram Moolenaar67fe1a12005-05-22 22:12:58 +000013186 if (argvars[1].v_type != VAR_UNKNOWN)
13187 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013188 pat = get_tv_string_buf_chk(&argvars[1], patbuf);
13189 if (pat == NULL)
13190 typeerr = TRUE;
Bram Moolenaar67fe1a12005-05-22 22:12:58 +000013191 if (argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013192 keepempty = get_tv_number_chk(&argvars[2], &typeerr);
Bram Moolenaar67fe1a12005-05-22 22:12:58 +000013193 }
13194 if (pat == NULL || *pat == NUL)
13195 pat = (char_u *)"[\\x01- ]\\+";
Bram Moolenaar0d660222005-01-07 21:51:51 +000013196
13197 l = list_alloc();
13198 if (l == NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000013199 return;
Bram Moolenaar0d660222005-01-07 21:51:51 +000013200 rettv->v_type = VAR_LIST;
13201 rettv->vval.v_list = l;
13202 ++l->lv_refcount;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013203 if (typeerr)
13204 return;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013205
Bram Moolenaar0d660222005-01-07 21:51:51 +000013206 regmatch.regprog = vim_regcomp(pat, RE_MAGIC + RE_STRING);
13207 if (regmatch.regprog != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000013208 {
Bram Moolenaar0d660222005-01-07 21:51:51 +000013209 regmatch.rm_ic = FALSE;
Bram Moolenaar67fe1a12005-05-22 22:12:58 +000013210 while (*str != NUL || keepempty)
Bram Moolenaar0d660222005-01-07 21:51:51 +000013211 {
Bram Moolenaar67fe1a12005-05-22 22:12:58 +000013212 if (*str == NUL)
13213 match = FALSE; /* empty item at the end */
13214 else
13215 match = vim_regexec_nl(&regmatch, str, col);
Bram Moolenaar0d660222005-01-07 21:51:51 +000013216 if (match)
13217 end = regmatch.startp[0];
13218 else
13219 end = str + STRLEN(str);
Bram Moolenaar54ee7752005-05-31 22:22:17 +000013220 if (keepempty || end > str || (l->lv_len > 0 && *str != NUL
13221 && match && end < regmatch.endp[0]))
Bram Moolenaar0d660222005-01-07 21:51:51 +000013222 {
13223 ni = listitem_alloc();
13224 if (ni == NULL)
13225 break;
13226 ni->li_tv.v_type = VAR_STRING;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000013227 ni->li_tv.v_lock = 0;
Bram Moolenaar0d660222005-01-07 21:51:51 +000013228 ni->li_tv.vval.v_string = vim_strnsave(str, end - str);
13229 list_append(l, ni);
13230 }
13231 if (!match)
13232 break;
13233 /* Advance to just after the match. */
13234 if (regmatch.endp[0] > str)
13235 col = 0;
13236 else
13237 {
13238 /* Don't get stuck at the same match. */
13239#ifdef FEAT_MBYTE
13240 col = mb_ptr2len_check(regmatch.endp[0]);
13241#else
13242 col = 1;
13243#endif
13244 }
13245 str = regmatch.endp[0];
13246 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000013247
Bram Moolenaar0d660222005-01-07 21:51:51 +000013248 vim_free(regmatch.regprog);
Bram Moolenaar071d4272004-06-13 20:20:40 +000013249 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000013250
Bram Moolenaar0d660222005-01-07 21:51:51 +000013251 p_cpo = save_cpo;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013252}
13253
13254#ifdef HAVE_STRFTIME
13255/*
13256 * "strftime({format}[, {time}])" function
13257 */
13258 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013259f_strftime(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000013260 typval_T *argvars;
13261 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013262{
13263 char_u result_buf[256];
13264 struct tm *curtime;
13265 time_t seconds;
13266 char_u *p;
13267
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013268 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013269
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013270 p = get_tv_string(&argvars[0]);
Bram Moolenaar49cd9572005-01-03 21:06:01 +000013271 if (argvars[1].v_type == VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +000013272 seconds = time(NULL);
13273 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013274 seconds = (time_t)get_tv_number(&argvars[1]);
Bram Moolenaar071d4272004-06-13 20:20:40 +000013275 curtime = localtime(&seconds);
13276 /* MSVC returns NULL for an invalid value of seconds. */
13277 if (curtime == NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013278 rettv->vval.v_string = vim_strsave((char_u *)_("(Invalid)"));
Bram Moolenaar071d4272004-06-13 20:20:40 +000013279 else
13280 {
13281# ifdef FEAT_MBYTE
13282 vimconv_T conv;
13283 char_u *enc;
13284
13285 conv.vc_type = CONV_NONE;
13286 enc = enc_locale();
13287 convert_setup(&conv, p_enc, enc);
13288 if (conv.vc_type != CONV_NONE)
13289 p = string_convert(&conv, p, NULL);
13290# endif
13291 if (p != NULL)
13292 (void)strftime((char *)result_buf, sizeof(result_buf),
13293 (char *)p, curtime);
13294 else
13295 result_buf[0] = NUL;
13296
13297# ifdef FEAT_MBYTE
13298 if (conv.vc_type != CONV_NONE)
13299 vim_free(p);
13300 convert_setup(&conv, enc, p_enc);
13301 if (conv.vc_type != CONV_NONE)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013302 rettv->vval.v_string = string_convert(&conv, result_buf, NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +000013303 else
13304# endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013305 rettv->vval.v_string = vim_strsave(result_buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +000013306
13307# ifdef FEAT_MBYTE
13308 /* Release conversion descriptors */
13309 convert_setup(&conv, NULL, NULL);
13310 vim_free(enc);
13311# endif
13312 }
13313}
13314#endif
13315
13316/*
13317 * "stridx()" function
13318 */
13319 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013320f_stridx(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000013321 typval_T *argvars;
13322 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013323{
13324 char_u buf[NUMBUFLEN];
13325 char_u *needle;
13326 char_u *haystack;
Bram Moolenaar33570922005-01-25 22:26:29 +000013327 char_u *save_haystack;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013328 char_u *pos;
Bram Moolenaar33570922005-01-25 22:26:29 +000013329 int start_idx;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013330
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013331 needle = get_tv_string_chk(&argvars[1]);
13332 save_haystack = haystack = get_tv_string_buf_chk(&argvars[0], buf);
Bram Moolenaar33570922005-01-25 22:26:29 +000013333 rettv->vval.v_number = -1;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013334 if (needle == NULL || haystack == NULL)
13335 return; /* type error; errmsg already given */
Bram Moolenaar071d4272004-06-13 20:20:40 +000013336
Bram Moolenaar33570922005-01-25 22:26:29 +000013337 if (argvars[2].v_type != VAR_UNKNOWN)
13338 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013339 int error = FALSE;
13340
13341 start_idx = get_tv_number_chk(&argvars[2], &error);
13342 if (error || start_idx >= (int)STRLEN(haystack))
Bram Moolenaar33570922005-01-25 22:26:29 +000013343 return;
Bram Moolenaar532c7802005-01-27 14:44:31 +000013344 if (start_idx >= 0)
13345 haystack += start_idx;
Bram Moolenaar33570922005-01-25 22:26:29 +000013346 }
13347
13348 pos = (char_u *)strstr((char *)haystack, (char *)needle);
13349 if (pos != NULL)
13350 rettv->vval.v_number = (varnumber_T)(pos - save_haystack);
Bram Moolenaar071d4272004-06-13 20:20:40 +000013351}
13352
13353/*
Bram Moolenaar49cd9572005-01-03 21:06:01 +000013354 * "string()" function
13355 */
13356 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013357f_string(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000013358 typval_T *argvars;
13359 typval_T *rettv;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000013360{
13361 char_u *tofree;
Bram Moolenaar8a283e52005-01-06 23:28:25 +000013362 char_u numbuf[NUMBUFLEN];
Bram Moolenaar49cd9572005-01-03 21:06:01 +000013363
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013364 rettv->v_type = VAR_STRING;
Bram Moolenaar8a283e52005-01-06 23:28:25 +000013365 rettv->vval.v_string = tv2string(&argvars[0], &tofree, numbuf);
Bram Moolenaar49cd9572005-01-03 21:06:01 +000013366 if (tofree == NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013367 rettv->vval.v_string = vim_strsave(rettv->vval.v_string);
Bram Moolenaar071d4272004-06-13 20:20:40 +000013368}
13369
13370/*
13371 * "strlen()" function
13372 */
13373 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013374f_strlen(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000013375 typval_T *argvars;
13376 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013377{
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013378 rettv->vval.v_number = (varnumber_T)(STRLEN(
13379 get_tv_string(&argvars[0])));
Bram Moolenaar071d4272004-06-13 20:20:40 +000013380}
13381
13382/*
13383 * "strpart()" function
13384 */
13385 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013386f_strpart(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000013387 typval_T *argvars;
13388 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013389{
13390 char_u *p;
13391 int n;
13392 int len;
13393 int slen;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013394 int error = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013395
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013396 p = get_tv_string(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +000013397 slen = (int)STRLEN(p);
13398
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013399 n = get_tv_number_chk(&argvars[1], &error);
13400 if (error)
13401 len = 0;
13402 else if (argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013403 len = get_tv_number(&argvars[2]);
Bram Moolenaar071d4272004-06-13 20:20:40 +000013404 else
13405 len = slen - n; /* default len: all bytes that are available. */
13406
13407 /*
13408 * Only return the overlap between the specified part and the actual
13409 * string.
13410 */
13411 if (n < 0)
13412 {
13413 len += n;
13414 n = 0;
13415 }
13416 else if (n > slen)
13417 n = slen;
13418 if (len < 0)
13419 len = 0;
13420 else if (n + len > slen)
13421 len = slen - n;
13422
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013423 rettv->v_type = VAR_STRING;
13424 rettv->vval.v_string = vim_strnsave(p + n, len);
Bram Moolenaar071d4272004-06-13 20:20:40 +000013425}
13426
13427/*
Bram Moolenaar0d660222005-01-07 21:51:51 +000013428 * "strridx()" function
13429 */
13430 static void
13431f_strridx(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000013432 typval_T *argvars;
13433 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000013434{
13435 char_u buf[NUMBUFLEN];
13436 char_u *needle;
13437 char_u *haystack;
13438 char_u *rest;
13439 char_u *lastmatch = NULL;
Bram Moolenaar532c7802005-01-27 14:44:31 +000013440 int haystack_len, end_idx;
Bram Moolenaar0d660222005-01-07 21:51:51 +000013441
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013442 needle = get_tv_string_chk(&argvars[1]);
13443 haystack = get_tv_string_buf_chk(&argvars[0], buf);
Bram Moolenaar532c7802005-01-27 14:44:31 +000013444 haystack_len = STRLEN(haystack);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013445
13446 rettv->vval.v_number = -1;
13447 if (needle == NULL || haystack == NULL)
13448 return; /* type error; errmsg already given */
Bram Moolenaar05159a02005-02-26 23:04:13 +000013449 if (argvars[2].v_type != VAR_UNKNOWN)
13450 {
13451 /* Third argument: upper limit for index */
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013452 end_idx = get_tv_number_chk(&argvars[2], NULL);
Bram Moolenaar05159a02005-02-26 23:04:13 +000013453 if (end_idx < 0)
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013454 return; /* can never find a match */
Bram Moolenaar05159a02005-02-26 23:04:13 +000013455 }
13456 else
13457 end_idx = haystack_len;
13458
Bram Moolenaar0d660222005-01-07 21:51:51 +000013459 if (*needle == NUL)
Bram Moolenaar05159a02005-02-26 23:04:13 +000013460 {
Bram Moolenaar0d660222005-01-07 21:51:51 +000013461 /* Empty string matches past the end. */
Bram Moolenaar05159a02005-02-26 23:04:13 +000013462 lastmatch = haystack + end_idx;
13463 }
Bram Moolenaar0d660222005-01-07 21:51:51 +000013464 else
Bram Moolenaar532c7802005-01-27 14:44:31 +000013465 {
Bram Moolenaar0d660222005-01-07 21:51:51 +000013466 for (rest = haystack; *rest != '\0'; ++rest)
13467 {
13468 rest = (char_u *)strstr((char *)rest, (char *)needle);
Bram Moolenaar532c7802005-01-27 14:44:31 +000013469 if (rest == NULL || rest > haystack + end_idx)
Bram Moolenaar0d660222005-01-07 21:51:51 +000013470 break;
13471 lastmatch = rest;
13472 }
Bram Moolenaar532c7802005-01-27 14:44:31 +000013473 }
Bram Moolenaar0d660222005-01-07 21:51:51 +000013474
13475 if (lastmatch == NULL)
13476 rettv->vval.v_number = -1;
13477 else
13478 rettv->vval.v_number = (varnumber_T)(lastmatch - haystack);
13479}
13480
13481/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000013482 * "strtrans()" function
13483 */
13484 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013485f_strtrans(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000013486 typval_T *argvars;
13487 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013488{
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013489 rettv->v_type = VAR_STRING;
13490 rettv->vval.v_string = transstr(get_tv_string(&argvars[0]));
Bram Moolenaar071d4272004-06-13 20:20:40 +000013491}
13492
13493/*
Bram Moolenaar0d660222005-01-07 21:51:51 +000013494 * "submatch()" function
13495 */
13496 static void
13497f_submatch(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000013498 typval_T *argvars;
13499 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000013500{
13501 rettv->v_type = VAR_STRING;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013502 rettv->vval.v_string =
13503 reg_submatch((int)get_tv_number_chk(&argvars[0], NULL));
Bram Moolenaar0d660222005-01-07 21:51:51 +000013504}
13505
13506/*
13507 * "substitute()" function
13508 */
13509 static void
13510f_substitute(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000013511 typval_T *argvars;
13512 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000013513{
13514 char_u patbuf[NUMBUFLEN];
13515 char_u subbuf[NUMBUFLEN];
13516 char_u flagsbuf[NUMBUFLEN];
13517
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013518 char_u *str = get_tv_string_chk(&argvars[0]);
13519 char_u *pat = get_tv_string_buf_chk(&argvars[1], patbuf);
13520 char_u *sub = get_tv_string_buf_chk(&argvars[2], subbuf);
13521 char_u *flg = get_tv_string_buf_chk(&argvars[3], flagsbuf);
13522
Bram Moolenaar0d660222005-01-07 21:51:51 +000013523 rettv->v_type = VAR_STRING;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013524 if (str == NULL || pat == NULL || sub == NULL || flg == NULL)
13525 rettv->vval.v_string = NULL;
13526 else
13527 rettv->vval.v_string = do_string_sub(str, pat, sub, flg);
Bram Moolenaar0d660222005-01-07 21:51:51 +000013528}
13529
13530/*
Bram Moolenaar54ff3412005-04-20 19:48:33 +000013531 * "synID(lnum, col, trans)" function
Bram Moolenaar071d4272004-06-13 20:20:40 +000013532 */
13533/*ARGSUSED*/
13534 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013535f_synID(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000013536 typval_T *argvars;
13537 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013538{
13539 int id = 0;
13540#ifdef FEAT_SYN_HL
Bram Moolenaar54ff3412005-04-20 19:48:33 +000013541 long lnum;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013542 long col;
13543 int trans;
Bram Moolenaar92124a32005-06-17 22:03:40 +000013544 int transerr = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013545
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013546 lnum = get_tv_lnum(argvars); /* -1 on type error */
13547 col = get_tv_number(&argvars[1]) - 1; /* -1 on type error */
13548 trans = get_tv_number_chk(&argvars[2], &transerr);
Bram Moolenaar071d4272004-06-13 20:20:40 +000013549
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013550 if (!transerr && lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count
Bram Moolenaar54ff3412005-04-20 19:48:33 +000013551 && col >= 0 && col < (long)STRLEN(ml_get(lnum)))
13552 id = syn_get_id(lnum, (colnr_T)col, trans, NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +000013553#endif
13554
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013555 rettv->vval.v_number = id;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013556}
13557
13558/*
13559 * "synIDattr(id, what [, mode])" function
13560 */
13561/*ARGSUSED*/
13562 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013563f_synIDattr(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000013564 typval_T *argvars;
13565 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013566{
13567 char_u *p = NULL;
13568#ifdef FEAT_SYN_HL
13569 int id;
13570 char_u *what;
13571 char_u *mode;
13572 char_u modebuf[NUMBUFLEN];
13573 int modec;
13574
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013575 id = get_tv_number(&argvars[0]);
13576 what = get_tv_string(&argvars[1]);
Bram Moolenaar49cd9572005-01-03 21:06:01 +000013577 if (argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +000013578 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013579 mode = get_tv_string_buf(&argvars[2], modebuf);
Bram Moolenaar071d4272004-06-13 20:20:40 +000013580 modec = TOLOWER_ASC(mode[0]);
13581 if (modec != 't' && modec != 'c'
13582#ifdef FEAT_GUI
13583 && modec != 'g'
13584#endif
13585 )
13586 modec = 0; /* replace invalid with current */
13587 }
13588 else
13589 {
13590#ifdef FEAT_GUI
13591 if (gui.in_use)
13592 modec = 'g';
13593 else
13594#endif
13595 if (t_colors > 1)
13596 modec = 'c';
13597 else
13598 modec = 't';
13599 }
13600
13601
13602 switch (TOLOWER_ASC(what[0]))
13603 {
13604 case 'b':
13605 if (TOLOWER_ASC(what[1]) == 'g') /* bg[#] */
13606 p = highlight_color(id, what, modec);
13607 else /* bold */
13608 p = highlight_has_attr(id, HL_BOLD, modec);
13609 break;
13610
13611 case 'f': /* fg[#] */
13612 p = highlight_color(id, what, modec);
13613 break;
13614
13615 case 'i':
13616 if (TOLOWER_ASC(what[1]) == 'n') /* inverse */
13617 p = highlight_has_attr(id, HL_INVERSE, modec);
13618 else /* italic */
13619 p = highlight_has_attr(id, HL_ITALIC, modec);
13620 break;
13621
13622 case 'n': /* name */
13623 p = get_highlight_name(NULL, id - 1);
13624 break;
13625
13626 case 'r': /* reverse */
13627 p = highlight_has_attr(id, HL_INVERSE, modec);
13628 break;
13629
13630 case 's': /* standout */
13631 p = highlight_has_attr(id, HL_STANDOUT, modec);
13632 break;
13633
Bram Moolenaar5b743bf2005-03-15 22:50:43 +000013634 case 'u':
13635 if (STRLEN(what) <= 5 || TOLOWER_ASC(what[5]) != 'c')
13636 /* underline */
13637 p = highlight_has_attr(id, HL_UNDERLINE, modec);
13638 else
13639 /* undercurl */
13640 p = highlight_has_attr(id, HL_UNDERCURL, modec);
Bram Moolenaar071d4272004-06-13 20:20:40 +000013641 break;
13642 }
13643
13644 if (p != NULL)
13645 p = vim_strsave(p);
13646#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013647 rettv->v_type = VAR_STRING;
13648 rettv->vval.v_string = p;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013649}
13650
13651/*
13652 * "synIDtrans(id)" function
13653 */
13654/*ARGSUSED*/
13655 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013656f_synIDtrans(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{
13660 int id;
13661
13662#ifdef FEAT_SYN_HL
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013663 id = get_tv_number(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +000013664
13665 if (id > 0)
13666 id = syn_get_final_id(id);
13667 else
13668#endif
13669 id = 0;
13670
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013671 rettv->vval.v_number = id;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013672}
13673
13674/*
13675 * "system()" function
13676 */
13677 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013678f_system(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000013679 typval_T *argvars;
13680 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013681{
Bram Moolenaarc0197e22004-09-13 20:26:32 +000013682 char_u *res = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013683 char_u *p;
Bram Moolenaarc0197e22004-09-13 20:26:32 +000013684 char_u *infile = NULL;
13685 char_u buf[NUMBUFLEN];
13686 int err = FALSE;
13687 FILE *fd;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013688
Bram Moolenaar49cd9572005-01-03 21:06:01 +000013689 if (argvars[1].v_type != VAR_UNKNOWN)
Bram Moolenaarc0197e22004-09-13 20:26:32 +000013690 {
13691 /*
13692 * Write the string to a temp file, to be used for input of the shell
13693 * command.
13694 */
13695 if ((infile = vim_tempname('i')) == NULL)
13696 {
13697 EMSG(_(e_notmp));
13698 return;
13699 }
13700
13701 fd = mch_fopen((char *)infile, WRITEBIN);
13702 if (fd == NULL)
13703 {
13704 EMSG2(_(e_notopen), infile);
13705 goto done;
13706 }
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013707 p = get_tv_string_buf_chk(&argvars[1], buf);
13708 if (p == NULL)
13709 goto done; /* type error; errmsg already given */
Bram Moolenaarc0197e22004-09-13 20:26:32 +000013710 if (fwrite(p, STRLEN(p), 1, fd) != 1)
13711 err = TRUE;
13712 if (fclose(fd) != 0)
13713 err = TRUE;
13714 if (err)
13715 {
13716 EMSG(_("E677: Error writing temp file"));
13717 goto done;
13718 }
13719 }
13720
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013721 res = get_cmd_output(get_tv_string(&argvars[0]), infile, SHELL_SILENT);
Bram Moolenaarc0197e22004-09-13 20:26:32 +000013722
Bram Moolenaar071d4272004-06-13 20:20:40 +000013723#ifdef USE_CR
13724 /* translate <CR> into <NL> */
Bram Moolenaarc0197e22004-09-13 20:26:32 +000013725 if (res != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000013726 {
13727 char_u *s;
13728
Bram Moolenaarc0197e22004-09-13 20:26:32 +000013729 for (s = res; *s; ++s)
Bram Moolenaar071d4272004-06-13 20:20:40 +000013730 {
13731 if (*s == CAR)
13732 *s = NL;
13733 }
13734 }
13735#else
13736# ifdef USE_CRNL
13737 /* translate <CR><NL> into <NL> */
Bram Moolenaarc0197e22004-09-13 20:26:32 +000013738 if (res != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000013739 {
13740 char_u *s, *d;
13741
Bram Moolenaarc0197e22004-09-13 20:26:32 +000013742 d = res;
13743 for (s = res; *s; ++s)
Bram Moolenaar071d4272004-06-13 20:20:40 +000013744 {
13745 if (s[0] == CAR && s[1] == NL)
13746 ++s;
13747 *d++ = *s;
13748 }
13749 *d = NUL;
13750 }
13751# endif
13752#endif
Bram Moolenaarc0197e22004-09-13 20:26:32 +000013753
13754done:
13755 if (infile != NULL)
13756 {
13757 mch_remove(infile);
13758 vim_free(infile);
13759 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013760 rettv->v_type = VAR_STRING;
13761 rettv->vval.v_string = res;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013762}
13763
13764/*
Bram Moolenaare2ac10d2005-03-07 23:26:06 +000013765 * "taglist()" function
Bram Moolenaar19a09a12005-03-04 23:39:37 +000013766 */
13767 static void
13768f_taglist(argvars, rettv)
13769 typval_T *argvars;
13770 typval_T *rettv;
13771{
13772 char_u *tag_pattern;
13773 list_T *l;
13774
13775 tag_pattern = get_tv_string(&argvars[0]);
13776
13777 rettv->vval.v_number = FALSE;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013778 if (*tag_pattern == NUL)
13779 return;
Bram Moolenaar19a09a12005-03-04 23:39:37 +000013780
13781 l = list_alloc();
13782 if (l != NULL)
13783 {
13784 if (get_tags(l, tag_pattern) != FAIL)
13785 {
13786 rettv->vval.v_list = l;
13787 rettv->v_type = VAR_LIST;
13788 ++l->lv_refcount;
13789 }
13790 else
13791 list_free(l);
13792 }
13793}
13794
13795/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000013796 * "tempname()" function
13797 */
13798/*ARGSUSED*/
13799 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013800f_tempname(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000013801 typval_T *argvars;
13802 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013803{
13804 static int x = 'A';
13805
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013806 rettv->v_type = VAR_STRING;
13807 rettv->vval.v_string = vim_tempname(x);
Bram Moolenaar071d4272004-06-13 20:20:40 +000013808
13809 /* Advance 'x' to use A-Z and 0-9, so that there are at least 34 different
13810 * names. Skip 'I' and 'O', they are used for shell redirection. */
13811 do
13812 {
13813 if (x == 'Z')
13814 x = '0';
13815 else if (x == '9')
13816 x = 'A';
13817 else
13818 {
13819#ifdef EBCDIC
13820 if (x == 'I')
13821 x = 'J';
13822 else if (x == 'R')
13823 x = 'S';
13824 else
13825#endif
13826 ++x;
13827 }
13828 } while (x == 'I' || x == 'O');
13829}
13830
13831/*
13832 * "tolower(string)" function
13833 */
13834 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013835f_tolower(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000013836 typval_T *argvars;
13837 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013838{
13839 char_u *p;
13840
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013841 p = vim_strsave(get_tv_string(&argvars[0]));
13842 rettv->v_type = VAR_STRING;
13843 rettv->vval.v_string = p;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013844
13845 if (p != NULL)
13846 while (*p != NUL)
13847 {
13848#ifdef FEAT_MBYTE
13849 int l;
13850
13851 if (enc_utf8)
13852 {
13853 int c, lc;
13854
13855 c = utf_ptr2char(p);
13856 lc = utf_tolower(c);
13857 l = utf_ptr2len_check(p);
13858 /* TODO: reallocate string when byte count changes. */
13859 if (utf_char2len(lc) == l)
13860 utf_char2bytes(lc, p);
13861 p += l;
13862 }
13863 else if (has_mbyte && (l = (*mb_ptr2len_check)(p)) > 1)
13864 p += l; /* skip multi-byte character */
13865 else
13866#endif
13867 {
13868 *p = TOLOWER_LOC(*p); /* note that tolower() can be a macro */
13869 ++p;
13870 }
13871 }
13872}
13873
13874/*
13875 * "toupper(string)" function
13876 */
13877 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013878f_toupper(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000013879 typval_T *argvars;
13880 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013881{
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013882 rettv->v_type = VAR_STRING;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013883 rettv->vval.v_string = strup_save(get_tv_string(&argvars[0]));
Bram Moolenaar071d4272004-06-13 20:20:40 +000013884}
13885
13886/*
Bram Moolenaar8299df92004-07-10 09:47:34 +000013887 * "tr(string, fromstr, tostr)" function
13888 */
13889 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013890f_tr(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000013891 typval_T *argvars;
13892 typval_T *rettv;
Bram Moolenaar8299df92004-07-10 09:47:34 +000013893{
13894 char_u *instr;
13895 char_u *fromstr;
13896 char_u *tostr;
13897 char_u *p;
13898#ifdef FEAT_MBYTE
13899 int inlen;
13900 int fromlen;
13901 int tolen;
13902 int idx;
13903 char_u *cpstr;
13904 int cplen;
13905 int first = TRUE;
13906#endif
13907 char_u buf[NUMBUFLEN];
13908 char_u buf2[NUMBUFLEN];
13909 garray_T ga;
13910
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013911 instr = get_tv_string(&argvars[0]);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013912 fromstr = get_tv_string_buf_chk(&argvars[1], buf);
13913 tostr = get_tv_string_buf_chk(&argvars[2], buf2);
Bram Moolenaar8299df92004-07-10 09:47:34 +000013914
13915 /* Default return value: empty string. */
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013916 rettv->v_type = VAR_STRING;
13917 rettv->vval.v_string = NULL;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013918 if (fromstr == NULL || tostr == NULL)
13919 return; /* type error; errmsg already given */
Bram Moolenaar8299df92004-07-10 09:47:34 +000013920 ga_init2(&ga, (int)sizeof(char), 80);
13921
13922#ifdef FEAT_MBYTE
13923 if (!has_mbyte)
13924#endif
13925 /* not multi-byte: fromstr and tostr must be the same length */
13926 if (STRLEN(fromstr) != STRLEN(tostr))
13927 {
Bram Moolenaar5eb86f92004-07-26 12:53:41 +000013928#ifdef FEAT_MBYTE
Bram Moolenaar8299df92004-07-10 09:47:34 +000013929error:
Bram Moolenaar5eb86f92004-07-26 12:53:41 +000013930#endif
Bram Moolenaar8299df92004-07-10 09:47:34 +000013931 EMSG2(_(e_invarg2), fromstr);
13932 ga_clear(&ga);
13933 return;
13934 }
13935
13936 /* fromstr and tostr have to contain the same number of chars */
13937 while (*instr != NUL)
13938 {
13939#ifdef FEAT_MBYTE
13940 if (has_mbyte)
13941 {
13942 inlen = mb_ptr2len_check(instr);
13943 cpstr = instr;
13944 cplen = inlen;
13945 idx = 0;
13946 for (p = fromstr; *p != NUL; p += fromlen)
13947 {
13948 fromlen = mb_ptr2len_check(p);
13949 if (fromlen == inlen && STRNCMP(instr, p, inlen) == 0)
13950 {
13951 for (p = tostr; *p != NUL; p += tolen)
13952 {
13953 tolen = mb_ptr2len_check(p);
13954 if (idx-- == 0)
13955 {
13956 cplen = tolen;
13957 cpstr = p;
13958 break;
13959 }
13960 }
13961 if (*p == NUL) /* tostr is shorter than fromstr */
13962 goto error;
13963 break;
13964 }
13965 ++idx;
13966 }
13967
13968 if (first && cpstr == instr)
13969 {
13970 /* Check that fromstr and tostr have the same number of
13971 * (multi-byte) characters. Done only once when a character
13972 * of instr doesn't appear in fromstr. */
13973 first = FALSE;
13974 for (p = tostr; *p != NUL; p += tolen)
13975 {
13976 tolen = mb_ptr2len_check(p);
13977 --idx;
13978 }
13979 if (idx != 0)
13980 goto error;
13981 }
13982
13983 ga_grow(&ga, cplen);
Bram Moolenaar2df6dcc2004-07-12 15:53:54 +000013984 mch_memmove((char *)ga.ga_data + ga.ga_len, cpstr, (size_t)cplen);
Bram Moolenaar8299df92004-07-10 09:47:34 +000013985 ga.ga_len += cplen;
Bram Moolenaar8299df92004-07-10 09:47:34 +000013986
13987 instr += inlen;
13988 }
13989 else
13990#endif
13991 {
13992 /* When not using multi-byte chars we can do it faster. */
13993 p = vim_strchr(fromstr, *instr);
13994 if (p != NULL)
13995 ga_append(&ga, tostr[p - fromstr]);
13996 else
13997 ga_append(&ga, *instr);
13998 ++instr;
13999 }
14000 }
14001
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014002 rettv->vval.v_string = ga.ga_data;
Bram Moolenaar8299df92004-07-10 09:47:34 +000014003}
14004
14005/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000014006 * "type(expr)" function
14007 */
14008 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014009f_type(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000014010 typval_T *argvars;
14011 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014012{
Bram Moolenaar6cc16192005-01-08 21:49:45 +000014013 int n;
14014
14015 switch (argvars[0].v_type)
14016 {
14017 case VAR_NUMBER: n = 0; break;
14018 case VAR_STRING: n = 1; break;
14019 case VAR_FUNC: n = 2; break;
14020 case VAR_LIST: n = 3; break;
Bram Moolenaar758711c2005-02-02 23:11:38 +000014021 case VAR_DICT: n = 4; break;
Bram Moolenaar6cc16192005-01-08 21:49:45 +000014022 default: EMSG2(_(e_intern2), "f_type()"); n = 0; break;
14023 }
14024 rettv->vval.v_number = n;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014025}
14026
14027/*
Bram Moolenaar8c711452005-01-14 21:53:12 +000014028 * "values(dict)" function
14029 */
14030 static void
14031f_values(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000014032 typval_T *argvars;
14033 typval_T *rettv;
Bram Moolenaar8c711452005-01-14 21:53:12 +000014034{
14035 dict_list(argvars, rettv, 1);
14036}
14037
14038/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000014039 * "virtcol(string)" function
14040 */
14041 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014042f_virtcol(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000014043 typval_T *argvars;
14044 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014045{
14046 colnr_T vcol = 0;
14047 pos_T *fp;
14048
14049 fp = var2fpos(&argvars[0], FALSE);
14050 if (fp != NULL && fp->lnum <= curbuf->b_ml.ml_line_count)
14051 {
14052 getvvcol(curwin, fp, NULL, NULL, &vcol);
14053 ++vcol;
14054 }
14055
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014056 rettv->vval.v_number = vcol;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014057}
14058
14059/*
14060 * "visualmode()" function
14061 */
14062/*ARGSUSED*/
14063 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014064f_visualmode(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000014065 typval_T *argvars;
14066 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014067{
14068#ifdef FEAT_VISUAL
14069 char_u str[2];
14070
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014071 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014072 str[0] = curbuf->b_visual_mode_eval;
14073 str[1] = NUL;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014074 rettv->vval.v_string = vim_strsave(str);
Bram Moolenaar071d4272004-06-13 20:20:40 +000014075
14076 /* A non-zero number or non-empty string argument: reset mode. */
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014077 if ((argvars[0].v_type == VAR_NUMBER
14078 && argvars[0].vval.v_number != 0)
14079 || (argvars[0].v_type == VAR_STRING
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014080 && *get_tv_string(&argvars[0]) != NUL))
Bram Moolenaar071d4272004-06-13 20:20:40 +000014081 curbuf->b_visual_mode_eval = NUL;
14082#else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014083 rettv->vval.v_number = 0; /* return anything, it won't work anyway */
Bram Moolenaar071d4272004-06-13 20:20:40 +000014084#endif
14085}
14086
14087/*
14088 * "winbufnr(nr)" function
14089 */
14090 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014091f_winbufnr(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000014092 typval_T *argvars;
14093 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014094{
14095 win_T *wp;
14096
14097 wp = find_win_by_nr(&argvars[0]);
14098 if (wp == NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014099 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014100 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014101 rettv->vval.v_number = wp->w_buffer->b_fnum;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014102}
14103
14104/*
14105 * "wincol()" function
14106 */
14107/*ARGSUSED*/
14108 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014109f_wincol(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000014110 typval_T *argvars;
14111 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014112{
14113 validate_cursor();
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014114 rettv->vval.v_number = curwin->w_wcol + 1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014115}
14116
14117/*
14118 * "winheight(nr)" function
14119 */
14120 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014121f_winheight(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000014122 typval_T *argvars;
14123 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014124{
14125 win_T *wp;
14126
14127 wp = find_win_by_nr(&argvars[0]);
14128 if (wp == NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014129 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014130 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014131 rettv->vval.v_number = wp->w_height;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014132}
14133
14134/*
14135 * "winline()" function
14136 */
14137/*ARGSUSED*/
14138 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014139f_winline(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000014140 typval_T *argvars;
14141 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014142{
14143 validate_cursor();
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014144 rettv->vval.v_number = curwin->w_wrow + 1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014145}
14146
14147/*
14148 * "winnr()" function
14149 */
14150/* ARGSUSED */
14151 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014152f_winnr(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000014153 typval_T *argvars;
14154 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014155{
14156 int nr = 1;
14157#ifdef FEAT_WINDOWS
14158 win_T *wp;
Bram Moolenaar5eb86f92004-07-26 12:53:41 +000014159 win_T *twin = curwin;
14160 char_u *arg;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014161
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014162 if (argvars[0].v_type != VAR_UNKNOWN)
Bram Moolenaar5eb86f92004-07-26 12:53:41 +000014163 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000014164 arg = get_tv_string_chk(&argvars[0]);
14165 if (arg == NULL)
14166 nr = 0; /* type error; errmsg already given */
14167 else if (STRCMP(arg, "$") == 0)
Bram Moolenaar5eb86f92004-07-26 12:53:41 +000014168 twin = lastwin;
14169 else if (STRCMP(arg, "#") == 0)
14170 {
14171 twin = prevwin;
14172 if (prevwin == NULL)
14173 nr = 0;
14174 }
14175 else
14176 {
14177 EMSG2(_(e_invexpr2), arg);
14178 nr = 0;
14179 }
14180 }
14181
14182 if (nr > 0)
14183 for (wp = firstwin; wp != twin; wp = wp->w_next)
14184 ++nr;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014185#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014186 rettv->vval.v_number = nr;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014187}
14188
14189/*
14190 * "winrestcmd()" function
14191 */
14192/* ARGSUSED */
14193 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014194f_winrestcmd(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000014195 typval_T *argvars;
14196 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014197{
14198#ifdef FEAT_WINDOWS
14199 win_T *wp;
14200 int winnr = 1;
14201 garray_T ga;
14202 char_u buf[50];
14203
14204 ga_init2(&ga, (int)sizeof(char), 70);
14205 for (wp = firstwin; wp != NULL; wp = wp->w_next)
14206 {
14207 sprintf((char *)buf, "%dresize %d|", winnr, wp->w_height);
14208 ga_concat(&ga, buf);
14209# ifdef FEAT_VERTSPLIT
14210 sprintf((char *)buf, "vert %dresize %d|", winnr, wp->w_width);
14211 ga_concat(&ga, buf);
14212# endif
14213 ++winnr;
14214 }
Bram Moolenaar269ec652004-07-29 08:43:53 +000014215 ga_append(&ga, NUL);
Bram Moolenaar071d4272004-06-13 20:20:40 +000014216
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014217 rettv->vval.v_string = ga.ga_data;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014218#else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014219 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014220#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014221 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014222}
14223
14224/*
14225 * "winwidth(nr)" function
14226 */
14227 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014228f_winwidth(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000014229 typval_T *argvars;
14230 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014231{
14232 win_T *wp;
14233
14234 wp = find_win_by_nr(&argvars[0]);
14235 if (wp == NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014236 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014237 else
14238#ifdef FEAT_VERTSPLIT
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014239 rettv->vval.v_number = wp->w_width;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014240#else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014241 rettv->vval.v_number = Columns;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014242#endif
14243}
14244
14245 static win_T *
14246find_win_by_nr(vp)
Bram Moolenaar33570922005-01-25 22:26:29 +000014247 typval_T *vp;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014248{
14249#ifdef FEAT_WINDOWS
14250 win_T *wp;
14251#endif
14252 int nr;
14253
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000014254 nr = get_tv_number_chk(vp, NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +000014255
14256#ifdef FEAT_WINDOWS
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000014257 if (nr < 0)
14258 return NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014259 if (nr == 0)
14260 return curwin;
14261
14262 for (wp = firstwin; wp != NULL; wp = wp->w_next)
14263 if (--nr <= 0)
14264 break;
14265 return wp;
14266#else
14267 if (nr == 0 || nr == 1)
14268 return curwin;
14269 return NULL;
14270#endif
14271}
14272
14273/*
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000014274 * "writefile()" function
14275 */
14276 static void
14277f_writefile(argvars, rettv)
14278 typval_T *argvars;
14279 typval_T *rettv;
14280{
14281 int binary = FALSE;
14282 char_u *fname;
14283 FILE *fd;
14284 listitem_T *li;
14285 char_u *s;
14286 int ret = 0;
14287 int c;
14288
14289 if (argvars[0].v_type != VAR_LIST)
14290 {
14291 EMSG2(_(e_listarg), "writefile()");
14292 return;
14293 }
14294 if (argvars[0].vval.v_list == NULL)
14295 return;
14296
14297 if (argvars[2].v_type != VAR_UNKNOWN
14298 && STRCMP(get_tv_string(&argvars[2]), "b") == 0)
14299 binary = TRUE;
14300
14301 /* Always open the file in binary mode, library functions have a mind of
14302 * their own about CR-LF conversion. */
14303 fname = get_tv_string(&argvars[1]);
14304 if (*fname == NUL || (fd = mch_fopen((char *)fname, WRITEBIN)) == NULL)
14305 {
14306 EMSG2(_(e_notcreate), *fname == NUL ? (char_u *)_("<empty>") : fname);
14307 ret = -1;
14308 }
14309 else
14310 {
14311 for (li = argvars[0].vval.v_list->lv_first; li != NULL;
14312 li = li->li_next)
14313 {
14314 for (s = get_tv_string(&li->li_tv); *s != NUL; ++s)
14315 {
14316 if (*s == '\n')
14317 c = putc(NUL, fd);
14318 else
14319 c = putc(*s, fd);
14320 if (c == EOF)
14321 {
14322 ret = -1;
14323 break;
14324 }
14325 }
14326 if (!binary || li->li_next != NULL)
14327 if (putc('\n', fd) == EOF)
14328 {
14329 ret = -1;
14330 break;
14331 }
14332 if (ret < 0)
14333 {
14334 EMSG(_(e_write));
14335 break;
14336 }
14337 }
14338 fclose(fd);
14339 }
14340
14341 rettv->vval.v_number = ret;
14342}
14343
14344/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000014345 * Translate a String variable into a position.
14346 */
14347 static pos_T *
14348var2fpos(varp, lnum)
Bram Moolenaar33570922005-01-25 22:26:29 +000014349 typval_T *varp;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014350 int lnum; /* TRUE when $ is last line */
14351{
14352 char_u *name;
14353 static pos_T pos;
14354 pos_T *pp;
14355
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000014356 name = get_tv_string_chk(varp);
14357 if (name == NULL)
14358 return NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014359 if (name[0] == '.') /* cursor */
14360 return &curwin->w_cursor;
14361 if (name[0] == '\'') /* mark */
14362 {
14363 pp = getmark(name[1], FALSE);
14364 if (pp == NULL || pp == (pos_T *)-1 || pp->lnum <= 0)
14365 return NULL;
14366 return pp;
14367 }
14368 if (name[0] == '$') /* last column or line */
14369 {
14370 if (lnum)
14371 {
14372 pos.lnum = curbuf->b_ml.ml_line_count;
14373 pos.col = 0;
14374 }
14375 else
14376 {
14377 pos.lnum = curwin->w_cursor.lnum;
14378 pos.col = (colnr_T)STRLEN(ml_get_curline());
14379 }
14380 return &pos;
14381 }
14382 return NULL;
14383}
14384
14385/*
14386 * Get the length of an environment variable name.
14387 * Advance "arg" to the first character after the name.
14388 * Return 0 for error.
14389 */
14390 static int
14391get_env_len(arg)
14392 char_u **arg;
14393{
14394 char_u *p;
14395 int len;
14396
14397 for (p = *arg; vim_isIDc(*p); ++p)
14398 ;
14399 if (p == *arg) /* no name found */
14400 return 0;
14401
14402 len = (int)(p - *arg);
14403 *arg = p;
14404 return len;
14405}
14406
14407/*
14408 * Get the length of the name of a function or internal variable.
14409 * "arg" is advanced to the first non-white character after the name.
14410 * Return 0 if something is wrong.
14411 */
14412 static int
14413get_id_len(arg)
14414 char_u **arg;
14415{
14416 char_u *p;
14417 int len;
14418
14419 /* Find the end of the name. */
14420 for (p = *arg; eval_isnamec(*p); ++p)
14421 ;
14422 if (p == *arg) /* no name found */
14423 return 0;
14424
14425 len = (int)(p - *arg);
14426 *arg = skipwhite(p);
14427
14428 return len;
14429}
14430
14431/*
Bram Moolenaara7043832005-01-21 11:56:39 +000014432 * Get the length of the name of a variable or function.
14433 * Only the name is recognized, does not handle ".key" or "[idx]".
Bram Moolenaar071d4272004-06-13 20:20:40 +000014434 * "arg" is advanced to the first non-white character after the name.
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000014435 * Return -1 if curly braces expansion failed.
14436 * Return 0 if something else is wrong.
Bram Moolenaar071d4272004-06-13 20:20:40 +000014437 * If the name contains 'magic' {}'s, expand them and return the
14438 * expanded name in an allocated string via 'alias' - caller must free.
14439 */
14440 static int
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000014441get_name_len(arg, alias, evaluate, verbose)
Bram Moolenaar071d4272004-06-13 20:20:40 +000014442 char_u **arg;
14443 char_u **alias;
14444 int evaluate;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000014445 int verbose;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014446{
14447 int len;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014448 char_u *p;
14449 char_u *expr_start;
14450 char_u *expr_end;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014451
14452 *alias = NULL; /* default to no alias */
14453
14454 if ((*arg)[0] == K_SPECIAL && (*arg)[1] == KS_EXTRA
14455 && (*arg)[2] == (int)KE_SNR)
14456 {
14457 /* hard coded <SNR>, already translated */
14458 *arg += 3;
14459 return get_id_len(arg) + 3;
14460 }
14461 len = eval_fname_script(*arg);
14462 if (len > 0)
14463 {
14464 /* literal "<SID>", "s:" or "<SNR>" */
14465 *arg += len;
14466 }
14467
Bram Moolenaar071d4272004-06-13 20:20:40 +000014468 /*
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014469 * Find the end of the name; check for {} construction.
Bram Moolenaar071d4272004-06-13 20:20:40 +000014470 */
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +000014471 p = find_name_end(*arg, &expr_start, &expr_end,
14472 len > 0 ? 0 : FNE_CHECK_START);
Bram Moolenaar071d4272004-06-13 20:20:40 +000014473 if (expr_start != NULL)
14474 {
14475 char_u *temp_string;
14476
14477 if (!evaluate)
14478 {
14479 len += (int)(p - *arg);
14480 *arg = skipwhite(p);
14481 return len;
14482 }
14483
14484 /*
14485 * Include any <SID> etc in the expanded string:
14486 * Thus the -len here.
14487 */
14488 temp_string = make_expanded_name(*arg - len, expr_start, expr_end, p);
14489 if (temp_string == NULL)
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000014490 return -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014491 *alias = temp_string;
14492 *arg = skipwhite(p);
14493 return (int)STRLEN(temp_string);
14494 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000014495
14496 len += get_id_len(arg);
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000014497 if (len == 0 && verbose)
Bram Moolenaar071d4272004-06-13 20:20:40 +000014498 EMSG2(_(e_invexpr2), *arg);
14499
14500 return len;
14501}
14502
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014503/*
14504 * Find the end of a variable or function name, taking care of magic braces.
14505 * If "expr_start" is not NULL then "expr_start" and "expr_end" are set to the
14506 * start and end of the first magic braces item.
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +000014507 * "flags" can have FNE_INCL_BR and FNE_CHECK_START.
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014508 * Return a pointer to just after the name. Equal to "arg" if there is no
14509 * valid name.
14510 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000014511 static char_u *
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +000014512find_name_end(arg, expr_start, expr_end, flags)
Bram Moolenaar071d4272004-06-13 20:20:40 +000014513 char_u *arg;
14514 char_u **expr_start;
14515 char_u **expr_end;
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +000014516 int flags;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014517{
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014518 int mb_nest = 0;
14519 int br_nest = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014520 char_u *p;
14521
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014522 if (expr_start != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000014523 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014524 *expr_start = NULL;
14525 *expr_end = NULL;
14526 }
14527
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +000014528 /* Quick check for valid starting character. */
14529 if ((flags & FNE_CHECK_START) && !eval_isnamec1(*arg) && *arg != '{')
14530 return arg;
14531
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014532 for (p = arg; *p != NUL
14533 && (eval_isnamec(*p)
Bram Moolenaare9a41262005-01-15 22:18:47 +000014534 || *p == '{'
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +000014535 || ((flags & FNE_INCL_BR) && (*p == '[' || *p == '.'))
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014536 || mb_nest != 0
14537 || br_nest != 0); ++p)
14538 {
14539 if (mb_nest == 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +000014540 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014541 if (*p == '[')
14542 ++br_nest;
14543 else if (*p == ']')
14544 --br_nest;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014545 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014546 if (br_nest == 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +000014547 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014548 if (*p == '{')
14549 {
14550 mb_nest++;
14551 if (expr_start != NULL && *expr_start == NULL)
14552 *expr_start = p;
14553 }
14554 else if (*p == '}')
14555 {
14556 mb_nest--;
14557 if (expr_start != NULL && mb_nest == 0 && *expr_end == NULL)
14558 *expr_end = p;
14559 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000014560 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000014561 }
14562
14563 return p;
14564}
14565
14566/*
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000014567 * Expands out the 'magic' {}'s in a variable/function name.
14568 * Note that this can call itself recursively, to deal with
14569 * constructs like foo{bar}{baz}{bam}
14570 * The four pointer arguments point to "foo{expre}ss{ion}bar"
14571 * "in_start" ^
14572 * "expr_start" ^
14573 * "expr_end" ^
14574 * "in_end" ^
14575 *
14576 * Returns a new allocated string, which the caller must free.
14577 * Returns NULL for failure.
14578 */
14579 static char_u *
14580make_expanded_name(in_start, expr_start, expr_end, in_end)
14581 char_u *in_start;
14582 char_u *expr_start;
14583 char_u *expr_end;
14584 char_u *in_end;
14585{
14586 char_u c1;
14587 char_u *retval = NULL;
14588 char_u *temp_result;
14589 char_u *nextcmd = NULL;
14590
14591 if (expr_end == NULL || in_end == NULL)
14592 return NULL;
14593 *expr_start = NUL;
14594 *expr_end = NUL;
14595 c1 = *in_end;
14596 *in_end = NUL;
14597
14598 temp_result = eval_to_string(expr_start + 1, &nextcmd);
14599 if (temp_result != NULL && nextcmd == NULL)
14600 {
14601 retval = alloc((unsigned)(STRLEN(temp_result) + (expr_start - in_start)
14602 + (in_end - expr_end) + 1));
14603 if (retval != NULL)
14604 {
14605 STRCPY(retval, in_start);
14606 STRCAT(retval, temp_result);
14607 STRCAT(retval, expr_end + 1);
14608 }
14609 }
14610 vim_free(temp_result);
14611
14612 *in_end = c1; /* put char back for error messages */
14613 *expr_start = '{';
14614 *expr_end = '}';
14615
14616 if (retval != NULL)
14617 {
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +000014618 temp_result = find_name_end(retval, &expr_start, &expr_end, 0);
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000014619 if (expr_start != NULL)
14620 {
14621 /* Further expansion! */
14622 temp_result = make_expanded_name(retval, expr_start,
14623 expr_end, temp_result);
14624 vim_free(retval);
14625 retval = temp_result;
14626 }
14627 }
14628
14629 return retval;
14630}
14631
14632/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000014633 * Return TRUE if character "c" can be used in a variable or function name.
Bram Moolenaare9a41262005-01-15 22:18:47 +000014634 * Does not include '{' or '}' for magic braces.
Bram Moolenaar071d4272004-06-13 20:20:40 +000014635 */
14636 static int
14637eval_isnamec(c)
14638 int c;
14639{
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +000014640 return (ASCII_ISALNUM(c) || c == '_' || c == ':' || c == AUTOLOAD_CHAR);
14641}
14642
14643/*
14644 * Return TRUE if character "c" can be used as the first character in a
14645 * variable or function name (excluding '{' and '}').
14646 */
14647 static int
14648eval_isnamec1(c)
14649 int c;
14650{
14651 return (ASCII_ISALPHA(c) || c == '_');
Bram Moolenaar071d4272004-06-13 20:20:40 +000014652}
14653
14654/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000014655 * Set number v: variable to "val".
14656 */
14657 void
14658set_vim_var_nr(idx, val)
14659 int idx;
14660 long val;
14661{
Bram Moolenaare9a41262005-01-15 22:18:47 +000014662 vimvars[idx].vv_nr = val;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014663}
14664
14665/*
Bram Moolenaar19a09a12005-03-04 23:39:37 +000014666 * Get number v: variable value.
Bram Moolenaar071d4272004-06-13 20:20:40 +000014667 */
14668 long
14669get_vim_var_nr(idx)
14670 int idx;
14671{
Bram Moolenaare9a41262005-01-15 22:18:47 +000014672 return vimvars[idx].vv_nr;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014673}
14674
Bram Moolenaar19a09a12005-03-04 23:39:37 +000014675#if defined(FEAT_AUTOCMD) || defined(PROTO)
14676/*
14677 * Get string v: variable value. Uses a static buffer, can only be used once.
14678 */
14679 char_u *
14680get_vim_var_str(idx)
14681 int idx;
14682{
14683 return get_tv_string(&vimvars[idx].vv_tv);
14684}
14685#endif
14686
Bram Moolenaar071d4272004-06-13 20:20:40 +000014687/*
14688 * Set v:count, v:count1 and v:prevcount.
14689 */
14690 void
14691set_vcount(count, count1)
14692 long count;
14693 long count1;
14694{
Bram Moolenaare9a41262005-01-15 22:18:47 +000014695 vimvars[VV_PREVCOUNT].vv_nr = vimvars[VV_COUNT].vv_nr;
14696 vimvars[VV_COUNT].vv_nr = count;
14697 vimvars[VV_COUNT1].vv_nr = count1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014698}
14699
14700/*
14701 * Set string v: variable to a copy of "val".
14702 */
14703 void
14704set_vim_var_string(idx, val, len)
14705 int idx;
14706 char_u *val;
14707 int len; /* length of "val" to use or -1 (whole string) */
14708{
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000014709 /* Need to do this (at least) once, since we can't initialize a union.
14710 * Will always be invoked when "v:progname" is set. */
14711 vimvars[VV_VERSION].vv_nr = VIM_VERSION_100;
14712
Bram Moolenaare9a41262005-01-15 22:18:47 +000014713 vim_free(vimvars[idx].vv_str);
Bram Moolenaar071d4272004-06-13 20:20:40 +000014714 if (val == NULL)
Bram Moolenaare9a41262005-01-15 22:18:47 +000014715 vimvars[idx].vv_str = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014716 else if (len == -1)
Bram Moolenaare9a41262005-01-15 22:18:47 +000014717 vimvars[idx].vv_str = vim_strsave(val);
Bram Moolenaar071d4272004-06-13 20:20:40 +000014718 else
Bram Moolenaare9a41262005-01-15 22:18:47 +000014719 vimvars[idx].vv_str = vim_strnsave(val, len);
Bram Moolenaar071d4272004-06-13 20:20:40 +000014720}
14721
14722/*
14723 * Set v:register if needed.
14724 */
14725 void
14726set_reg_var(c)
14727 int c;
14728{
14729 char_u regname;
14730
14731 if (c == 0 || c == ' ')
14732 regname = '"';
14733 else
14734 regname = c;
14735 /* Avoid free/alloc when the value is already right. */
Bram Moolenaare9a41262005-01-15 22:18:47 +000014736 if (vimvars[VV_REG].vv_str == NULL || vimvars[VV_REG].vv_str[0] != c)
Bram Moolenaar071d4272004-06-13 20:20:40 +000014737 set_vim_var_string(VV_REG, &regname, 1);
14738}
14739
14740/*
14741 * Get or set v:exception. If "oldval" == NULL, return the current value.
14742 * Otherwise, restore the value to "oldval" and return NULL.
14743 * Must always be called in pairs to save and restore v:exception! Does not
14744 * take care of memory allocations.
14745 */
14746 char_u *
14747v_exception(oldval)
14748 char_u *oldval;
14749{
14750 if (oldval == NULL)
Bram Moolenaare9a41262005-01-15 22:18:47 +000014751 return vimvars[VV_EXCEPTION].vv_str;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014752
Bram Moolenaare9a41262005-01-15 22:18:47 +000014753 vimvars[VV_EXCEPTION].vv_str = oldval;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014754 return NULL;
14755}
14756
14757/*
14758 * Get or set v:throwpoint. If "oldval" == NULL, return the current value.
14759 * Otherwise, restore the value to "oldval" and return NULL.
14760 * Must always be called in pairs to save and restore v:throwpoint! Does not
14761 * take care of memory allocations.
14762 */
14763 char_u *
14764v_throwpoint(oldval)
14765 char_u *oldval;
14766{
14767 if (oldval == NULL)
Bram Moolenaare9a41262005-01-15 22:18:47 +000014768 return vimvars[VV_THROWPOINT].vv_str;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014769
Bram Moolenaare9a41262005-01-15 22:18:47 +000014770 vimvars[VV_THROWPOINT].vv_str = oldval;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014771 return NULL;
14772}
14773
14774#if defined(FEAT_AUTOCMD) || defined(PROTO)
14775/*
14776 * Set v:cmdarg.
14777 * If "eap" != NULL, use "eap" to generate the value and return the old value.
14778 * If "oldarg" != NULL, restore the value to "oldarg" and return NULL.
14779 * Must always be called in pairs!
14780 */
14781 char_u *
14782set_cmdarg(eap, oldarg)
14783 exarg_T *eap;
14784 char_u *oldarg;
14785{
14786 char_u *oldval;
14787 char_u *newval;
14788 unsigned len;
14789
Bram Moolenaare9a41262005-01-15 22:18:47 +000014790 oldval = vimvars[VV_CMDARG].vv_str;
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +000014791 if (eap == NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000014792 {
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +000014793 vim_free(oldval);
Bram Moolenaare9a41262005-01-15 22:18:47 +000014794 vimvars[VV_CMDARG].vv_str = oldarg;
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +000014795 return NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014796 }
14797
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +000014798 if (eap->force_bin == FORCE_BIN)
14799 len = 6;
14800 else if (eap->force_bin == FORCE_NOBIN)
14801 len = 8;
14802 else
14803 len = 0;
14804 if (eap->force_ff != 0)
14805 len += (unsigned)STRLEN(eap->cmd + eap->force_ff) + 6;
14806# ifdef FEAT_MBYTE
14807 if (eap->force_enc != 0)
14808 len += (unsigned)STRLEN(eap->cmd + eap->force_enc) + 7;
14809# endif
14810
14811 newval = alloc(len + 1);
14812 if (newval == NULL)
14813 return NULL;
14814
14815 if (eap->force_bin == FORCE_BIN)
14816 sprintf((char *)newval, " ++bin");
14817 else if (eap->force_bin == FORCE_NOBIN)
14818 sprintf((char *)newval, " ++nobin");
14819 else
14820 *newval = NUL;
14821 if (eap->force_ff != 0)
14822 sprintf((char *)newval + STRLEN(newval), " ++ff=%s",
14823 eap->cmd + eap->force_ff);
14824# ifdef FEAT_MBYTE
14825 if (eap->force_enc != 0)
14826 sprintf((char *)newval + STRLEN(newval), " ++enc=%s",
14827 eap->cmd + eap->force_enc);
14828# endif
Bram Moolenaare9a41262005-01-15 22:18:47 +000014829 vimvars[VV_CMDARG].vv_str = newval;
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +000014830 return oldval;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014831}
14832#endif
14833
14834/*
14835 * Get the value of internal variable "name".
14836 * Return OK or FAIL.
14837 */
14838 static int
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000014839get_var_tv(name, len, rettv, verbose)
Bram Moolenaar071d4272004-06-13 20:20:40 +000014840 char_u *name;
14841 int len; /* length of "name" */
Bram Moolenaar33570922005-01-25 22:26:29 +000014842 typval_T *rettv; /* NULL when only checking existence */
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000014843 int verbose; /* may give error message */
Bram Moolenaar071d4272004-06-13 20:20:40 +000014844{
14845 int ret = OK;
Bram Moolenaar33570922005-01-25 22:26:29 +000014846 typval_T *tv = NULL;
14847 typval_T atv;
14848 dictitem_T *v;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014849 int cc;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014850
14851 /* truncate the name, so that we can use strcmp() */
14852 cc = name[len];
14853 name[len] = NUL;
14854
14855 /*
14856 * Check for "b:changedtick".
14857 */
14858 if (STRCMP(name, "b:changedtick") == 0)
14859 {
Bram Moolenaare9a41262005-01-15 22:18:47 +000014860 atv.v_type = VAR_NUMBER;
14861 atv.vval.v_number = curbuf->b_changedtick;
14862 tv = &atv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014863 }
14864
14865 /*
Bram Moolenaar071d4272004-06-13 20:20:40 +000014866 * Check for user-defined variables.
14867 */
14868 else
14869 {
Bram Moolenaara7043832005-01-21 11:56:39 +000014870 v = find_var(name, NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +000014871 if (v != NULL)
Bram Moolenaar33570922005-01-25 22:26:29 +000014872 tv = &v->di_tv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014873 }
14874
Bram Moolenaare9a41262005-01-15 22:18:47 +000014875 if (tv == NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000014876 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000014877 if (rettv != NULL && verbose)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014878 EMSG2(_(e_undefvar), name);
Bram Moolenaar071d4272004-06-13 20:20:40 +000014879 ret = FAIL;
14880 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014881 else if (rettv != NULL)
Bram Moolenaare9a41262005-01-15 22:18:47 +000014882 copy_tv(tv, rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000014883
14884 name[len] = cc;
14885
14886 return ret;
14887}
14888
14889/*
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000014890 * Handle expr[expr], expr[expr:expr] subscript and .name lookup.
14891 * Also handle function call with Funcref variable: func(expr)
14892 * Can all be combined: dict.func(expr)[idx]['func'](expr)
14893 */
14894 static int
14895handle_subscript(arg, rettv, evaluate, verbose)
14896 char_u **arg;
14897 typval_T *rettv;
14898 int evaluate; /* do more than finding the end */
14899 int verbose; /* give error messages */
14900{
14901 int ret = OK;
14902 dict_T *selfdict = NULL;
14903 char_u *s;
14904 int len;
14905
14906 while (ret == OK
14907 && (**arg == '['
14908 || (**arg == '.' && rettv->v_type == VAR_DICT)
14909 || (**arg == '(' && rettv->v_type == VAR_FUNC))
14910 && !vim_iswhite(*(*arg - 1)))
14911 {
14912 if (**arg == '(')
14913 {
14914 s = rettv->vval.v_string;
14915
14916 /* Invoke the function. Recursive! */
14917 ret = get_func_tv(s, STRLEN(s), rettv, arg,
14918 curwin->w_cursor.lnum, curwin->w_cursor.lnum,
14919 &len, evaluate, selfdict);
14920
14921 /* Stop the expression evaluation when immediately aborting on
14922 * error, or when an interrupt occurred or an exception was thrown
14923 * but not caught. */
14924 if (aborting())
14925 {
14926 if (ret == OK)
14927 clear_tv(rettv);
14928 ret = FAIL;
14929 }
14930 dict_unref(selfdict);
14931 selfdict = NULL;
14932 }
14933 else /* **arg == '[' || **arg == '.' */
14934 {
14935 dict_unref(selfdict);
14936 if (rettv->v_type == VAR_DICT)
14937 {
14938 selfdict = rettv->vval.v_dict;
14939 if (selfdict != NULL)
14940 ++selfdict->dv_refcount;
14941 }
14942 else
14943 selfdict = NULL;
14944 if (eval_index(arg, rettv, evaluate, verbose) == FAIL)
14945 {
14946 clear_tv(rettv);
14947 ret = FAIL;
14948 }
14949 }
14950 }
14951 dict_unref(selfdict);
14952 return ret;
14953}
14954
14955/*
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014956 * Allocate memory for a variable type-value, and make it emtpy (0 or NULL
14957 * value).
14958 */
Bram Moolenaar33570922005-01-25 22:26:29 +000014959 static typval_T *
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014960alloc_tv()
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014961{
Bram Moolenaar33570922005-01-25 22:26:29 +000014962 return (typval_T *)alloc_clear((unsigned)sizeof(typval_T));
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014963}
14964
14965/*
14966 * Allocate memory for a variable type-value, and assign a string to it.
Bram Moolenaar071d4272004-06-13 20:20:40 +000014967 * The string "s" must have been allocated, it is consumed.
14968 * Return NULL for out of memory, the variable otherwise.
14969 */
Bram Moolenaar33570922005-01-25 22:26:29 +000014970 static typval_T *
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014971alloc_string_tv(s)
Bram Moolenaar071d4272004-06-13 20:20:40 +000014972 char_u *s;
14973{
Bram Moolenaar33570922005-01-25 22:26:29 +000014974 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014975
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014976 rettv = alloc_tv();
14977 if (rettv != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000014978 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014979 rettv->v_type = VAR_STRING;
14980 rettv->vval.v_string = s;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014981 }
14982 else
14983 vim_free(s);
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014984 return rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014985}
14986
14987/*
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014988 * Free the memory for a variable type-value.
Bram Moolenaar071d4272004-06-13 20:20:40 +000014989 */
14990 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014991free_tv(varp)
Bram Moolenaar33570922005-01-25 22:26:29 +000014992 typval_T *varp;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014993{
14994 if (varp != NULL)
14995 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014996 switch (varp->v_type)
14997 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014998 case VAR_FUNC:
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000014999 func_unref(varp->vval.v_string);
15000 /*FALLTHROUGH*/
15001 case VAR_STRING:
Bram Moolenaar49cd9572005-01-03 21:06:01 +000015002 vim_free(varp->vval.v_string);
15003 break;
15004 case VAR_LIST:
15005 list_unref(varp->vval.v_list);
15006 break;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000015007 case VAR_DICT:
15008 dict_unref(varp->vval.v_dict);
15009 break;
Bram Moolenaar758711c2005-02-02 23:11:38 +000015010 case VAR_NUMBER:
15011 case VAR_UNKNOWN:
15012 break;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000015013 default:
Bram Moolenaar758711c2005-02-02 23:11:38 +000015014 EMSG2(_(e_intern2), "free_tv()");
Bram Moolenaar49cd9572005-01-03 21:06:01 +000015015 break;
15016 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000015017 vim_free(varp);
15018 }
15019}
15020
15021/*
15022 * Free the memory for a variable value and set the value to NULL or 0.
15023 */
15024 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015025clear_tv(varp)
Bram Moolenaar33570922005-01-25 22:26:29 +000015026 typval_T *varp;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015027{
15028 if (varp != NULL)
15029 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +000015030 switch (varp->v_type)
Bram Moolenaar071d4272004-06-13 20:20:40 +000015031 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +000015032 case VAR_FUNC:
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000015033 func_unref(varp->vval.v_string);
15034 /*FALLTHROUGH*/
15035 case VAR_STRING:
Bram Moolenaar49cd9572005-01-03 21:06:01 +000015036 vim_free(varp->vval.v_string);
15037 varp->vval.v_string = NULL;
15038 break;
15039 case VAR_LIST:
15040 list_unref(varp->vval.v_list);
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000015041 varp->vval.v_list = NULL;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000015042 break;
Bram Moolenaar8c711452005-01-14 21:53:12 +000015043 case VAR_DICT:
15044 dict_unref(varp->vval.v_dict);
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000015045 varp->vval.v_dict = NULL;
Bram Moolenaar8c711452005-01-14 21:53:12 +000015046 break;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015047 case VAR_NUMBER:
Bram Moolenaar49cd9572005-01-03 21:06:01 +000015048 varp->vval.v_number = 0;
15049 break;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015050 case VAR_UNKNOWN:
15051 break;
15052 default:
15053 EMSG2(_(e_intern2), "clear_tv()");
Bram Moolenaar071d4272004-06-13 20:20:40 +000015054 }
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000015055 varp->v_lock = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015056 }
15057}
15058
15059/*
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015060 * Set the value of a variable to NULL without freeing items.
15061 */
15062 static void
15063init_tv(varp)
Bram Moolenaar33570922005-01-25 22:26:29 +000015064 typval_T *varp;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015065{
15066 if (varp != NULL)
Bram Moolenaar33570922005-01-25 22:26:29 +000015067 vim_memset(varp, 0, sizeof(typval_T));
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015068}
15069
15070/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000015071 * Get the number value of a variable.
15072 * If it is a String variable, uses vim_str2nr().
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000015073 * For incompatible types, return 0.
15074 * get_tv_number_chk() is similar to get_tv_number(), but informs the
15075 * caller of incompatible types: it sets *denote to TRUE if "denote"
15076 * is not NULL or returns -1 otherwise.
Bram Moolenaar071d4272004-06-13 20:20:40 +000015077 */
15078 static long
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015079get_tv_number(varp)
Bram Moolenaar33570922005-01-25 22:26:29 +000015080 typval_T *varp;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015081{
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000015082 int error = FALSE;
15083
15084 return get_tv_number_chk(varp, &error); /* return 0L on error */
15085}
15086
15087 static long
15088get_tv_number_chk(varp, denote)
15089 typval_T *varp;
15090 int *denote;
15091{
Bram Moolenaar49cd9572005-01-03 21:06:01 +000015092 long n = 0L;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015093
Bram Moolenaar49cd9572005-01-03 21:06:01 +000015094 switch (varp->v_type)
Bram Moolenaar071d4272004-06-13 20:20:40 +000015095 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +000015096 case VAR_NUMBER:
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000015097 return (long)(varp->vval.v_number);
Bram Moolenaar49cd9572005-01-03 21:06:01 +000015098 case VAR_FUNC:
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000015099 EMSG(_("E703: Using a Funcref as a number"));
Bram Moolenaar49cd9572005-01-03 21:06:01 +000015100 break;
15101 case VAR_STRING:
15102 if (varp->vval.v_string != NULL)
15103 vim_str2nr(varp->vval.v_string, NULL, NULL,
15104 TRUE, TRUE, &n, NULL);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000015105 return n;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000015106 case VAR_LIST:
Bram Moolenaar758711c2005-02-02 23:11:38 +000015107 EMSG(_("E745: Using a List as a number"));
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000015108 break;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000015109 case VAR_DICT:
15110 EMSG(_("E728: Using a Dictionary as a number"));
15111 break;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000015112 default:
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000015113 EMSG2(_(e_intern2), "get_tv_number()");
Bram Moolenaar49cd9572005-01-03 21:06:01 +000015114 break;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015115 }
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000015116 if (denote == NULL) /* useful for values that must be unsigned */
15117 n = -1;
15118 else
15119 *denote = TRUE;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000015120 return n;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015121}
15122
15123/*
15124 * Get the lnum from the first argument. Also accepts ".", "$", etc.
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000015125 * Returns -1 on error.
Bram Moolenaar071d4272004-06-13 20:20:40 +000015126 */
15127 static linenr_T
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015128get_tv_lnum(argvars)
Bram Moolenaar33570922005-01-25 22:26:29 +000015129 typval_T *argvars;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015130{
Bram Moolenaar33570922005-01-25 22:26:29 +000015131 typval_T rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015132 linenr_T lnum;
15133
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000015134 lnum = get_tv_number_chk(&argvars[0], NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +000015135 if (lnum == 0) /* no valid number, try using line() */
15136 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015137 rettv.v_type = VAR_NUMBER;
15138 f_line(argvars, &rettv);
15139 lnum = rettv.vval.v_number;
15140 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000015141 }
15142 return lnum;
15143}
15144
15145/*
15146 * Get the string value of a variable.
15147 * If it is a Number variable, the number is converted into a string.
Bram Moolenaara7043832005-01-21 11:56:39 +000015148 * get_tv_string() uses a single, static buffer. YOU CAN ONLY USE IT ONCE!
15149 * get_tv_string_buf() uses a given buffer.
Bram Moolenaar071d4272004-06-13 20:20:40 +000015150 * If the String variable has never been set, return an empty string.
15151 * Never returns NULL;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000015152 * get_tv_string_chk() and get_tv_string_buf_chk() are similar, but return
15153 * NULL on error.
Bram Moolenaar071d4272004-06-13 20:20:40 +000015154 */
15155 static char_u *
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015156get_tv_string(varp)
Bram Moolenaar33570922005-01-25 22:26:29 +000015157 typval_T *varp;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015158{
15159 static char_u mybuf[NUMBUFLEN];
15160
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015161 return get_tv_string_buf(varp, mybuf);
Bram Moolenaar071d4272004-06-13 20:20:40 +000015162}
15163
15164 static char_u *
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015165get_tv_string_buf(varp, buf)
Bram Moolenaar33570922005-01-25 22:26:29 +000015166 typval_T *varp;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000015167 char_u *buf;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015168{
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000015169 char_u *res = get_tv_string_buf_chk(varp, buf);
15170
15171 return res != NULL ? res : (char_u *)"";
15172}
15173
15174 static char_u *
15175get_tv_string_chk(varp)
15176 typval_T *varp;
15177{
15178 static char_u mybuf[NUMBUFLEN];
15179
15180 return get_tv_string_buf_chk(varp, mybuf);
15181}
15182
15183 static char_u *
15184get_tv_string_buf_chk(varp, buf)
15185 typval_T *varp;
15186 char_u *buf;
15187{
Bram Moolenaar49cd9572005-01-03 21:06:01 +000015188 switch (varp->v_type)
Bram Moolenaar071d4272004-06-13 20:20:40 +000015189 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +000015190 case VAR_NUMBER:
15191 sprintf((char *)buf, "%ld", (long)varp->vval.v_number);
15192 return buf;
15193 case VAR_FUNC:
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000015194 EMSG(_("E729: using Funcref as a String"));
Bram Moolenaar49cd9572005-01-03 21:06:01 +000015195 break;
15196 case VAR_LIST:
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000015197 EMSG(_("E730: using List as a String"));
Bram Moolenaar8c711452005-01-14 21:53:12 +000015198 break;
15199 case VAR_DICT:
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000015200 EMSG(_("E731: using Dictionary as a String"));
Bram Moolenaar49cd9572005-01-03 21:06:01 +000015201 break;
15202 case VAR_STRING:
15203 if (varp->vval.v_string != NULL)
15204 return varp->vval.v_string;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000015205 return (char_u *)"";
Bram Moolenaar49cd9572005-01-03 21:06:01 +000015206 default:
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015207 EMSG2(_(e_intern2), "get_tv_string_buf()");
Bram Moolenaar49cd9572005-01-03 21:06:01 +000015208 break;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015209 }
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000015210 return NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015211}
15212
15213/*
15214 * Find variable "name" in the list of variables.
15215 * Return a pointer to it if found, NULL if not found.
Bram Moolenaar49cd9572005-01-03 21:06:01 +000015216 * Careful: "a:0" variables don't have a name.
Bram Moolenaara7043832005-01-21 11:56:39 +000015217 * When "htp" is not NULL we are writing to the variable, set "htp" to the
Bram Moolenaar33570922005-01-25 22:26:29 +000015218 * hashtab_T used.
Bram Moolenaar071d4272004-06-13 20:20:40 +000015219 */
Bram Moolenaar33570922005-01-25 22:26:29 +000015220 static dictitem_T *
Bram Moolenaara7043832005-01-21 11:56:39 +000015221find_var(name, htp)
Bram Moolenaar071d4272004-06-13 20:20:40 +000015222 char_u *name;
Bram Moolenaar33570922005-01-25 22:26:29 +000015223 hashtab_T **htp;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015224{
Bram Moolenaar071d4272004-06-13 20:20:40 +000015225 char_u *varname;
Bram Moolenaar33570922005-01-25 22:26:29 +000015226 hashtab_T *ht;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015227
Bram Moolenaara7043832005-01-21 11:56:39 +000015228 ht = find_var_ht(name, &varname);
15229 if (htp != NULL)
15230 *htp = ht;
15231 if (ht == NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000015232 return NULL;
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000015233 return find_var_in_ht(ht, varname, htp != NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +000015234}
15235
15236/*
Bram Moolenaar33570922005-01-25 22:26:29 +000015237 * Find variable "varname" in hashtab "ht".
Bram Moolenaara7043832005-01-21 11:56:39 +000015238 * Returns NULL if not found.
Bram Moolenaar071d4272004-06-13 20:20:40 +000015239 */
Bram Moolenaar33570922005-01-25 22:26:29 +000015240 static dictitem_T *
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000015241find_var_in_ht(ht, varname, writing)
Bram Moolenaar33570922005-01-25 22:26:29 +000015242 hashtab_T *ht;
Bram Moolenaara7043832005-01-21 11:56:39 +000015243 char_u *varname;
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000015244 int writing;
Bram Moolenaara7043832005-01-21 11:56:39 +000015245{
Bram Moolenaar33570922005-01-25 22:26:29 +000015246 hashitem_T *hi;
15247
15248 if (*varname == NUL)
15249 {
15250 /* Must be something like "s:", otherwise "ht" would be NULL. */
15251 switch (varname[-2])
15252 {
15253 case 's': return &SCRIPT_SV(current_SID).sv_var;
15254 case 'g': return &globvars_var;
15255 case 'v': return &vimvars_var;
15256 case 'b': return &curbuf->b_bufvar;
15257 case 'w': return &curwin->w_winvar;
15258 case 'l': return &current_funccal->l_vars_var;
15259 case 'a': return &current_funccal->l_avars_var;
15260 }
15261 return NULL;
15262 }
Bram Moolenaara7043832005-01-21 11:56:39 +000015263
15264 hi = hash_find(ht, varname);
15265 if (HASHITEM_EMPTY(hi))
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000015266 {
15267 /* For global variables we may try auto-loading the script. If it
15268 * worked find the variable again. */
15269 if (ht == &globvarht && !writing
15270 && script_autoload(varname) && !aborting())
15271 hi = hash_find(ht, varname);
15272 if (HASHITEM_EMPTY(hi))
15273 return NULL;
15274 }
Bram Moolenaar33570922005-01-25 22:26:29 +000015275 return HI2DI(hi);
Bram Moolenaara7043832005-01-21 11:56:39 +000015276}
15277
15278/*
Bram Moolenaar33570922005-01-25 22:26:29 +000015279 * Find the hashtab used for a variable name.
Bram Moolenaara7043832005-01-21 11:56:39 +000015280 * Set "varname" to the start of name without ':'.
15281 */
Bram Moolenaar33570922005-01-25 22:26:29 +000015282 static hashtab_T *
Bram Moolenaara7043832005-01-21 11:56:39 +000015283find_var_ht(name, varname)
Bram Moolenaar071d4272004-06-13 20:20:40 +000015284 char_u *name;
15285 char_u **varname;
15286{
Bram Moolenaar75c50c42005-06-04 22:06:24 +000015287 hashitem_T *hi;
15288
Bram Moolenaar071d4272004-06-13 20:20:40 +000015289 if (name[1] != ':')
15290 {
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +000015291 /* The name must not start with a colon or #. */
15292 if (name[0] == ':' || name[0] == AUTOLOAD_CHAR)
Bram Moolenaar071d4272004-06-13 20:20:40 +000015293 return NULL;
15294 *varname = name;
Bram Moolenaar532c7802005-01-27 14:44:31 +000015295
15296 /* "version" is "v:version" in all scopes */
Bram Moolenaar75c50c42005-06-04 22:06:24 +000015297 hi = hash_find(&compat_hashtab, name);
15298 if (!HASHITEM_EMPTY(hi))
Bram Moolenaar532c7802005-01-27 14:44:31 +000015299 return &compat_hashtab;
15300
Bram Moolenaar071d4272004-06-13 20:20:40 +000015301 if (current_funccal == NULL)
Bram Moolenaar33570922005-01-25 22:26:29 +000015302 return &globvarht; /* global variable */
15303 return &current_funccal->l_vars.dv_hashtab; /* l: variable */
Bram Moolenaar071d4272004-06-13 20:20:40 +000015304 }
15305 *varname = name + 2;
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000015306 if (*name == 'g') /* global variable */
15307 return &globvarht;
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +000015308 /* There must be no ':' or '#' in the rest of the name, unless g: is used
15309 */
15310 if (vim_strchr(name + 2, ':') != NULL
15311 || vim_strchr(name + 2, AUTOLOAD_CHAR) != NULL)
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000015312 return NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015313 if (*name == 'b') /* buffer variable */
Bram Moolenaar33570922005-01-25 22:26:29 +000015314 return &curbuf->b_vars.dv_hashtab;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015315 if (*name == 'w') /* window variable */
Bram Moolenaar33570922005-01-25 22:26:29 +000015316 return &curwin->w_vars.dv_hashtab;
Bram Moolenaar33570922005-01-25 22:26:29 +000015317 if (*name == 'v') /* v: variable */
15318 return &vimvarht;
15319 if (*name == 'a' && current_funccal != NULL) /* function argument */
15320 return &current_funccal->l_avars.dv_hashtab;
15321 if (*name == 'l' && current_funccal != NULL) /* local function variable */
15322 return &current_funccal->l_vars.dv_hashtab;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015323 if (*name == 's' /* script variable */
15324 && current_SID > 0 && current_SID <= ga_scripts.ga_len)
15325 return &SCRIPT_VARS(current_SID);
15326 return NULL;
15327}
15328
15329/*
15330 * Get the string value of a (global/local) variable.
15331 * Returns NULL when it doesn't exist.
15332 */
15333 char_u *
15334get_var_value(name)
15335 char_u *name;
15336{
Bram Moolenaar33570922005-01-25 22:26:29 +000015337 dictitem_T *v;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015338
Bram Moolenaara7043832005-01-21 11:56:39 +000015339 v = find_var(name, NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +000015340 if (v == NULL)
15341 return NULL;
Bram Moolenaar33570922005-01-25 22:26:29 +000015342 return get_tv_string(&v->di_tv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000015343}
15344
15345/*
Bram Moolenaar33570922005-01-25 22:26:29 +000015346 * Allocate a new hashtab for a sourced script. It will be used while
Bram Moolenaar071d4272004-06-13 20:20:40 +000015347 * sourcing this script and when executing functions defined in the script.
15348 */
15349 void
15350new_script_vars(id)
15351 scid_T id;
15352{
Bram Moolenaara7043832005-01-21 11:56:39 +000015353 int i;
Bram Moolenaar33570922005-01-25 22:26:29 +000015354 hashtab_T *ht;
15355 scriptvar_T *sv;
Bram Moolenaara7043832005-01-21 11:56:39 +000015356
Bram Moolenaar071d4272004-06-13 20:20:40 +000015357 if (ga_grow(&ga_scripts, (int)(id - ga_scripts.ga_len)) == OK)
15358 {
Bram Moolenaara7043832005-01-21 11:56:39 +000015359 /* Re-allocating ga_data means that an ht_array pointing to
15360 * ht_smallarray becomes invalid. We can recognize this: ht_mask is
Bram Moolenaar33570922005-01-25 22:26:29 +000015361 * at its init value. Also reset "v_dict", it's always the same. */
Bram Moolenaara7043832005-01-21 11:56:39 +000015362 for (i = 1; i <= ga_scripts.ga_len; ++i)
15363 {
15364 ht = &SCRIPT_VARS(i);
15365 if (ht->ht_mask == HT_INIT_SIZE - 1)
15366 ht->ht_array = ht->ht_smallarray;
Bram Moolenaar33570922005-01-25 22:26:29 +000015367 sv = &SCRIPT_SV(i);
15368 sv->sv_var.di_tv.vval.v_dict = &sv->sv_dict;
Bram Moolenaara7043832005-01-21 11:56:39 +000015369 }
15370
Bram Moolenaar071d4272004-06-13 20:20:40 +000015371 while (ga_scripts.ga_len < id)
15372 {
Bram Moolenaar33570922005-01-25 22:26:29 +000015373 sv = &SCRIPT_SV(ga_scripts.ga_len + 1);
15374 init_var_dict(&sv->sv_dict, &sv->sv_var);
Bram Moolenaar071d4272004-06-13 20:20:40 +000015375 ++ga_scripts.ga_len;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015376 }
15377 }
15378}
15379
15380/*
Bram Moolenaar33570922005-01-25 22:26:29 +000015381 * Initialize dictionary "dict" as a scope and set variable "dict_var" to
15382 * point to it.
Bram Moolenaar071d4272004-06-13 20:20:40 +000015383 */
15384 void
Bram Moolenaar33570922005-01-25 22:26:29 +000015385init_var_dict(dict, dict_var)
15386 dict_T *dict;
15387 dictitem_T *dict_var;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015388{
Bram Moolenaar33570922005-01-25 22:26:29 +000015389 hash_init(&dict->dv_hashtab);
15390 dict->dv_refcount = 99999;
15391 dict_var->di_tv.vval.v_dict = dict;
15392 dict_var->di_tv.v_type = VAR_DICT;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000015393 dict_var->di_tv.v_lock = VAR_FIXED;
Bram Moolenaar33570922005-01-25 22:26:29 +000015394 dict_var->di_flags = DI_FLAGS_RO | DI_FLAGS_FIX;
15395 dict_var->di_key[0] = NUL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015396}
15397
15398/*
15399 * Clean up a list of internal variables.
Bram Moolenaar33570922005-01-25 22:26:29 +000015400 * Frees all allocated variables and the value they contain.
15401 * Clears hashtab "ht", does not free it.
Bram Moolenaar071d4272004-06-13 20:20:40 +000015402 */
15403 void
Bram Moolenaara7043832005-01-21 11:56:39 +000015404vars_clear(ht)
Bram Moolenaar33570922005-01-25 22:26:29 +000015405 hashtab_T *ht;
15406{
15407 vars_clear_ext(ht, TRUE);
15408}
15409
15410/*
15411 * Like vars_clear(), but only free the value if "free_val" is TRUE.
15412 */
15413 static void
15414vars_clear_ext(ht, free_val)
15415 hashtab_T *ht;
15416 int free_val;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015417{
Bram Moolenaara7043832005-01-21 11:56:39 +000015418 int todo;
Bram Moolenaar33570922005-01-25 22:26:29 +000015419 hashitem_T *hi;
15420 dictitem_T *v;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015421
Bram Moolenaar33570922005-01-25 22:26:29 +000015422 hash_lock(ht);
Bram Moolenaara7043832005-01-21 11:56:39 +000015423 todo = ht->ht_used;
15424 for (hi = ht->ht_array; todo > 0; ++hi)
15425 {
15426 if (!HASHITEM_EMPTY(hi))
15427 {
15428 --todo;
15429
Bram Moolenaar33570922005-01-25 22:26:29 +000015430 /* Free the variable. Don't remove it from the hashtab,
Bram Moolenaara7043832005-01-21 11:56:39 +000015431 * ht_array might change then. hash_clear() takes care of it
15432 * later. */
Bram Moolenaar33570922005-01-25 22:26:29 +000015433 v = HI2DI(hi);
15434 if (free_val)
15435 clear_tv(&v->di_tv);
15436 if ((v->di_flags & DI_FLAGS_FIX) == 0)
15437 vim_free(v);
Bram Moolenaara7043832005-01-21 11:56:39 +000015438 }
15439 }
15440 hash_clear(ht);
Bram Moolenaar071d4272004-06-13 20:20:40 +000015441}
15442
Bram Moolenaara7043832005-01-21 11:56:39 +000015443/*
Bram Moolenaar33570922005-01-25 22:26:29 +000015444 * Delete a variable from hashtab "ht" at item "hi".
15445 * Clear the variable value and free the dictitem.
Bram Moolenaara7043832005-01-21 11:56:39 +000015446 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000015447 static void
Bram Moolenaara7043832005-01-21 11:56:39 +000015448delete_var(ht, hi)
Bram Moolenaar33570922005-01-25 22:26:29 +000015449 hashtab_T *ht;
15450 hashitem_T *hi;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015451{
Bram Moolenaar33570922005-01-25 22:26:29 +000015452 dictitem_T *di = HI2DI(hi);
Bram Moolenaara7043832005-01-21 11:56:39 +000015453
15454 hash_remove(ht, hi);
Bram Moolenaar33570922005-01-25 22:26:29 +000015455 clear_tv(&di->di_tv);
15456 vim_free(di);
Bram Moolenaar071d4272004-06-13 20:20:40 +000015457}
15458
15459/*
15460 * List the value of one internal variable.
15461 */
15462 static void
15463list_one_var(v, prefix)
Bram Moolenaar33570922005-01-25 22:26:29 +000015464 dictitem_T *v;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015465 char_u *prefix;
15466{
Bram Moolenaar49cd9572005-01-03 21:06:01 +000015467 char_u *tofree;
15468 char_u *s;
Bram Moolenaar8a283e52005-01-06 23:28:25 +000015469 char_u numbuf[NUMBUFLEN];
Bram Moolenaar49cd9572005-01-03 21:06:01 +000015470
Bram Moolenaar33570922005-01-25 22:26:29 +000015471 s = echo_string(&v->di_tv, &tofree, numbuf);
15472 list_one_var_a(prefix, v->di_key, v->di_tv.v_type,
Bram Moolenaar49cd9572005-01-03 21:06:01 +000015473 s == NULL ? (char_u *)"" : s);
15474 vim_free(tofree);
Bram Moolenaar071d4272004-06-13 20:20:40 +000015475}
15476
Bram Moolenaar071d4272004-06-13 20:20:40 +000015477 static void
15478list_one_var_a(prefix, name, type, string)
15479 char_u *prefix;
15480 char_u *name;
15481 int type;
15482 char_u *string;
15483{
15484 msg_attr(prefix, 0); /* don't use msg(), it overwrites "v:statusmsg" */
15485 if (name != NULL) /* "a:" vars don't have a name stored */
15486 msg_puts(name);
15487 msg_putchar(' ');
15488 msg_advance(22);
15489 if (type == VAR_NUMBER)
15490 msg_putchar('#');
Bram Moolenaar49cd9572005-01-03 21:06:01 +000015491 else if (type == VAR_FUNC)
15492 msg_putchar('*');
15493 else if (type == VAR_LIST)
15494 {
15495 msg_putchar('[');
15496 if (*string == '[')
15497 ++string;
15498 }
Bram Moolenaar8c711452005-01-14 21:53:12 +000015499 else if (type == VAR_DICT)
15500 {
15501 msg_putchar('{');
15502 if (*string == '{')
15503 ++string;
15504 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000015505 else
15506 msg_putchar(' ');
Bram Moolenaar49cd9572005-01-03 21:06:01 +000015507
Bram Moolenaar071d4272004-06-13 20:20:40 +000015508 msg_outtrans(string);
Bram Moolenaar49cd9572005-01-03 21:06:01 +000015509
15510 if (type == VAR_FUNC)
15511 msg_puts((char_u *)"()");
Bram Moolenaar071d4272004-06-13 20:20:40 +000015512}
15513
15514/*
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015515 * Set variable "name" to value in "tv".
Bram Moolenaar071d4272004-06-13 20:20:40 +000015516 * If the variable already exists, the value is updated.
15517 * Otherwise the variable is created.
15518 */
15519 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015520set_var(name, tv, copy)
Bram Moolenaar071d4272004-06-13 20:20:40 +000015521 char_u *name;
Bram Moolenaar33570922005-01-25 22:26:29 +000015522 typval_T *tv;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015523 int copy; /* make copy of value in "tv" */
Bram Moolenaar071d4272004-06-13 20:20:40 +000015524{
Bram Moolenaar33570922005-01-25 22:26:29 +000015525 dictitem_T *v;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015526 char_u *varname;
Bram Moolenaar33570922005-01-25 22:26:29 +000015527 hashtab_T *ht;
Bram Moolenaar92124a32005-06-17 22:03:40 +000015528 char_u *p;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015529
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015530 if (tv->v_type == VAR_FUNC)
Bram Moolenaar49cd9572005-01-03 21:06:01 +000015531 {
15532 if (!(vim_strchr((char_u *)"wbs", name[0]) != NULL && name[1] == ':')
15533 && !ASCII_ISUPPER((name[0] != NUL && name[1] == ':')
15534 ? name[2] : name[0]))
15535 {
Bram Moolenaare49b69a2005-01-08 16:11:57 +000015536 EMSG2(_("E704: Funcref variable name must start with a capital: %s"), name);
Bram Moolenaar49cd9572005-01-03 21:06:01 +000015537 return;
15538 }
15539 if (function_exists(name))
15540 {
Bram Moolenaar81bf7082005-02-12 14:31:42 +000015541 EMSG2(_("705: Variable name conflicts with existing function: %s"),
15542 name);
Bram Moolenaar49cd9572005-01-03 21:06:01 +000015543 return;
15544 }
15545 }
15546
Bram Moolenaara7043832005-01-21 11:56:39 +000015547 ht = find_var_ht(name, &varname);
Bram Moolenaar33570922005-01-25 22:26:29 +000015548 if (ht == NULL || *varname == NUL)
Bram Moolenaara7043832005-01-21 11:56:39 +000015549 {
Bram Moolenaar92124a32005-06-17 22:03:40 +000015550 EMSG2(_(e_illvar), name);
Bram Moolenaara7043832005-01-21 11:56:39 +000015551 return;
15552 }
15553
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000015554 v = find_var_in_ht(ht, varname, TRUE);
Bram Moolenaar33570922005-01-25 22:26:29 +000015555 if (v != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000015556 {
Bram Moolenaar33570922005-01-25 22:26:29 +000015557 /* existing variable, need to clear the value */
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000015558 if (var_check_ro(v->di_flags, name)
15559 || tv_check_lock(v->di_tv.v_lock, name))
Bram Moolenaar33570922005-01-25 22:26:29 +000015560 return;
15561 if (v->di_tv.v_type != tv->v_type
15562 && !((v->di_tv.v_type == VAR_STRING
15563 || v->di_tv.v_type == VAR_NUMBER)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015564 && (tv->v_type == VAR_STRING
15565 || tv->v_type == VAR_NUMBER)))
Bram Moolenaar49cd9572005-01-03 21:06:01 +000015566 {
Bram Moolenaare49b69a2005-01-08 16:11:57 +000015567 EMSG2(_("E706: Variable type mismatch for: %s"), name);
Bram Moolenaar49cd9572005-01-03 21:06:01 +000015568 return;
15569 }
Bram Moolenaar33570922005-01-25 22:26:29 +000015570
15571 /*
Bram Moolenaar758711c2005-02-02 23:11:38 +000015572 * Handle setting internal v: variables separately: we don't change
15573 * the type.
Bram Moolenaar33570922005-01-25 22:26:29 +000015574 */
15575 if (ht == &vimvarht)
15576 {
15577 if (v->di_tv.v_type == VAR_STRING)
15578 {
15579 vim_free(v->di_tv.vval.v_string);
15580 if (copy || tv->v_type != VAR_STRING)
15581 v->di_tv.vval.v_string = vim_strsave(get_tv_string(tv));
15582 else
15583 {
15584 /* Take over the string to avoid an extra alloc/free. */
15585 v->di_tv.vval.v_string = tv->vval.v_string;
15586 tv->vval.v_string = NULL;
15587 }
15588 }
15589 else if (v->di_tv.v_type != VAR_NUMBER)
15590 EMSG2(_(e_intern2), "set_var()");
15591 else
15592 v->di_tv.vval.v_number = get_tv_number(tv);
15593 return;
15594 }
15595
15596 clear_tv(&v->di_tv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000015597 }
15598 else /* add a new variable */
15599 {
Bram Moolenaar92124a32005-06-17 22:03:40 +000015600 /* Make sure the variable name is valid. */
15601 for (p = varname; *p != NUL; ++p)
15602 if (!eval_isnamec1(*p) && (p == varname || !VIM_ISDIGIT(*p)))
15603 {
15604 EMSG2(_(e_illvar), varname);
15605 return;
15606 }
15607
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000015608 v = (dictitem_T *)alloc((unsigned)(sizeof(dictitem_T)
15609 + STRLEN(varname)));
Bram Moolenaara7043832005-01-21 11:56:39 +000015610 if (v == NULL)
15611 return;
Bram Moolenaar33570922005-01-25 22:26:29 +000015612 STRCPY(v->di_key, varname);
Bram Moolenaar33570922005-01-25 22:26:29 +000015613 if (hash_add(ht, DI2HIKEY(v)) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000015614 {
Bram Moolenaara7043832005-01-21 11:56:39 +000015615 vim_free(v);
Bram Moolenaar071d4272004-06-13 20:20:40 +000015616 return;
15617 }
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000015618 v->di_flags = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015619 }
Bram Moolenaara7043832005-01-21 11:56:39 +000015620
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015621 if (copy || tv->v_type == VAR_NUMBER)
Bram Moolenaar33570922005-01-25 22:26:29 +000015622 copy_tv(tv, &v->di_tv);
Bram Moolenaar1c2fda22005-01-02 11:43:19 +000015623 else
15624 {
Bram Moolenaar33570922005-01-25 22:26:29 +000015625 v->di_tv = *tv;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000015626 v->di_tv.v_lock = 0;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015627 init_tv(tv);
Bram Moolenaar1c2fda22005-01-02 11:43:19 +000015628 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000015629}
15630
Bram Moolenaar49cd9572005-01-03 21:06:01 +000015631/*
Bram Moolenaar33570922005-01-25 22:26:29 +000015632 * Return TRUE if di_flags "flags" indicate read-only variable "name".
15633 * Also give an error message.
15634 */
15635 static int
15636var_check_ro(flags, name)
15637 int flags;
15638 char_u *name;
15639{
15640 if (flags & DI_FLAGS_RO)
15641 {
15642 EMSG2(_(e_readonlyvar), name);
15643 return TRUE;
15644 }
15645 if ((flags & DI_FLAGS_RO_SBX) && sandbox)
15646 {
15647 EMSG2(_(e_readonlysbx), name);
15648 return TRUE;
15649 }
15650 return FALSE;
15651}
15652
15653/*
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000015654 * Return TRUE if typeval "tv" is set to be locked (immutable).
15655 * Also give an error message, using "name".
15656 */
15657 static int
15658tv_check_lock(lock, name)
15659 int lock;
15660 char_u *name;
15661{
15662 if (lock & VAR_LOCKED)
15663 {
15664 EMSG2(_("E741: Value is locked: %s"),
15665 name == NULL ? (char_u *)_("Unknown") : name);
15666 return TRUE;
15667 }
15668 if (lock & VAR_FIXED)
15669 {
15670 EMSG2(_("E742: Cannot change value of %s"),
15671 name == NULL ? (char_u *)_("Unknown") : name);
15672 return TRUE;
15673 }
15674 return FALSE;
15675}
15676
15677/*
Bram Moolenaar33570922005-01-25 22:26:29 +000015678 * Copy the values from typval_T "from" to typval_T "to".
Bram Moolenaar49cd9572005-01-03 21:06:01 +000015679 * When needed allocates string or increases reference count.
Bram Moolenaare9a41262005-01-15 22:18:47 +000015680 * Does not make a copy of a list or dict but copies the reference!
Bram Moolenaar49cd9572005-01-03 21:06:01 +000015681 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000015682 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015683copy_tv(from, to)
Bram Moolenaar33570922005-01-25 22:26:29 +000015684 typval_T *from;
15685 typval_T *to;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015686{
Bram Moolenaar49cd9572005-01-03 21:06:01 +000015687 to->v_type = from->v_type;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000015688 to->v_lock = 0;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000015689 switch (from->v_type)
15690 {
15691 case VAR_NUMBER:
15692 to->vval.v_number = from->vval.v_number;
15693 break;
15694 case VAR_STRING:
15695 case VAR_FUNC:
15696 if (from->vval.v_string == NULL)
15697 to->vval.v_string = NULL;
15698 else
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000015699 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +000015700 to->vval.v_string = vim_strsave(from->vval.v_string);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000015701 if (from->v_type == VAR_FUNC)
15702 func_ref(to->vval.v_string);
15703 }
Bram Moolenaar49cd9572005-01-03 21:06:01 +000015704 break;
15705 case VAR_LIST:
15706 if (from->vval.v_list == NULL)
15707 to->vval.v_list = NULL;
15708 else
15709 {
15710 to->vval.v_list = from->vval.v_list;
15711 ++to->vval.v_list->lv_refcount;
15712 }
15713 break;
Bram Moolenaar8c711452005-01-14 21:53:12 +000015714 case VAR_DICT:
15715 if (from->vval.v_dict == NULL)
15716 to->vval.v_dict = NULL;
15717 else
15718 {
15719 to->vval.v_dict = from->vval.v_dict;
15720 ++to->vval.v_dict->dv_refcount;
15721 }
15722 break;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000015723 default:
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015724 EMSG2(_(e_intern2), "copy_tv()");
Bram Moolenaar49cd9572005-01-03 21:06:01 +000015725 break;
15726 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000015727}
15728
15729/*
Bram Moolenaare9a41262005-01-15 22:18:47 +000015730 * Make a copy of an item.
15731 * Lists and Dictionaries are also copied. A deep copy if "deep" is set.
Bram Moolenaar81bf7082005-02-12 14:31:42 +000015732 * For deepcopy() "copyID" is zero for a full copy or the ID for when a
15733 * reference to an already copied list/dict can be used.
15734 * Returns FAIL or OK.
Bram Moolenaare9a41262005-01-15 22:18:47 +000015735 */
Bram Moolenaar81bf7082005-02-12 14:31:42 +000015736 static int
15737item_copy(from, to, deep, copyID)
Bram Moolenaar33570922005-01-25 22:26:29 +000015738 typval_T *from;
15739 typval_T *to;
Bram Moolenaare9a41262005-01-15 22:18:47 +000015740 int deep;
Bram Moolenaar81bf7082005-02-12 14:31:42 +000015741 int copyID;
Bram Moolenaare9a41262005-01-15 22:18:47 +000015742{
15743 static int recurse = 0;
Bram Moolenaar81bf7082005-02-12 14:31:42 +000015744 int ret = OK;
Bram Moolenaare9a41262005-01-15 22:18:47 +000015745
Bram Moolenaar33570922005-01-25 22:26:29 +000015746 if (recurse >= DICT_MAXNEST)
Bram Moolenaare9a41262005-01-15 22:18:47 +000015747 {
15748 EMSG(_("E698: variable nested too deep for making a copy"));
Bram Moolenaar81bf7082005-02-12 14:31:42 +000015749 return FAIL;
Bram Moolenaare9a41262005-01-15 22:18:47 +000015750 }
15751 ++recurse;
15752
15753 switch (from->v_type)
15754 {
15755 case VAR_NUMBER:
15756 case VAR_STRING:
15757 case VAR_FUNC:
15758 copy_tv(from, to);
15759 break;
15760 case VAR_LIST:
15761 to->v_type = VAR_LIST;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000015762 to->v_lock = 0;
Bram Moolenaar81bf7082005-02-12 14:31:42 +000015763 if (from->vval.v_list == NULL)
15764 to->vval.v_list = NULL;
15765 else if (copyID != 0 && from->vval.v_list->lv_copyID == copyID)
15766 {
15767 /* use the copy made earlier */
15768 to->vval.v_list = from->vval.v_list->lv_copylist;
15769 ++to->vval.v_list->lv_refcount;
15770 }
15771 else
15772 to->vval.v_list = list_copy(from->vval.v_list, deep, copyID);
15773 if (to->vval.v_list == NULL)
15774 ret = FAIL;
Bram Moolenaare9a41262005-01-15 22:18:47 +000015775 break;
15776 case VAR_DICT:
15777 to->v_type = VAR_DICT;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000015778 to->v_lock = 0;
Bram Moolenaar81bf7082005-02-12 14:31:42 +000015779 if (from->vval.v_dict == NULL)
15780 to->vval.v_dict = NULL;
15781 else if (copyID != 0 && from->vval.v_dict->dv_copyID == copyID)
15782 {
15783 /* use the copy made earlier */
15784 to->vval.v_dict = from->vval.v_dict->dv_copydict;
15785 ++to->vval.v_dict->dv_refcount;
15786 }
15787 else
15788 to->vval.v_dict = dict_copy(from->vval.v_dict, deep, copyID);
15789 if (to->vval.v_dict == NULL)
15790 ret = FAIL;
Bram Moolenaare9a41262005-01-15 22:18:47 +000015791 break;
15792 default:
15793 EMSG2(_(e_intern2), "item_copy()");
Bram Moolenaar81bf7082005-02-12 14:31:42 +000015794 ret = FAIL;
Bram Moolenaare9a41262005-01-15 22:18:47 +000015795 }
15796 --recurse;
Bram Moolenaar81bf7082005-02-12 14:31:42 +000015797 return ret;
Bram Moolenaare9a41262005-01-15 22:18:47 +000015798}
15799
15800/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000015801 * ":echo expr1 ..." print each argument separated with a space, add a
15802 * newline at the end.
15803 * ":echon expr1 ..." print each argument plain.
15804 */
15805 void
15806ex_echo(eap)
15807 exarg_T *eap;
15808{
15809 char_u *arg = eap->arg;
Bram Moolenaar33570922005-01-25 22:26:29 +000015810 typval_T rettv;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000015811 char_u *tofree;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015812 char_u *p;
15813 int needclr = TRUE;
15814 int atstart = TRUE;
Bram Moolenaar8a283e52005-01-06 23:28:25 +000015815 char_u numbuf[NUMBUFLEN];
Bram Moolenaar071d4272004-06-13 20:20:40 +000015816
15817 if (eap->skip)
15818 ++emsg_skip;
15819 while (*arg != NUL && *arg != '|' && *arg != '\n' && !got_int)
15820 {
15821 p = arg;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015822 if (eval1(&arg, &rettv, !eap->skip) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000015823 {
15824 /*
15825 * Report the invalid expression unless the expression evaluation
15826 * has been cancelled due to an aborting error, an interrupt, or an
15827 * exception.
15828 */
15829 if (!aborting())
15830 EMSG2(_(e_invexpr2), p);
15831 break;
15832 }
15833 if (!eap->skip)
15834 {
15835 if (atstart)
15836 {
15837 atstart = FALSE;
15838 /* Call msg_start() after eval1(), evaluating the expression
15839 * may cause a message to appear. */
15840 if (eap->cmdidx == CMD_echo)
15841 msg_start();
15842 }
15843 else if (eap->cmdidx == CMD_echo)
15844 msg_puts_attr((char_u *)" ", echo_attr);
Bram Moolenaar81bf7082005-02-12 14:31:42 +000015845 p = echo_string(&rettv, &tofree, numbuf);
15846 if (p != NULL)
15847 for ( ; *p != NUL && !got_int; ++p)
Bram Moolenaar071d4272004-06-13 20:20:40 +000015848 {
Bram Moolenaar81bf7082005-02-12 14:31:42 +000015849 if (*p == '\n' || *p == '\r' || *p == TAB)
Bram Moolenaar071d4272004-06-13 20:20:40 +000015850 {
Bram Moolenaar81bf7082005-02-12 14:31:42 +000015851 if (*p != TAB && needclr)
15852 {
15853 /* remove any text still there from the command */
15854 msg_clr_eos();
15855 needclr = FALSE;
15856 }
15857 msg_putchar_attr(*p, echo_attr);
Bram Moolenaar071d4272004-06-13 20:20:40 +000015858 }
15859 else
Bram Moolenaar81bf7082005-02-12 14:31:42 +000015860 {
15861#ifdef FEAT_MBYTE
15862 if (has_mbyte)
15863 {
15864 int i = (*mb_ptr2len_check)(p);
15865
15866 (void)msg_outtrans_len_attr(p, i, echo_attr);
15867 p += i - 1;
15868 }
15869 else
Bram Moolenaar071d4272004-06-13 20:20:40 +000015870#endif
Bram Moolenaar81bf7082005-02-12 14:31:42 +000015871 (void)msg_outtrans_len_attr(p, 1, echo_attr);
15872 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000015873 }
Bram Moolenaar49cd9572005-01-03 21:06:01 +000015874 vim_free(tofree);
Bram Moolenaar071d4272004-06-13 20:20:40 +000015875 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015876 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000015877 arg = skipwhite(arg);
15878 }
15879 eap->nextcmd = check_nextcmd(arg);
15880
15881 if (eap->skip)
15882 --emsg_skip;
15883 else
15884 {
15885 /* remove text that may still be there from the command */
15886 if (needclr)
15887 msg_clr_eos();
15888 if (eap->cmdidx == CMD_echo)
15889 msg_end();
15890 }
15891}
15892
15893/*
15894 * ":echohl {name}".
15895 */
15896 void
15897ex_echohl(eap)
15898 exarg_T *eap;
15899{
15900 int id;
15901
15902 id = syn_name2id(eap->arg);
15903 if (id == 0)
15904 echo_attr = 0;
15905 else
15906 echo_attr = syn_id2attr(id);
15907}
15908
15909/*
15910 * ":execute expr1 ..." execute the result of an expression.
15911 * ":echomsg expr1 ..." Print a message
15912 * ":echoerr expr1 ..." Print an error
15913 * Each gets spaces around each argument and a newline at the end for
15914 * echo commands
15915 */
15916 void
15917ex_execute(eap)
15918 exarg_T *eap;
15919{
15920 char_u *arg = eap->arg;
Bram Moolenaar33570922005-01-25 22:26:29 +000015921 typval_T rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015922 int ret = OK;
15923 char_u *p;
15924 garray_T ga;
15925 int len;
15926 int save_did_emsg;
15927
15928 ga_init2(&ga, 1, 80);
15929
15930 if (eap->skip)
15931 ++emsg_skip;
15932 while (*arg != NUL && *arg != '|' && *arg != '\n')
15933 {
15934 p = arg;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015935 if (eval1(&arg, &rettv, !eap->skip) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000015936 {
15937 /*
15938 * Report the invalid expression unless the expression evaluation
15939 * has been cancelled due to an aborting error, an interrupt, or an
15940 * exception.
15941 */
15942 if (!aborting())
15943 EMSG2(_(e_invexpr2), p);
15944 ret = FAIL;
15945 break;
15946 }
15947
15948 if (!eap->skip)
15949 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015950 p = get_tv_string(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000015951 len = (int)STRLEN(p);
15952 if (ga_grow(&ga, len + 2) == FAIL)
15953 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015954 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000015955 ret = FAIL;
15956 break;
15957 }
15958 if (ga.ga_len)
Bram Moolenaar071d4272004-06-13 20:20:40 +000015959 ((char_u *)(ga.ga_data))[ga.ga_len++] = ' ';
Bram Moolenaar071d4272004-06-13 20:20:40 +000015960 STRCPY((char_u *)(ga.ga_data) + ga.ga_len, p);
Bram Moolenaar071d4272004-06-13 20:20:40 +000015961 ga.ga_len += len;
15962 }
15963
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015964 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000015965 arg = skipwhite(arg);
15966 }
15967
15968 if (ret != FAIL && ga.ga_data != NULL)
15969 {
15970 if (eap->cmdidx == CMD_echomsg)
15971 MSG_ATTR(ga.ga_data, echo_attr);
15972 else if (eap->cmdidx == CMD_echoerr)
15973 {
15974 /* We don't want to abort following commands, restore did_emsg. */
15975 save_did_emsg = did_emsg;
15976 EMSG((char_u *)ga.ga_data);
15977 if (!force_abort)
15978 did_emsg = save_did_emsg;
15979 }
15980 else if (eap->cmdidx == CMD_execute)
15981 do_cmdline((char_u *)ga.ga_data,
15982 eap->getline, eap->cookie, DOCMD_NOWAIT|DOCMD_VERBOSE);
15983 }
15984
15985 ga_clear(&ga);
15986
15987 if (eap->skip)
15988 --emsg_skip;
15989
15990 eap->nextcmd = check_nextcmd(arg);
15991}
15992
15993/*
15994 * Skip over the name of an option: "&option", "&g:option" or "&l:option".
15995 * "arg" points to the "&" or '+' when called, to "option" when returning.
15996 * Returns NULL when no option name found. Otherwise pointer to the char
15997 * after the option name.
15998 */
15999 static char_u *
16000find_option_end(arg, opt_flags)
16001 char_u **arg;
16002 int *opt_flags;
16003{
16004 char_u *p = *arg;
16005
16006 ++p;
16007 if (*p == 'g' && p[1] == ':')
16008 {
16009 *opt_flags = OPT_GLOBAL;
16010 p += 2;
16011 }
16012 else if (*p == 'l' && p[1] == ':')
16013 {
16014 *opt_flags = OPT_LOCAL;
16015 p += 2;
16016 }
16017 else
16018 *opt_flags = 0;
16019
16020 if (!ASCII_ISALPHA(*p))
16021 return NULL;
16022 *arg = p;
16023
16024 if (p[0] == 't' && p[1] == '_' && p[2] != NUL && p[3] != NUL)
16025 p += 4; /* termcap option */
16026 else
16027 while (ASCII_ISALPHA(*p))
16028 ++p;
16029 return p;
16030}
16031
16032/*
16033 * ":function"
16034 */
16035 void
16036ex_function(eap)
16037 exarg_T *eap;
16038{
16039 char_u *theline;
16040 int j;
16041 int c;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016042 int saved_did_emsg;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016043 char_u *name = NULL;
16044 char_u *p;
16045 char_u *arg;
16046 garray_T newargs;
16047 garray_T newlines;
16048 int varargs = FALSE;
16049 int mustend = FALSE;
16050 int flags = 0;
16051 ufunc_T *fp;
16052 int indent;
16053 int nesting;
16054 char_u *skip_until = NULL;
Bram Moolenaar33570922005-01-25 22:26:29 +000016055 dictitem_T *v;
16056 funcdict_T fudi;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000016057 static int func_nr = 0; /* number for nameless function */
16058 int paren;
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000016059 hashtab_T *ht;
16060 int todo;
16061 hashitem_T *hi;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016062
16063 /*
16064 * ":function" without argument: list functions.
16065 */
16066 if (ends_excmd(*eap->arg))
16067 {
16068 if (!eap->skip)
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000016069 {
Bram Moolenaar038eb0e2005-02-27 22:43:26 +000016070 todo = func_hashtab.ht_used;
16071 for (hi = func_hashtab.ht_array; todo > 0 && !got_int; ++hi)
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000016072 {
16073 if (!HASHITEM_EMPTY(hi))
16074 {
16075 --todo;
16076 fp = HI2UF(hi);
16077 if (!isdigit(*fp->uf_name))
16078 list_func_head(fp, FALSE);
16079 }
16080 }
16081 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000016082 eap->nextcmd = check_nextcmd(eap->arg);
16083 return;
16084 }
16085
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000016086 /*
16087 * Get the function name. There are these situations:
16088 * func normal function name
16089 * "name" == func, "fudi.fd_dict" == NULL
16090 * dict.func new dictionary entry
16091 * "name" == NULL, "fudi.fd_dict" set,
16092 * "fudi.fd_di" == NULL, "fudi.fd_newkey" == func
16093 * dict.func existing dict entry with a Funcref
Bram Moolenaard857f0e2005-06-21 22:37:39 +000016094 * "name" == func, "fudi.fd_dict" set,
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000016095 * "fudi.fd_di" set, "fudi.fd_newkey" == NULL
16096 * dict.func existing dict entry that's not a Funcref
16097 * "name" == NULL, "fudi.fd_dict" set,
16098 * "fudi.fd_di" set, "fudi.fd_newkey" == NULL
16099 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000016100 p = eap->arg;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000016101 name = trans_function_name(&p, eap->skip, 0, &fudi);
16102 paren = (vim_strchr(p, '(') != NULL);
16103 if (name == NULL && (fudi.fd_dict == NULL || !paren) && !eap->skip)
Bram Moolenaar071d4272004-06-13 20:20:40 +000016104 {
16105 /*
16106 * Return on an invalid expression in braces, unless the expression
16107 * evaluation has been cancelled due to an aborting error, an
16108 * interrupt, or an exception.
16109 */
16110 if (!aborting())
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000016111 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000016112 if (!eap->skip && fudi.fd_newkey != NULL)
16113 EMSG2(_(e_dictkey), fudi.fd_newkey);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000016114 vim_free(fudi.fd_newkey);
Bram Moolenaar071d4272004-06-13 20:20:40 +000016115 return;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000016116 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000016117 else
16118 eap->skip = TRUE;
16119 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000016120 /* An error in a function call during evaluation of an expression in magic
16121 * braces should not cause the function not to be defined. */
16122 saved_did_emsg = did_emsg;
16123 did_emsg = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016124
16125 /*
16126 * ":function func" with only function name: list function.
16127 */
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000016128 if (!paren)
Bram Moolenaar071d4272004-06-13 20:20:40 +000016129 {
16130 if (!ends_excmd(*skipwhite(p)))
16131 {
16132 EMSG(_(e_trailing));
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000016133 goto ret_free;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016134 }
16135 eap->nextcmd = check_nextcmd(p);
16136 if (eap->nextcmd != NULL)
16137 *p = NUL;
16138 if (!eap->skip && !got_int)
16139 {
16140 fp = find_func(name);
16141 if (fp != NULL)
16142 {
16143 list_func_head(fp, TRUE);
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000016144 for (j = 0; j < fp->uf_lines.ga_len && !got_int; ++j)
Bram Moolenaar071d4272004-06-13 20:20:40 +000016145 {
16146 msg_putchar('\n');
16147 msg_outnum((long)(j + 1));
16148 if (j < 9)
16149 msg_putchar(' ');
16150 if (j < 99)
16151 msg_putchar(' ');
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000016152 msg_prt_line(FUNCLINE(fp, j), FALSE);
Bram Moolenaar071d4272004-06-13 20:20:40 +000016153 out_flush(); /* show a line at a time */
16154 ui_breakcheck();
16155 }
16156 if (!got_int)
16157 {
16158 msg_putchar('\n');
16159 msg_puts((char_u *)" endfunction");
16160 }
16161 }
16162 else
Bram Moolenaar81bf7082005-02-12 14:31:42 +000016163 emsg_funcname("E123: Undefined function: %s", name);
Bram Moolenaar071d4272004-06-13 20:20:40 +000016164 }
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000016165 goto ret_free;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016166 }
16167
16168 /*
16169 * ":function name(arg1, arg2)" Define function.
16170 */
16171 p = skipwhite(p);
16172 if (*p != '(')
16173 {
16174 if (!eap->skip)
16175 {
16176 EMSG2(_("E124: Missing '(': %s"), eap->arg);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000016177 goto ret_free;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016178 }
16179 /* attempt to continue by skipping some text */
16180 if (vim_strchr(p, '(') != NULL)
16181 p = vim_strchr(p, '(');
16182 }
16183 p = skipwhite(p + 1);
16184
16185 ga_init2(&newargs, (int)sizeof(char_u *), 3);
16186 ga_init2(&newlines, (int)sizeof(char_u *), 3);
16187
Bram Moolenaard857f0e2005-06-21 22:37:39 +000016188 if (!eap->skip)
16189 {
16190 /* Check the name of the function. */
16191 if (name != NULL)
16192 arg = name;
16193 else
16194 arg = fudi.fd_newkey;
16195 if (arg != NULL)
16196 {
16197 if (*arg == K_SPECIAL)
16198 j = 3;
16199 else
16200 j = 0;
16201 while (arg[j] != NUL && (j == 0 ? eval_isnamec1(arg[j])
16202 : eval_isnamec(arg[j])))
16203 ++j;
16204 if (arg[j] != NUL)
16205 emsg_funcname(_(e_invarg2), arg);
16206 }
16207 }
16208
Bram Moolenaar071d4272004-06-13 20:20:40 +000016209 /*
16210 * Isolate the arguments: "arg1, arg2, ...)"
16211 */
16212 while (*p != ')')
16213 {
16214 if (p[0] == '.' && p[1] == '.' && p[2] == '.')
16215 {
16216 varargs = TRUE;
16217 p += 3;
16218 mustend = TRUE;
16219 }
16220 else
16221 {
16222 arg = p;
16223 while (ASCII_ISALNUM(*p) || *p == '_')
16224 ++p;
16225 if (arg == p || isdigit(*arg)
16226 || (p - arg == 9 && STRNCMP(arg, "firstline", 9) == 0)
16227 || (p - arg == 8 && STRNCMP(arg, "lastline", 8) == 0))
16228 {
16229 if (!eap->skip)
16230 EMSG2(_("E125: Illegal argument: %s"), arg);
16231 break;
16232 }
16233 if (ga_grow(&newargs, 1) == FAIL)
16234 goto erret;
16235 c = *p;
16236 *p = NUL;
16237 arg = vim_strsave(arg);
16238 if (arg == NULL)
16239 goto erret;
16240 ((char_u **)(newargs.ga_data))[newargs.ga_len] = arg;
16241 *p = c;
16242 newargs.ga_len++;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016243 if (*p == ',')
16244 ++p;
16245 else
16246 mustend = TRUE;
16247 }
16248 p = skipwhite(p);
16249 if (mustend && *p != ')')
16250 {
16251 if (!eap->skip)
16252 EMSG2(_(e_invarg2), eap->arg);
16253 break;
16254 }
16255 }
16256 ++p; /* skip the ')' */
16257
Bram Moolenaare9a41262005-01-15 22:18:47 +000016258 /* find extra arguments "range", "dict" and "abort" */
Bram Moolenaar071d4272004-06-13 20:20:40 +000016259 for (;;)
16260 {
16261 p = skipwhite(p);
16262 if (STRNCMP(p, "range", 5) == 0)
16263 {
16264 flags |= FC_RANGE;
16265 p += 5;
16266 }
Bram Moolenaare9a41262005-01-15 22:18:47 +000016267 else if (STRNCMP(p, "dict", 4) == 0)
16268 {
16269 flags |= FC_DICT;
16270 p += 4;
16271 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000016272 else if (STRNCMP(p, "abort", 5) == 0)
16273 {
16274 flags |= FC_ABORT;
16275 p += 5;
16276 }
16277 else
16278 break;
16279 }
16280
16281 if (*p != NUL && *p != '"' && *p != '\n' && !eap->skip && !did_emsg)
16282 EMSG(_(e_trailing));
16283
16284 /*
16285 * Read the body of the function, until ":endfunction" is found.
16286 */
16287 if (KeyTyped)
16288 {
16289 /* Check if the function already exists, don't let the user type the
16290 * whole function before telling him it doesn't work! For a script we
16291 * need to skip the body to be able to find what follows. */
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000016292 if (!eap->skip && !eap->forceit)
16293 {
16294 if (fudi.fd_dict != NULL && fudi.fd_newkey == NULL)
16295 EMSG(_(e_funcdict));
16296 else if (name != NULL && find_func(name) != NULL)
Bram Moolenaar81bf7082005-02-12 14:31:42 +000016297 emsg_funcname(e_funcexts, name);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000016298 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000016299
Bram Moolenaard857f0e2005-06-21 22:37:39 +000016300 if (!eap->skip && did_emsg)
16301 goto erret;
16302
Bram Moolenaar071d4272004-06-13 20:20:40 +000016303 msg_putchar('\n'); /* don't overwrite the function name */
16304 cmdline_row = msg_row;
16305 }
16306
16307 indent = 2;
16308 nesting = 0;
16309 for (;;)
16310 {
16311 msg_scroll = TRUE;
16312 need_wait_return = FALSE;
16313 if (eap->getline == NULL)
16314 theline = getcmdline(':', 0L, indent);
16315 else
16316 theline = eap->getline(':', eap->cookie, indent);
16317 if (KeyTyped)
16318 lines_left = Rows - 1;
16319 if (theline == NULL)
16320 {
16321 EMSG(_("E126: Missing :endfunction"));
16322 goto erret;
16323 }
16324
16325 if (skip_until != NULL)
16326 {
16327 /* between ":append" and "." and between ":python <<EOF" and "EOF"
16328 * don't check for ":endfunc". */
16329 if (STRCMP(theline, skip_until) == 0)
16330 {
16331 vim_free(skip_until);
16332 skip_until = NULL;
16333 }
16334 }
16335 else
16336 {
16337 /* skip ':' and blanks*/
16338 for (p = theline; vim_iswhite(*p) || *p == ':'; ++p)
16339 ;
16340
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000016341 /* Check for "endfunction". */
16342 if (checkforcmd(&p, "endfunction", 4) && nesting-- == 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +000016343 {
16344 vim_free(theline);
16345 break;
16346 }
16347
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000016348 /* Increase indent inside "if", "while", "for" and "try", decrease
Bram Moolenaar071d4272004-06-13 20:20:40 +000016349 * at "end". */
16350 if (indent > 2 && STRNCMP(p, "end", 3) == 0)
16351 indent -= 2;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000016352 else if (STRNCMP(p, "if", 2) == 0
16353 || STRNCMP(p, "wh", 2) == 0
16354 || STRNCMP(p, "for", 3) == 0
Bram Moolenaar071d4272004-06-13 20:20:40 +000016355 || STRNCMP(p, "try", 3) == 0)
16356 indent += 2;
16357
16358 /* Check for defining a function inside this function. */
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000016359 if (checkforcmd(&p, "function", 2))
Bram Moolenaar071d4272004-06-13 20:20:40 +000016360 {
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000016361 if (*p == '!')
16362 p = skipwhite(p + 1);
Bram Moolenaar071d4272004-06-13 20:20:40 +000016363 p += eval_fname_script(p);
16364 if (ASCII_ISALPHA(*p))
16365 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000016366 vim_free(trans_function_name(&p, TRUE, 0, NULL));
Bram Moolenaar071d4272004-06-13 20:20:40 +000016367 if (*skipwhite(p) == '(')
16368 {
16369 ++nesting;
16370 indent += 2;
16371 }
16372 }
16373 }
16374
16375 /* Check for ":append" or ":insert". */
16376 p = skip_range(p, NULL);
16377 if ((p[0] == 'a' && (!ASCII_ISALPHA(p[1]) || p[1] == 'p'))
16378 || (p[0] == 'i'
16379 && (!ASCII_ISALPHA(p[1]) || (p[1] == 'n'
16380 && (!ASCII_ISALPHA(p[2]) || (p[2] == 's'))))))
16381 skip_until = vim_strsave((char_u *)".");
16382
16383 /* Check for ":python <<EOF", ":tcl <<EOF", etc. */
16384 arg = skipwhite(skiptowhite(p));
16385 if (arg[0] == '<' && arg[1] =='<'
16386 && ((p[0] == 'p' && p[1] == 'y'
16387 && (!ASCII_ISALPHA(p[2]) || p[2] == 't'))
16388 || (p[0] == 'p' && p[1] == 'e'
16389 && (!ASCII_ISALPHA(p[2]) || p[2] == 'r'))
16390 || (p[0] == 't' && p[1] == 'c'
16391 && (!ASCII_ISALPHA(p[2]) || p[2] == 'l'))
16392 || (p[0] == 'r' && p[1] == 'u' && p[2] == 'b'
16393 && (!ASCII_ISALPHA(p[3]) || p[3] == 'y'))
Bram Moolenaar325b7a22004-07-05 15:58:32 +000016394 || (p[0] == 'm' && p[1] == 'z'
16395 && (!ASCII_ISALPHA(p[2]) || p[2] == 's'))
Bram Moolenaar071d4272004-06-13 20:20:40 +000016396 ))
16397 {
16398 /* ":python <<" continues until a dot, like ":append" */
16399 p = skipwhite(arg + 2);
16400 if (*p == NUL)
16401 skip_until = vim_strsave((char_u *)".");
16402 else
16403 skip_until = vim_strsave(p);
16404 }
16405 }
16406
16407 /* Add the line to the function. */
16408 if (ga_grow(&newlines, 1) == FAIL)
16409 goto erret;
16410 ((char_u **)(newlines.ga_data))[newlines.ga_len] = theline;
16411 newlines.ga_len++;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016412 }
16413
16414 /* Don't define the function when skipping commands or when an error was
16415 * detected. */
16416 if (eap->skip || did_emsg)
16417 goto erret;
16418
16419 /*
16420 * If there are no errors, add the function
16421 */
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000016422 if (fudi.fd_dict == NULL)
Bram Moolenaar49cd9572005-01-03 21:06:01 +000016423 {
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000016424 v = find_var(name, &ht);
Bram Moolenaar33570922005-01-25 22:26:29 +000016425 if (v != NULL && v->di_tv.v_type == VAR_FUNC)
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000016426 {
Bram Moolenaar81bf7082005-02-12 14:31:42 +000016427 emsg_funcname("E707: Function name conflicts with variable: %s",
16428 name);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000016429 goto erret;
16430 }
Bram Moolenaar49cd9572005-01-03 21:06:01 +000016431
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000016432 fp = find_func(name);
16433 if (fp != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000016434 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000016435 if (!eap->forceit)
16436 {
Bram Moolenaar81bf7082005-02-12 14:31:42 +000016437 emsg_funcname(e_funcexts, name);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000016438 goto erret;
16439 }
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000016440 if (fp->uf_calls > 0)
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000016441 {
Bram Moolenaar81bf7082005-02-12 14:31:42 +000016442 emsg_funcname("E127: Cannot redefine function %s: It is in use",
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000016443 name);
16444 goto erret;
16445 }
16446 /* redefine existing function */
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000016447 ga_clear_strings(&(fp->uf_args));
16448 ga_clear_strings(&(fp->uf_lines));
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000016449 vim_free(name);
16450 name = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016451 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000016452 }
16453 else
16454 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000016455 char numbuf[20];
16456
16457 fp = NULL;
16458 if (fudi.fd_newkey == NULL && !eap->forceit)
16459 {
16460 EMSG(_(e_funcdict));
16461 goto erret;
16462 }
Bram Moolenaar758711c2005-02-02 23:11:38 +000016463 if (fudi.fd_di == NULL)
16464 {
16465 /* Can't add a function to a locked dictionary */
16466 if (tv_check_lock(fudi.fd_dict->dv_lock, eap->arg))
16467 goto erret;
16468 }
16469 /* Can't change an existing function if it is locked */
16470 else if (tv_check_lock(fudi.fd_di->di_tv.v_lock, eap->arg))
16471 goto erret;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000016472
16473 /* Give the function a sequential number. Can only be used with a
16474 * Funcref! */
16475 vim_free(name);
16476 sprintf(numbuf, "%d", ++func_nr);
16477 name = vim_strsave((char_u *)numbuf);
16478 if (name == NULL)
16479 goto erret;
16480 }
16481
16482 if (fp == NULL)
16483 {
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +000016484 if (fudi.fd_dict == NULL && vim_strchr(name, AUTOLOAD_CHAR) != NULL)
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000016485 {
16486 int slen, plen;
16487 char_u *scriptname;
16488
16489 /* Check that the autoload name matches the script name. */
16490 j = FAIL;
16491 if (sourcing_name != NULL)
16492 {
16493 scriptname = autoload_name(name);
16494 if (scriptname != NULL)
16495 {
16496 p = vim_strchr(scriptname, '/');
16497 plen = STRLEN(p);
16498 slen = STRLEN(sourcing_name);
16499 if (slen > plen && fnamecmp(p,
16500 sourcing_name + slen - plen) == 0)
16501 j = OK;
16502 vim_free(scriptname);
16503 }
16504 }
16505 if (j == FAIL)
16506 {
16507 EMSG2(_("E746: Function name does not match script file name: %s"), name);
16508 goto erret;
16509 }
16510 }
16511
16512 fp = (ufunc_T *)alloc((unsigned)(sizeof(ufunc_T) + STRLEN(name)));
Bram Moolenaar071d4272004-06-13 20:20:40 +000016513 if (fp == NULL)
16514 goto erret;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000016515
16516 if (fudi.fd_dict != NULL)
16517 {
16518 if (fudi.fd_di == NULL)
16519 {
16520 /* add new dict entry */
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000016521 fudi.fd_di = dictitem_alloc(fudi.fd_newkey);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000016522 if (fudi.fd_di == NULL)
16523 {
16524 vim_free(fp);
16525 goto erret;
16526 }
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000016527 if (dict_add(fudi.fd_dict, fudi.fd_di) == FAIL)
16528 {
16529 vim_free(fudi.fd_di);
16530 goto erret;
16531 }
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000016532 }
16533 else
16534 /* overwrite existing dict entry */
16535 clear_tv(&fudi.fd_di->di_tv);
16536 fudi.fd_di->di_tv.v_type = VAR_FUNC;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000016537 fudi.fd_di->di_tv.v_lock = 0;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000016538 fudi.fd_di->di_tv.vval.v_string = vim_strsave(name);
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000016539 fp->uf_refcount = 1;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000016540 }
16541
Bram Moolenaar071d4272004-06-13 20:20:40 +000016542 /* insert the new function in the function list */
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000016543 STRCPY(fp->uf_name, name);
16544 hash_add(&func_hashtab, UF2HIKEY(fp));
Bram Moolenaar071d4272004-06-13 20:20:40 +000016545 }
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000016546 fp->uf_args = newargs;
16547 fp->uf_lines = newlines;
Bram Moolenaar05159a02005-02-26 23:04:13 +000016548#ifdef FEAT_PROFILE
16549 fp->uf_tml_count = NULL;
16550 fp->uf_tml_total = NULL;
16551 fp->uf_tml_self = NULL;
16552 fp->uf_profiling = FALSE;
16553 if (prof_def_func())
16554 func_do_profile(fp);
16555#endif
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000016556 fp->uf_varargs = varargs;
16557 fp->uf_flags = flags;
16558 fp->uf_calls = 0;
16559 fp->uf_script_ID = current_SID;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000016560 goto ret_free;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016561
16562erret:
Bram Moolenaar071d4272004-06-13 20:20:40 +000016563 ga_clear_strings(&newargs);
16564 ga_clear_strings(&newlines);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000016565ret_free:
16566 vim_free(skip_until);
16567 vim_free(fudi.fd_newkey);
Bram Moolenaar071d4272004-06-13 20:20:40 +000016568 vim_free(name);
Bram Moolenaar071d4272004-06-13 20:20:40 +000016569 did_emsg |= saved_did_emsg;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016570}
16571
16572/*
16573 * Get a function name, translating "<SID>" and "<SNR>".
Bram Moolenaara7043832005-01-21 11:56:39 +000016574 * Also handles a Funcref in a List or Dictionary.
Bram Moolenaar071d4272004-06-13 20:20:40 +000016575 * Returns the function name in allocated memory, or NULL for failure.
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000016576 * flags:
16577 * TFN_INT: internal function name OK
16578 * TFN_QUIET: be quiet
Bram Moolenaar071d4272004-06-13 20:20:40 +000016579 * Advances "pp" to just after the function name (if no error).
16580 */
16581 static char_u *
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000016582trans_function_name(pp, skip, flags, fdp)
Bram Moolenaar071d4272004-06-13 20:20:40 +000016583 char_u **pp;
16584 int skip; /* only find the end, don't evaluate */
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000016585 int flags;
Bram Moolenaar33570922005-01-25 22:26:29 +000016586 funcdict_T *fdp; /* return: info about dictionary used */
Bram Moolenaar071d4272004-06-13 20:20:40 +000016587{
Bram Moolenaar7480b5c2005-01-16 22:07:38 +000016588 char_u *name = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016589 char_u *start;
16590 char_u *end;
16591 int lead;
16592 char_u sid_buf[20];
Bram Moolenaar071d4272004-06-13 20:20:40 +000016593 int len;
Bram Moolenaar33570922005-01-25 22:26:29 +000016594 lval_T lv;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000016595
16596 if (fdp != NULL)
Bram Moolenaar33570922005-01-25 22:26:29 +000016597 vim_memset(fdp, 0, sizeof(funcdict_T));
Bram Moolenaar071d4272004-06-13 20:20:40 +000016598 start = *pp;
Bram Moolenaara7043832005-01-21 11:56:39 +000016599
16600 /* Check for hard coded <SNR>: already translated function ID (from a user
16601 * command). */
16602 if ((*pp)[0] == K_SPECIAL && (*pp)[1] == KS_EXTRA
16603 && (*pp)[2] == (int)KE_SNR)
16604 {
16605 *pp += 3;
16606 len = get_id_len(pp) + 3;
16607 return vim_strnsave(start, len);
16608 }
16609
16610 /* A name starting with "<SID>" or "<SNR>" is local to a script. But
16611 * don't skip over "s:", get_lval() needs it for "s:dict.func". */
Bram Moolenaar071d4272004-06-13 20:20:40 +000016612 lead = eval_fname_script(start);
Bram Moolenaara7043832005-01-21 11:56:39 +000016613 if (lead > 2)
Bram Moolenaar071d4272004-06-13 20:20:40 +000016614 start += lead;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +000016615
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +000016616 end = get_lval(start, NULL, &lv, FALSE, skip, flags & TFN_QUIET,
16617 lead > 2 ? 0 : FNE_CHECK_START);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +000016618 if (end == start)
16619 {
16620 if (!skip)
16621 EMSG(_("E129: Function name required"));
16622 goto theend;
16623 }
Bram Moolenaara7043832005-01-21 11:56:39 +000016624 if (end == NULL || (lv.ll_tv != NULL && (lead > 2 || lv.ll_range)))
Bram Moolenaar7480b5c2005-01-16 22:07:38 +000016625 {
16626 /*
16627 * Report an invalid expression in braces, unless the expression
16628 * evaluation has been cancelled due to an aborting error, an
16629 * interrupt, or an exception.
16630 */
16631 if (!aborting())
16632 {
16633 if (end != NULL)
16634 EMSG2(_(e_invarg2), start);
16635 }
16636 else
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +000016637 *pp = find_name_end(start, NULL, NULL, FNE_INCL_BR);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +000016638 goto theend;
16639 }
16640
16641 if (lv.ll_tv != NULL)
16642 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000016643 if (fdp != NULL)
16644 {
16645 fdp->fd_dict = lv.ll_dict;
16646 fdp->fd_newkey = lv.ll_newkey;
16647 lv.ll_newkey = NULL;
16648 fdp->fd_di = lv.ll_di;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000016649 }
Bram Moolenaar7480b5c2005-01-16 22:07:38 +000016650 if (lv.ll_tv->v_type == VAR_FUNC && lv.ll_tv->vval.v_string != NULL)
16651 {
16652 name = vim_strsave(lv.ll_tv->vval.v_string);
16653 *pp = end;
16654 }
16655 else
16656 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000016657 if (!skip && !(flags & TFN_QUIET) && (fdp == NULL
16658 || lv.ll_dict == NULL || fdp->fd_newkey == NULL))
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000016659 EMSG(_(e_funcref));
16660 else
16661 *pp = end;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +000016662 name = NULL;
16663 }
16664 goto theend;
16665 }
16666
16667 if (lv.ll_name == NULL)
16668 {
16669 /* Error found, but continue after the function name. */
16670 *pp = end;
16671 goto theend;
16672 }
16673
16674 if (lv.ll_exp_name != NULL)
16675 len = STRLEN(lv.ll_exp_name);
16676 else
Bram Moolenaara7043832005-01-21 11:56:39 +000016677 {
16678 if (lead == 2) /* skip over "s:" */
16679 lv.ll_name += 2;
16680 len = (int)(end - lv.ll_name);
16681 }
Bram Moolenaar7480b5c2005-01-16 22:07:38 +000016682
16683 /*
16684 * Copy the function name to allocated memory.
16685 * Accept <SID>name() inside a script, translate into <SNR>123_name().
16686 * Accept <SNR>123_name() outside a script.
16687 */
16688 if (skip)
16689 lead = 0; /* do nothing */
16690 else if (lead > 0)
16691 {
16692 lead = 3;
16693 if (eval_fname_sid(*pp)) /* If it's "<SID>" */
16694 {
16695 if (current_SID <= 0)
16696 {
16697 EMSG(_(e_usingsid));
16698 goto theend;
16699 }
16700 sprintf((char *)sid_buf, "%ld_", (long)current_SID);
16701 lead += (int)STRLEN(sid_buf);
16702 }
16703 }
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +000016704 else if (!(flags & TFN_INT) && builtin_function(lv.ll_name))
Bram Moolenaar7480b5c2005-01-16 22:07:38 +000016705 {
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +000016706 EMSG2(_("E128: Function name must start with a capital or contain a colon: %s"), lv.ll_name);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +000016707 goto theend;
16708 }
16709 name = alloc((unsigned)(len + lead + 1));
16710 if (name != NULL)
16711 {
16712 if (lead > 0)
16713 {
16714 name[0] = K_SPECIAL;
16715 name[1] = KS_EXTRA;
16716 name[2] = (int)KE_SNR;
Bram Moolenaara7043832005-01-21 11:56:39 +000016717 if (lead > 3) /* If it's "<SID>" */
Bram Moolenaar7480b5c2005-01-16 22:07:38 +000016718 STRCPY(name + 3, sid_buf);
16719 }
16720 mch_memmove(name + lead, lv.ll_name, (size_t)len);
16721 name[len + lead] = NUL;
16722 }
16723 *pp = end;
16724
16725theend:
16726 clear_lval(&lv);
16727 return name;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016728}
16729
16730/*
16731 * Return 5 if "p" starts with "<SID>" or "<SNR>" (ignoring case).
16732 * Return 2 if "p" starts with "s:".
16733 * Return 0 otherwise.
16734 */
16735 static int
16736eval_fname_script(p)
16737 char_u *p;
16738{
16739 if (p[0] == '<' && (STRNICMP(p + 1, "SID>", 4) == 0
16740 || STRNICMP(p + 1, "SNR>", 4) == 0))
16741 return 5;
16742 if (p[0] == 's' && p[1] == ':')
16743 return 2;
16744 return 0;
16745}
16746
16747/*
16748 * Return TRUE if "p" starts with "<SID>" or "s:".
16749 * Only works if eval_fname_script() returned non-zero for "p"!
16750 */
16751 static int
16752eval_fname_sid(p)
16753 char_u *p;
16754{
16755 return (*p == 's' || TOUPPER_ASC(p[2]) == 'I');
16756}
16757
16758/*
16759 * List the head of the function: "name(arg1, arg2)".
16760 */
16761 static void
16762list_func_head(fp, indent)
16763 ufunc_T *fp;
16764 int indent;
16765{
16766 int j;
16767
16768 msg_start();
16769 if (indent)
16770 MSG_PUTS(" ");
16771 MSG_PUTS("function ");
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000016772 if (fp->uf_name[0] == K_SPECIAL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000016773 {
16774 MSG_PUTS_ATTR("<SNR>", hl_attr(HLF_8));
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000016775 msg_puts(fp->uf_name + 3);
Bram Moolenaar071d4272004-06-13 20:20:40 +000016776 }
16777 else
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000016778 msg_puts(fp->uf_name);
Bram Moolenaar071d4272004-06-13 20:20:40 +000016779 msg_putchar('(');
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000016780 for (j = 0; j < fp->uf_args.ga_len; ++j)
Bram Moolenaar071d4272004-06-13 20:20:40 +000016781 {
16782 if (j)
16783 MSG_PUTS(", ");
16784 msg_puts(FUNCARG(fp, j));
16785 }
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000016786 if (fp->uf_varargs)
Bram Moolenaar071d4272004-06-13 20:20:40 +000016787 {
16788 if (j)
16789 MSG_PUTS(", ");
16790 MSG_PUTS("...");
16791 }
16792 msg_putchar(')');
16793}
16794
16795/*
16796 * Find a function by name, return pointer to it in ufuncs.
16797 * Return NULL for unknown function.
16798 */
16799 static ufunc_T *
16800find_func(name)
16801 char_u *name;
16802{
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000016803 hashitem_T *hi;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016804
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000016805 hi = hash_find(&func_hashtab, name);
16806 if (!HASHITEM_EMPTY(hi))
16807 return HI2UF(hi);
16808 return NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016809}
16810
Bram Moolenaar49cd9572005-01-03 21:06:01 +000016811/*
16812 * Return TRUE if a function "name" exists.
16813 */
16814 static int
16815function_exists(name)
16816 char_u *name;
16817{
16818 char_u *p = name;
16819 int n = FALSE;
16820
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000016821 p = trans_function_name(&p, FALSE, TFN_INT|TFN_QUIET, NULL);
Bram Moolenaar49cd9572005-01-03 21:06:01 +000016822 if (p != NULL)
16823 {
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +000016824 if (builtin_function(p))
Bram Moolenaar49cd9572005-01-03 21:06:01 +000016825 n = (find_internal_func(p) >= 0);
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +000016826 else
16827 n = (find_func(p) != NULL);
Bram Moolenaar49cd9572005-01-03 21:06:01 +000016828 vim_free(p);
16829 }
16830 return n;
16831}
16832
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +000016833/*
16834 * Return TRUE if "name" looks like a builtin function name: starts with a
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +000016835 * lower case letter and doesn't contain a ':' or AUTOLOAD_CHAR.
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +000016836 */
16837 static int
16838builtin_function(name)
16839 char_u *name;
16840{
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +000016841 return ASCII_ISLOWER(name[0]) && vim_strchr(name, ':') == NULL
16842 && vim_strchr(name, AUTOLOAD_CHAR) == NULL;
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +000016843}
16844
Bram Moolenaar05159a02005-02-26 23:04:13 +000016845#if defined(FEAT_PROFILE) || defined(PROTO)
16846/*
16847 * Start profiling function "fp".
16848 */
16849 static void
16850func_do_profile(fp)
16851 ufunc_T *fp;
16852{
16853 fp->uf_tm_count = 0;
16854 profile_zero(&fp->uf_tm_self);
16855 profile_zero(&fp->uf_tm_total);
16856 if (fp->uf_tml_count == NULL)
16857 fp->uf_tml_count = (int *)alloc_clear((unsigned)
16858 (sizeof(int) * fp->uf_lines.ga_len));
16859 if (fp->uf_tml_total == NULL)
16860 fp->uf_tml_total = (proftime_T *)alloc_clear((unsigned)
16861 (sizeof(proftime_T) * fp->uf_lines.ga_len));
16862 if (fp->uf_tml_self == NULL)
16863 fp->uf_tml_self = (proftime_T *)alloc_clear((unsigned)
16864 (sizeof(proftime_T) * fp->uf_lines.ga_len));
16865 fp->uf_tml_idx = -1;
16866 if (fp->uf_tml_count == NULL || fp->uf_tml_total == NULL
16867 || fp->uf_tml_self == NULL)
16868 return; /* out of memory */
16869
16870 fp->uf_profiling = TRUE;
16871}
16872
16873/*
16874 * Dump the profiling results for all functions in file "fd".
16875 */
16876 void
16877func_dump_profile(fd)
16878 FILE *fd;
16879{
16880 hashitem_T *hi;
16881 int todo;
16882 ufunc_T *fp;
16883 int i;
Bram Moolenaar73830342005-02-28 22:48:19 +000016884 ufunc_T **sorttab;
16885 int st_len = 0;
Bram Moolenaar05159a02005-02-26 23:04:13 +000016886
16887 todo = func_hashtab.ht_used;
Bram Moolenaar73830342005-02-28 22:48:19 +000016888 sorttab = (ufunc_T **)alloc((unsigned)(sizeof(ufunc_T) * todo));
16889
Bram Moolenaar05159a02005-02-26 23:04:13 +000016890 for (hi = func_hashtab.ht_array; todo > 0; ++hi)
16891 {
16892 if (!HASHITEM_EMPTY(hi))
16893 {
16894 --todo;
16895 fp = HI2UF(hi);
16896 if (fp->uf_profiling)
16897 {
Bram Moolenaar73830342005-02-28 22:48:19 +000016898 if (sorttab != NULL)
16899 sorttab[st_len++] = fp;
16900
Bram Moolenaar05159a02005-02-26 23:04:13 +000016901 if (fp->uf_name[0] == K_SPECIAL)
16902 fprintf(fd, "FUNCTION <SNR>%s()\n", fp->uf_name + 3);
16903 else
16904 fprintf(fd, "FUNCTION %s()\n", fp->uf_name);
16905 if (fp->uf_tm_count == 1)
16906 fprintf(fd, "Called 1 time\n");
16907 else
16908 fprintf(fd, "Called %d times\n", fp->uf_tm_count);
16909 fprintf(fd, "Total time: %s\n", profile_msg(&fp->uf_tm_total));
16910 fprintf(fd, " Self time: %s\n", profile_msg(&fp->uf_tm_self));
16911 fprintf(fd, "\n");
16912 fprintf(fd, "count total (s) self (s)\n");
16913
16914 for (i = 0; i < fp->uf_lines.ga_len; ++i)
16915 {
Bram Moolenaar73830342005-02-28 22:48:19 +000016916 prof_func_line(fd, fp->uf_tml_count[i],
16917 &fp->uf_tml_total[i], &fp->uf_tml_self[i], TRUE);
Bram Moolenaar05159a02005-02-26 23:04:13 +000016918 fprintf(fd, "%s\n", FUNCLINE(fp, i));
16919 }
16920 fprintf(fd, "\n");
16921 }
16922 }
16923 }
Bram Moolenaar73830342005-02-28 22:48:19 +000016924
16925 if (sorttab != NULL && st_len > 0)
16926 {
16927 qsort((void *)sorttab, (size_t)st_len, sizeof(ufunc_T *),
16928 prof_total_cmp);
16929 prof_sort_list(fd, sorttab, st_len, "TOTAL", FALSE);
16930 qsort((void *)sorttab, (size_t)st_len, sizeof(ufunc_T *),
16931 prof_self_cmp);
16932 prof_sort_list(fd, sorttab, st_len, "SELF", TRUE);
16933 }
Bram Moolenaar05159a02005-02-26 23:04:13 +000016934}
Bram Moolenaar73830342005-02-28 22:48:19 +000016935
16936 static void
16937prof_sort_list(fd, sorttab, st_len, title, prefer_self)
16938 FILE *fd;
16939 ufunc_T **sorttab;
16940 int st_len;
16941 char *title;
16942 int prefer_self; /* when equal print only self time */
16943{
16944 int i;
16945 ufunc_T *fp;
16946
16947 fprintf(fd, "FUNCTIONS SORTED ON %s TIME\n", title);
16948 fprintf(fd, "count total (s) self (s) function\n");
16949 for (i = 0; i < 20 && i < st_len; ++i)
16950 {
16951 fp = sorttab[i];
16952 prof_func_line(fd, fp->uf_tm_count, &fp->uf_tm_total, &fp->uf_tm_self,
16953 prefer_self);
16954 if (fp->uf_name[0] == K_SPECIAL)
16955 fprintf(fd, " <SNR>%s()\n", fp->uf_name + 3);
16956 else
16957 fprintf(fd, " %s()\n", fp->uf_name);
16958 }
16959 fprintf(fd, "\n");
16960}
16961
16962/*
16963 * Print the count and times for one function or function line.
16964 */
16965 static void
16966prof_func_line(fd, count, total, self, prefer_self)
16967 FILE *fd;
16968 int count;
16969 proftime_T *total;
16970 proftime_T *self;
16971 int prefer_self; /* when equal print only self time */
16972{
16973 if (count > 0)
16974 {
16975 fprintf(fd, "%5d ", count);
16976 if (prefer_self && profile_equal(total, self))
16977 fprintf(fd, " ");
16978 else
16979 fprintf(fd, "%s ", profile_msg(total));
16980 if (!prefer_self && profile_equal(total, self))
16981 fprintf(fd, " ");
16982 else
16983 fprintf(fd, "%s ", profile_msg(self));
16984 }
16985 else
16986 fprintf(fd, " ");
16987}
16988
16989/*
16990 * Compare function for total time sorting.
16991 */
16992 static int
16993#ifdef __BORLANDC__
16994_RTLENTRYF
16995#endif
16996prof_total_cmp(s1, s2)
16997 const void *s1;
16998 const void *s2;
16999{
17000 ufunc_T *p1, *p2;
17001
17002 p1 = *(ufunc_T **)s1;
17003 p2 = *(ufunc_T **)s2;
17004 return profile_cmp(&p1->uf_tm_total, &p2->uf_tm_total);
17005}
17006
17007/*
17008 * Compare function for self time sorting.
17009 */
17010 static int
17011#ifdef __BORLANDC__
17012_RTLENTRYF
17013#endif
17014prof_self_cmp(s1, s2)
17015 const void *s1;
17016 const void *s2;
17017{
17018 ufunc_T *p1, *p2;
17019
17020 p1 = *(ufunc_T **)s1;
17021 p2 = *(ufunc_T **)s2;
17022 return profile_cmp(&p1->uf_tm_self, &p2->uf_tm_self);
17023}
17024
Bram Moolenaar05159a02005-02-26 23:04:13 +000017025#endif
17026
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +000017027/*
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000017028 * If "name" has a package name try autoloading the script for it.
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +000017029 * Return TRUE if a package was loaded.
17030 */
17031 static int
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000017032script_autoload(name)
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +000017033 char_u *name;
17034{
17035 char_u *p;
17036 char_u *scriptname;
17037 int ret = FALSE;
17038
17039 /* If there is no colon after name[1] there is no package name. */
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +000017040 p = vim_strchr(name, AUTOLOAD_CHAR);
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +000017041 if (p == NULL || p <= name + 2)
17042 return FALSE;
17043
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000017044 /* Try loading the package from $VIMRUNTIME/autoload/<name>.vim */
17045 scriptname = autoload_name(name);
17046 if (cmd_runtime(scriptname, FALSE) == OK)
17047 ret = TRUE;
17048
17049 vim_free(scriptname);
17050 return ret;
17051}
17052
17053/*
17054 * Return the autoload script name for a function or variable name.
17055 * Returns NULL when out of memory.
17056 */
17057 static char_u *
17058autoload_name(name)
17059 char_u *name;
17060{
17061 char_u *p;
17062 char_u *scriptname;
17063
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +000017064 /* Get the script file name: replace '#' with '/', append ".vim". */
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +000017065 scriptname = alloc((unsigned)(STRLEN(name) + 14));
17066 if (scriptname == NULL)
17067 return FALSE;
17068 STRCPY(scriptname, "autoload/");
17069 STRCAT(scriptname, name);
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +000017070 *vim_strrchr(scriptname, AUTOLOAD_CHAR) = NUL;
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +000017071 STRCAT(scriptname, ".vim");
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +000017072 while ((p = vim_strchr(scriptname, AUTOLOAD_CHAR)) != NULL)
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +000017073 *p = '/';
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000017074 return scriptname;
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +000017075}
17076
Bram Moolenaar071d4272004-06-13 20:20:40 +000017077#if defined(FEAT_CMDL_COMPL) || defined(PROTO)
17078
17079/*
17080 * Function given to ExpandGeneric() to obtain the list of user defined
17081 * function names.
17082 */
17083 char_u *
17084get_user_func_name(xp, idx)
17085 expand_T *xp;
17086 int idx;
17087{
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000017088 static long_u done;
17089 static hashitem_T *hi;
17090 ufunc_T *fp;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017091
17092 if (idx == 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +000017093 {
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000017094 done = 0;
17095 hi = func_hashtab.ht_array;
17096 }
17097 if (done < func_hashtab.ht_used)
17098 {
17099 if (done++ > 0)
17100 ++hi;
17101 while (HASHITEM_EMPTY(hi))
17102 ++hi;
17103 fp = HI2UF(hi);
17104
17105 if (STRLEN(fp->uf_name) + 4 >= IOSIZE)
17106 return fp->uf_name; /* prevents overflow */
Bram Moolenaar071d4272004-06-13 20:20:40 +000017107
17108 cat_func_name(IObuff, fp);
17109 if (xp->xp_context != EXPAND_USER_FUNC)
17110 {
17111 STRCAT(IObuff, "(");
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000017112 if (!fp->uf_varargs && fp->uf_args.ga_len == 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +000017113 STRCAT(IObuff, ")");
17114 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000017115 return IObuff;
17116 }
17117 return NULL;
17118}
17119
17120#endif /* FEAT_CMDL_COMPL */
17121
17122/*
17123 * Copy the function name of "fp" to buffer "buf".
17124 * "buf" must be able to hold the function name plus three bytes.
17125 * Takes care of script-local function names.
17126 */
17127 static void
17128cat_func_name(buf, fp)
17129 char_u *buf;
17130 ufunc_T *fp;
17131{
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000017132 if (fp->uf_name[0] == K_SPECIAL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000017133 {
17134 STRCPY(buf, "<SNR>");
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000017135 STRCAT(buf, fp->uf_name + 3);
Bram Moolenaar071d4272004-06-13 20:20:40 +000017136 }
17137 else
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000017138 STRCPY(buf, fp->uf_name);
Bram Moolenaar071d4272004-06-13 20:20:40 +000017139}
17140
17141/*
17142 * ":delfunction {name}"
17143 */
17144 void
17145ex_delfunction(eap)
17146 exarg_T *eap;
17147{
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000017148 ufunc_T *fp = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017149 char_u *p;
17150 char_u *name;
Bram Moolenaar33570922005-01-25 22:26:29 +000017151 funcdict_T fudi;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017152
17153 p = eap->arg;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000017154 name = trans_function_name(&p, eap->skip, 0, &fudi);
17155 vim_free(fudi.fd_newkey);
Bram Moolenaar071d4272004-06-13 20:20:40 +000017156 if (name == NULL)
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000017157 {
17158 if (fudi.fd_dict != NULL && !eap->skip)
17159 EMSG(_(e_funcref));
Bram Moolenaar071d4272004-06-13 20:20:40 +000017160 return;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000017161 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000017162 if (!ends_excmd(*skipwhite(p)))
17163 {
17164 vim_free(name);
17165 EMSG(_(e_trailing));
17166 return;
17167 }
17168 eap->nextcmd = check_nextcmd(p);
17169 if (eap->nextcmd != NULL)
17170 *p = NUL;
17171
17172 if (!eap->skip)
17173 fp = find_func(name);
17174 vim_free(name);
17175
17176 if (!eap->skip)
17177 {
17178 if (fp == NULL)
17179 {
Bram Moolenaar05159a02005-02-26 23:04:13 +000017180 EMSG2(_(e_nofunc), eap->arg);
Bram Moolenaar071d4272004-06-13 20:20:40 +000017181 return;
17182 }
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000017183 if (fp->uf_calls > 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +000017184 {
17185 EMSG2(_("E131: Cannot delete function %s: It is in use"), eap->arg);
17186 return;
17187 }
17188
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000017189 if (fudi.fd_dict != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000017190 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000017191 /* Delete the dict item that refers to the function, it will
17192 * invoke func_unref() and possibly delete the function. */
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000017193 dictitem_remove(fudi.fd_dict, fudi.fd_di);
Bram Moolenaar071d4272004-06-13 20:20:40 +000017194 }
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000017195 else
17196 func_free(fp);
17197 }
17198}
17199
17200/*
17201 * Free a function and remove it from the list of functions.
17202 */
17203 static void
17204func_free(fp)
17205 ufunc_T *fp;
17206{
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000017207 hashitem_T *hi;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000017208
17209 /* clear this function */
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000017210 ga_clear_strings(&(fp->uf_args));
17211 ga_clear_strings(&(fp->uf_lines));
Bram Moolenaar05159a02005-02-26 23:04:13 +000017212#ifdef FEAT_PROFILE
17213 vim_free(fp->uf_tml_count);
17214 vim_free(fp->uf_tml_total);
17215 vim_free(fp->uf_tml_self);
17216#endif
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000017217
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000017218 /* remove the function from the function hashtable */
17219 hi = hash_find(&func_hashtab, UF2HIKEY(fp));
17220 if (HASHITEM_EMPTY(hi))
17221 EMSG2(_(e_intern2), "func_free()");
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000017222 else
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000017223 hash_remove(&func_hashtab, hi);
17224
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000017225 vim_free(fp);
17226}
17227
17228/*
17229 * Unreference a Function: decrement the reference count and free it when it
17230 * becomes zero. Only for numbered functions.
17231 */
17232 static void
17233func_unref(name)
17234 char_u *name;
17235{
17236 ufunc_T *fp;
17237
17238 if (name != NULL && isdigit(*name))
17239 {
17240 fp = find_func(name);
17241 if (fp == NULL)
17242 EMSG2(_(e_intern2), "func_unref()");
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000017243 else if (--fp->uf_refcount <= 0)
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000017244 {
17245 /* Only delete it when it's not being used. Otherwise it's done
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000017246 * when "uf_calls" becomes zero. */
17247 if (fp->uf_calls == 0)
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000017248 func_free(fp);
17249 }
17250 }
17251}
17252
17253/*
17254 * Count a reference to a Function.
17255 */
17256 static void
17257func_ref(name)
17258 char_u *name;
17259{
17260 ufunc_T *fp;
17261
17262 if (name != NULL && isdigit(*name))
17263 {
17264 fp = find_func(name);
17265 if (fp == NULL)
17266 EMSG2(_(e_intern2), "func_ref()");
17267 else
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000017268 ++fp->uf_refcount;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017269 }
17270}
17271
17272/*
17273 * Call a user function.
17274 */
17275 static void
Bram Moolenaare9a41262005-01-15 22:18:47 +000017276call_user_func(fp, argcount, argvars, rettv, firstline, lastline, selfdict)
Bram Moolenaar071d4272004-06-13 20:20:40 +000017277 ufunc_T *fp; /* pointer to function */
17278 int argcount; /* nr of args */
Bram Moolenaar33570922005-01-25 22:26:29 +000017279 typval_T *argvars; /* arguments */
17280 typval_T *rettv; /* return value */
Bram Moolenaar071d4272004-06-13 20:20:40 +000017281 linenr_T firstline; /* first line of range */
17282 linenr_T lastline; /* last line of range */
Bram Moolenaar33570922005-01-25 22:26:29 +000017283 dict_T *selfdict; /* Dictionary for "self" */
Bram Moolenaar071d4272004-06-13 20:20:40 +000017284{
Bram Moolenaar33570922005-01-25 22:26:29 +000017285 char_u *save_sourcing_name;
17286 linenr_T save_sourcing_lnum;
17287 scid_T save_current_SID;
17288 funccall_T fc;
17289 funccall_T *save_fcp = current_funccal;
17290 int save_did_emsg;
17291 static int depth = 0;
17292 dictitem_T *v;
17293 int fixvar_idx = 0; /* index in fixvar[] */
17294 int i;
17295 int ai;
17296 char_u numbuf[NUMBUFLEN];
17297 char_u *name;
Bram Moolenaar05159a02005-02-26 23:04:13 +000017298#ifdef FEAT_PROFILE
17299 proftime_T wait_start;
17300#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000017301
17302 /* If depth of calling is getting too high, don't execute the function */
17303 if (depth >= p_mfd)
17304 {
17305 EMSG(_("E132: Function call depth is higher than 'maxfuncdepth'"));
Bram Moolenaarc70646c2005-01-04 21:52:38 +000017306 rettv->v_type = VAR_NUMBER;
17307 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017308 return;
17309 }
17310 ++depth;
17311
17312 line_breakcheck(); /* check for CTRL-C hit */
17313
Bram Moolenaar33570922005-01-25 22:26:29 +000017314 current_funccal = &fc;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017315 fc.func = fp;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000017316 fc.rettv = rettv;
17317 rettv->vval.v_number = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017318 fc.linenr = 0;
17319 fc.returned = FALSE;
17320 fc.level = ex_nesting_level;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017321 /* Check if this function has a breakpoint. */
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000017322 fc.breakpoint = dbg_find_breakpoint(FALSE, fp->uf_name, (linenr_T)0);
Bram Moolenaar071d4272004-06-13 20:20:40 +000017323 fc.dbg_tick = debug_tick;
17324
Bram Moolenaar33570922005-01-25 22:26:29 +000017325 /*
17326 * Note about using fc.fixvar[]: This is an array of FIXVAR_CNT variables
17327 * with names up to VAR_SHORT_LEN long. This avoids having to alloc/free
17328 * each argument variable and saves a lot of time.
17329 */
17330 /*
17331 * Init l: variables.
17332 */
17333 init_var_dict(&fc.l_vars, &fc.l_vars_var);
Bram Moolenaara7043832005-01-21 11:56:39 +000017334 if (selfdict != NULL)
Bram Moolenaare9a41262005-01-15 22:18:47 +000017335 {
Bram Moolenaar33570922005-01-25 22:26:29 +000017336 /* Set l:self to "selfdict". */
17337 v = &fc.fixvar[fixvar_idx++].var;
17338 STRCPY(v->di_key, "self");
17339 v->di_flags = DI_FLAGS_RO + DI_FLAGS_FIX;
17340 hash_add(&fc.l_vars.dv_hashtab, DI2HIKEY(v));
17341 v->di_tv.v_type = VAR_DICT;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000017342 v->di_tv.v_lock = 0;
Bram Moolenaar33570922005-01-25 22:26:29 +000017343 v->di_tv.vval.v_dict = selfdict;
17344 ++selfdict->dv_refcount;
17345 }
Bram Moolenaare9a41262005-01-15 22:18:47 +000017346
Bram Moolenaar33570922005-01-25 22:26:29 +000017347 /*
17348 * Init a: variables.
17349 * Set a:0 to "argcount".
17350 * Set a:000 to a list with room for the "..." arguments.
17351 */
17352 init_var_dict(&fc.l_avars, &fc.l_avars_var);
17353 add_nr_var(&fc.l_avars, &fc.fixvar[fixvar_idx++].var, "0",
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000017354 (varnumber_T)(argcount - fp->uf_args.ga_len));
Bram Moolenaar33570922005-01-25 22:26:29 +000017355 v = &fc.fixvar[fixvar_idx++].var;
17356 STRCPY(v->di_key, "000");
17357 v->di_flags = DI_FLAGS_RO | DI_FLAGS_FIX;
17358 hash_add(&fc.l_avars.dv_hashtab, DI2HIKEY(v));
17359 v->di_tv.v_type = VAR_LIST;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000017360 v->di_tv.v_lock = VAR_FIXED;
Bram Moolenaar33570922005-01-25 22:26:29 +000017361 v->di_tv.vval.v_list = &fc.l_varlist;
17362 vim_memset(&fc.l_varlist, 0, sizeof(list_T));
17363 fc.l_varlist.lv_refcount = 99999;
17364
17365 /*
17366 * Set a:firstline to "firstline" and a:lastline to "lastline".
17367 * Set a:name to named arguments.
17368 * Set a:N to the "..." arguments.
17369 */
17370 add_nr_var(&fc.l_avars, &fc.fixvar[fixvar_idx++].var, "firstline",
17371 (varnumber_T)firstline);
17372 add_nr_var(&fc.l_avars, &fc.fixvar[fixvar_idx++].var, "lastline",
17373 (varnumber_T)lastline);
17374 for (i = 0; i < argcount; ++i)
17375 {
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000017376 ai = i - fp->uf_args.ga_len;
Bram Moolenaar33570922005-01-25 22:26:29 +000017377 if (ai < 0)
17378 /* named argument a:name */
17379 name = FUNCARG(fp, i);
17380 else
Bram Moolenaare9a41262005-01-15 22:18:47 +000017381 {
Bram Moolenaar33570922005-01-25 22:26:29 +000017382 /* "..." argument a:1, a:2, etc. */
17383 sprintf((char *)numbuf, "%d", ai + 1);
17384 name = numbuf;
17385 }
17386 if (fixvar_idx < FIXVAR_CNT && STRLEN(name) <= VAR_SHORT_LEN)
17387 {
17388 v = &fc.fixvar[fixvar_idx++].var;
17389 v->di_flags = DI_FLAGS_RO | DI_FLAGS_FIX;
17390 }
17391 else
17392 {
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000017393 v = (dictitem_T *)alloc((unsigned)(sizeof(dictitem_T)
17394 + STRLEN(name)));
Bram Moolenaar33570922005-01-25 22:26:29 +000017395 if (v == NULL)
17396 break;
17397 v->di_flags = DI_FLAGS_RO;
17398 }
17399 STRCPY(v->di_key, name);
17400 hash_add(&fc.l_avars.dv_hashtab, DI2HIKEY(v));
17401
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000017402 /* Note: the values are copied directly to avoid alloc/free.
17403 * "argvars" must have VAR_FIXED for v_lock. */
Bram Moolenaar33570922005-01-25 22:26:29 +000017404 v->di_tv = argvars[i];
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000017405 v->di_tv.v_lock = VAR_FIXED;
Bram Moolenaar33570922005-01-25 22:26:29 +000017406
17407 if (ai >= 0 && ai < MAX_FUNC_ARGS)
17408 {
17409 list_append(&fc.l_varlist, &fc.l_listitems[ai]);
17410 fc.l_listitems[ai].li_tv = argvars[i];
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000017411 fc.l_listitems[ai].li_tv.v_lock = VAR_FIXED;
Bram Moolenaare9a41262005-01-15 22:18:47 +000017412 }
17413 }
17414
Bram Moolenaar071d4272004-06-13 20:20:40 +000017415 /* Don't redraw while executing the function. */
17416 ++RedrawingDisabled;
17417 save_sourcing_name = sourcing_name;
17418 save_sourcing_lnum = sourcing_lnum;
17419 sourcing_lnum = 1;
17420 sourcing_name = alloc((unsigned)((save_sourcing_name == NULL ? 0
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000017421 : STRLEN(save_sourcing_name)) + STRLEN(fp->uf_name) + 13));
Bram Moolenaar071d4272004-06-13 20:20:40 +000017422 if (sourcing_name != NULL)
17423 {
17424 if (save_sourcing_name != NULL
17425 && STRNCMP(save_sourcing_name, "function ", 9) == 0)
17426 sprintf((char *)sourcing_name, "%s..", save_sourcing_name);
17427 else
17428 STRCPY(sourcing_name, "function ");
17429 cat_func_name(sourcing_name + STRLEN(sourcing_name), fp);
17430
17431 if (p_verbose >= 12)
17432 {
17433 ++no_wait_return;
Bram Moolenaar54ee7752005-05-31 22:22:17 +000017434 verbose_enter_scroll();
17435
Bram Moolenaar555b2802005-05-19 21:08:39 +000017436 smsg((char_u *)_("calling %s"), sourcing_name);
Bram Moolenaar071d4272004-06-13 20:20:40 +000017437 if (p_verbose >= 14)
17438 {
Bram Moolenaar071d4272004-06-13 20:20:40 +000017439 char_u buf[MSG_BUF_LEN];
Bram Moolenaar758711c2005-02-02 23:11:38 +000017440 char_u numbuf[NUMBUFLEN];
17441 char_u *tofree;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017442
17443 msg_puts((char_u *)"(");
17444 for (i = 0; i < argcount; ++i)
17445 {
17446 if (i > 0)
17447 msg_puts((char_u *)", ");
Bram Moolenaar49cd9572005-01-03 21:06:01 +000017448 if (argvars[i].v_type == VAR_NUMBER)
17449 msg_outnum((long)argvars[i].vval.v_number);
Bram Moolenaar071d4272004-06-13 20:20:40 +000017450 else
17451 {
Bram Moolenaar758711c2005-02-02 23:11:38 +000017452 trunc_string(tv2string(&argvars[i], &tofree, numbuf),
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +000017453 buf, MSG_BUF_CLEN);
Bram Moolenaar071d4272004-06-13 20:20:40 +000017454 msg_puts(buf);
Bram Moolenaar758711c2005-02-02 23:11:38 +000017455 vim_free(tofree);
Bram Moolenaar071d4272004-06-13 20:20:40 +000017456 }
17457 }
17458 msg_puts((char_u *)")");
17459 }
17460 msg_puts((char_u *)"\n"); /* don't overwrite this either */
Bram Moolenaar54ee7752005-05-31 22:22:17 +000017461
17462 verbose_leave_scroll();
Bram Moolenaar071d4272004-06-13 20:20:40 +000017463 --no_wait_return;
17464 }
17465 }
Bram Moolenaar05159a02005-02-26 23:04:13 +000017466#ifdef FEAT_PROFILE
17467 if (do_profiling)
17468 {
17469 if (!fp->uf_profiling && has_profiling(FALSE, fp->uf_name, NULL))
17470 func_do_profile(fp);
17471 if (fp->uf_profiling
17472 || (save_fcp != NULL && &save_fcp->func->uf_profiling))
17473 {
17474 ++fp->uf_tm_count;
17475 profile_start(&fp->uf_tm_start);
17476 profile_zero(&fp->uf_tm_children);
17477 }
17478 script_prof_save(&wait_start);
17479 }
17480#endif
17481
Bram Moolenaar071d4272004-06-13 20:20:40 +000017482 save_current_SID = current_SID;
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000017483 current_SID = fp->uf_script_ID;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017484 save_did_emsg = did_emsg;
17485 did_emsg = FALSE;
17486
17487 /* call do_cmdline() to execute the lines */
17488 do_cmdline(NULL, get_func_line, (void *)&fc,
17489 DOCMD_NOWAIT|DOCMD_VERBOSE|DOCMD_REPEAT);
17490
17491 --RedrawingDisabled;
17492
17493 /* when the function was aborted because of an error, return -1 */
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000017494 if ((did_emsg && (fp->uf_flags & FC_ABORT)) || rettv->v_type == VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +000017495 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000017496 clear_tv(rettv);
17497 rettv->v_type = VAR_NUMBER;
17498 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017499 }
17500
Bram Moolenaar05159a02005-02-26 23:04:13 +000017501#ifdef FEAT_PROFILE
17502 if (fp->uf_profiling || (save_fcp != NULL && &save_fcp->func->uf_profiling))
17503 {
17504 profile_end(&fp->uf_tm_start);
17505 profile_sub_wait(&wait_start, &fp->uf_tm_start);
17506 profile_add(&fp->uf_tm_total, &fp->uf_tm_start);
17507 profile_add(&fp->uf_tm_self, &fp->uf_tm_start);
17508 profile_sub(&fp->uf_tm_self, &fp->uf_tm_children);
17509 if (save_fcp != NULL && &save_fcp->func->uf_profiling)
17510 {
17511 profile_add(&save_fcp->func->uf_tm_children, &fp->uf_tm_start);
17512 profile_add(&save_fcp->func->uf_tml_children, &fp->uf_tm_start);
17513 }
17514 }
17515#endif
17516
Bram Moolenaar071d4272004-06-13 20:20:40 +000017517 /* when being verbose, mention the return value */
17518 if (p_verbose >= 12)
17519 {
Bram Moolenaar071d4272004-06-13 20:20:40 +000017520 ++no_wait_return;
Bram Moolenaar54ee7752005-05-31 22:22:17 +000017521 verbose_enter_scroll();
Bram Moolenaar071d4272004-06-13 20:20:40 +000017522
Bram Moolenaar071d4272004-06-13 20:20:40 +000017523 if (aborting())
Bram Moolenaar555b2802005-05-19 21:08:39 +000017524 smsg((char_u *)_("%s aborted"), sourcing_name);
Bram Moolenaarc70646c2005-01-04 21:52:38 +000017525 else if (fc.rettv->v_type == VAR_NUMBER)
Bram Moolenaar555b2802005-05-19 21:08:39 +000017526 smsg((char_u *)_("%s returning #%ld"), sourcing_name,
17527 (long)fc.rettv->vval.v_number);
Bram Moolenaar758711c2005-02-02 23:11:38 +000017528 else
Bram Moolenaar071d4272004-06-13 20:20:40 +000017529 {
Bram Moolenaar758711c2005-02-02 23:11:38 +000017530 char_u buf[MSG_BUF_LEN];
17531 char_u numbuf[NUMBUFLEN];
17532 char_u *tofree;
17533
Bram Moolenaar555b2802005-05-19 21:08:39 +000017534 /* The value may be very long. Skip the middle part, so that we
17535 * have some idea how it starts and ends. smsg() would always
17536 * truncate it at the end. */
Bram Moolenaar758711c2005-02-02 23:11:38 +000017537 trunc_string(tv2string(fc.rettv, &tofree, numbuf),
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +000017538 buf, MSG_BUF_CLEN);
Bram Moolenaar555b2802005-05-19 21:08:39 +000017539 smsg((char_u *)_("%s returning %s"), sourcing_name, buf);
Bram Moolenaar758711c2005-02-02 23:11:38 +000017540 vim_free(tofree);
Bram Moolenaar071d4272004-06-13 20:20:40 +000017541 }
17542 msg_puts((char_u *)"\n"); /* don't overwrite this either */
Bram Moolenaar54ee7752005-05-31 22:22:17 +000017543
17544 verbose_leave_scroll();
Bram Moolenaar071d4272004-06-13 20:20:40 +000017545 --no_wait_return;
17546 }
17547
17548 vim_free(sourcing_name);
17549 sourcing_name = save_sourcing_name;
17550 sourcing_lnum = save_sourcing_lnum;
17551 current_SID = save_current_SID;
Bram Moolenaar05159a02005-02-26 23:04:13 +000017552#ifdef FEAT_PROFILE
17553 if (do_profiling)
17554 script_prof_restore(&wait_start);
17555#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000017556
17557 if (p_verbose >= 12 && sourcing_name != NULL)
17558 {
17559 ++no_wait_return;
Bram Moolenaar54ee7752005-05-31 22:22:17 +000017560 verbose_enter_scroll();
17561
Bram Moolenaar555b2802005-05-19 21:08:39 +000017562 smsg((char_u *)_("continuing in %s"), sourcing_name);
Bram Moolenaar071d4272004-06-13 20:20:40 +000017563 msg_puts((char_u *)"\n"); /* don't overwrite this either */
Bram Moolenaar54ee7752005-05-31 22:22:17 +000017564
17565 verbose_leave_scroll();
Bram Moolenaar071d4272004-06-13 20:20:40 +000017566 --no_wait_return;
17567 }
17568
17569 did_emsg |= save_did_emsg;
17570 current_funccal = save_fcp;
17571
Bram Moolenaar33570922005-01-25 22:26:29 +000017572 /* The a: variables typevals were not alloced, only free the allocated
17573 * variables. */
17574 vars_clear_ext(&fc.l_avars.dv_hashtab, FALSE);
17575
17576 vars_clear(&fc.l_vars.dv_hashtab); /* free all l: variables */
Bram Moolenaar071d4272004-06-13 20:20:40 +000017577 --depth;
17578}
17579
17580/*
Bram Moolenaar33570922005-01-25 22:26:29 +000017581 * Add a number variable "name" to dict "dp" with value "nr".
17582 */
17583 static void
17584add_nr_var(dp, v, name, nr)
17585 dict_T *dp;
17586 dictitem_T *v;
17587 char *name;
17588 varnumber_T nr;
17589{
17590 STRCPY(v->di_key, name);
17591 v->di_flags = DI_FLAGS_RO | DI_FLAGS_FIX;
17592 hash_add(&dp->dv_hashtab, DI2HIKEY(v));
17593 v->di_tv.v_type = VAR_NUMBER;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000017594 v->di_tv.v_lock = VAR_FIXED;
Bram Moolenaar33570922005-01-25 22:26:29 +000017595 v->di_tv.vval.v_number = nr;
17596}
17597
17598/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000017599 * ":return [expr]"
17600 */
17601 void
17602ex_return(eap)
17603 exarg_T *eap;
17604{
17605 char_u *arg = eap->arg;
Bram Moolenaar33570922005-01-25 22:26:29 +000017606 typval_T rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017607 int returning = FALSE;
17608
17609 if (current_funccal == NULL)
17610 {
17611 EMSG(_("E133: :return not inside a function"));
17612 return;
17613 }
17614
17615 if (eap->skip)
17616 ++emsg_skip;
17617
17618 eap->nextcmd = NULL;
17619 if ((*arg != NUL && *arg != '|' && *arg != '\n')
Bram Moolenaarc70646c2005-01-04 21:52:38 +000017620 && eval0(arg, &rettv, &eap->nextcmd, !eap->skip) != FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000017621 {
17622 if (!eap->skip)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000017623 returning = do_return(eap, FALSE, TRUE, &rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000017624 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000017625 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000017626 }
17627 /* It's safer to return also on error. */
17628 else if (!eap->skip)
17629 {
17630 /*
17631 * Return unless the expression evaluation has been cancelled due to an
17632 * aborting error, an interrupt, or an exception.
17633 */
17634 if (!aborting())
17635 returning = do_return(eap, FALSE, TRUE, NULL);
17636 }
17637
17638 /* When skipping or the return gets pending, advance to the next command
17639 * in this line (!returning). Otherwise, ignore the rest of the line.
17640 * Following lines will be ignored by get_func_line(). */
17641 if (returning)
17642 eap->nextcmd = NULL;
17643 else if (eap->nextcmd == NULL) /* no argument */
17644 eap->nextcmd = check_nextcmd(arg);
17645
17646 if (eap->skip)
17647 --emsg_skip;
17648}
17649
17650/*
17651 * Return from a function. Possibly makes the return pending. Also called
17652 * for a pending return at the ":endtry" or after returning from an extra
17653 * do_cmdline(). "reanimate" is used in the latter case. "is_cmd" is set
Bram Moolenaar33570922005-01-25 22:26:29 +000017654 * when called due to a ":return" command. "rettv" may point to a typval_T
Bram Moolenaarc70646c2005-01-04 21:52:38 +000017655 * with the return rettv. Returns TRUE when the return can be carried out,
Bram Moolenaar071d4272004-06-13 20:20:40 +000017656 * FALSE when the return gets pending.
17657 */
17658 int
Bram Moolenaarc70646c2005-01-04 21:52:38 +000017659do_return(eap, reanimate, is_cmd, rettv)
Bram Moolenaar071d4272004-06-13 20:20:40 +000017660 exarg_T *eap;
17661 int reanimate;
17662 int is_cmd;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000017663 void *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017664{
17665 int idx;
17666 struct condstack *cstack = eap->cstack;
17667
17668 if (reanimate)
17669 /* Undo the return. */
17670 current_funccal->returned = FALSE;
17671
17672 /*
17673 * Cleanup (and inactivate) conditionals, but stop when a try conditional
17674 * not in its finally clause (which then is to be executed next) is found.
17675 * In this case, make the ":return" pending for execution at the ":endtry".
17676 * Otherwise, return normally.
17677 */
17678 idx = cleanup_conditionals(eap->cstack, 0, TRUE);
17679 if (idx >= 0)
17680 {
17681 cstack->cs_pending[idx] = CSTP_RETURN;
17682
17683 if (!is_cmd && !reanimate)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000017684 /* A pending return again gets pending. "rettv" points to an
17685 * allocated variable with the rettv of the original ":return"'s
Bram Moolenaar071d4272004-06-13 20:20:40 +000017686 * argument if present or is NULL else. */
Bram Moolenaarc70646c2005-01-04 21:52:38 +000017687 cstack->cs_rettv[idx] = rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017688 else
17689 {
17690 /* When undoing a return in order to make it pending, get the stored
Bram Moolenaarc70646c2005-01-04 21:52:38 +000017691 * return rettv. */
Bram Moolenaar071d4272004-06-13 20:20:40 +000017692 if (reanimate)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000017693 rettv = current_funccal->rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017694
Bram Moolenaarc70646c2005-01-04 21:52:38 +000017695 if (rettv != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000017696 {
17697 /* Store the value of the pending return. */
Bram Moolenaarc70646c2005-01-04 21:52:38 +000017698 if ((cstack->cs_rettv[idx] = alloc_tv()) != NULL)
Bram Moolenaar33570922005-01-25 22:26:29 +000017699 *(typval_T *)cstack->cs_rettv[idx] = *(typval_T *)rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017700 else
17701 EMSG(_(e_outofmem));
17702 }
17703 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000017704 cstack->cs_rettv[idx] = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017705
17706 if (reanimate)
17707 {
17708 /* The pending return value could be overwritten by a ":return"
17709 * without argument in a finally clause; reset the default
17710 * return value. */
Bram Moolenaarc70646c2005-01-04 21:52:38 +000017711 current_funccal->rettv->v_type = VAR_NUMBER;
17712 current_funccal->rettv->vval.v_number = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017713 }
17714 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +000017715 report_make_pending(CSTP_RETURN, rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000017716 }
17717 else
17718 {
17719 current_funccal->returned = TRUE;
17720
17721 /* If the return is carried out now, store the return value. For
17722 * a return immediately after reanimation, the value is already
17723 * there. */
Bram Moolenaarc70646c2005-01-04 21:52:38 +000017724 if (!reanimate && rettv != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000017725 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000017726 clear_tv(current_funccal->rettv);
Bram Moolenaar33570922005-01-25 22:26:29 +000017727 *current_funccal->rettv = *(typval_T *)rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017728 if (!is_cmd)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000017729 vim_free(rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000017730 }
17731 }
17732
17733 return idx < 0;
17734}
17735
17736/*
17737 * Free the variable with a pending return value.
17738 */
17739 void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000017740discard_pending_return(rettv)
17741 void *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017742{
Bram Moolenaar33570922005-01-25 22:26:29 +000017743 free_tv((typval_T *)rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000017744}
17745
17746/*
Bram Moolenaarc70646c2005-01-04 21:52:38 +000017747 * Generate a return command for producing the value of "rettv". The result
Bram Moolenaar071d4272004-06-13 20:20:40 +000017748 * is an allocated string. Used by report_pending() for verbose messages.
17749 */
17750 char_u *
Bram Moolenaarc70646c2005-01-04 21:52:38 +000017751get_return_cmd(rettv)
17752 void *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017753{
Bram Moolenaar81bf7082005-02-12 14:31:42 +000017754 char_u *s = NULL;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000017755 char_u *tofree = NULL;
Bram Moolenaar8a283e52005-01-06 23:28:25 +000017756 char_u numbuf[NUMBUFLEN];
Bram Moolenaar071d4272004-06-13 20:20:40 +000017757
Bram Moolenaar81bf7082005-02-12 14:31:42 +000017758 if (rettv != NULL)
Bram Moolenaar33570922005-01-25 22:26:29 +000017759 s = echo_string((typval_T *)rettv, &tofree, numbuf);
Bram Moolenaar81bf7082005-02-12 14:31:42 +000017760 if (s == NULL)
17761 s = (char_u *)"";
Bram Moolenaarc70646c2005-01-04 21:52:38 +000017762
17763 STRCPY(IObuff, ":return ");
17764 STRNCPY(IObuff + 8, s, IOSIZE - 8);
17765 if (STRLEN(s) + 8 >= IOSIZE)
17766 STRCPY(IObuff + IOSIZE - 4, "...");
17767 vim_free(tofree);
17768 return vim_strsave(IObuff);
Bram Moolenaar071d4272004-06-13 20:20:40 +000017769}
17770
17771/*
17772 * Get next function line.
17773 * Called by do_cmdline() to get the next line.
17774 * Returns allocated string, or NULL for end of function.
17775 */
17776/* ARGSUSED */
17777 char_u *
17778get_func_line(c, cookie, indent)
17779 int c; /* not used */
17780 void *cookie;
17781 int indent; /* not used */
17782{
Bram Moolenaar33570922005-01-25 22:26:29 +000017783 funccall_T *fcp = (funccall_T *)cookie;
Bram Moolenaar05159a02005-02-26 23:04:13 +000017784 ufunc_T *fp = fcp->func;
17785 char_u *retval;
17786 garray_T *gap; /* growarray with function lines */
Bram Moolenaar071d4272004-06-13 20:20:40 +000017787
17788 /* If breakpoints have been added/deleted need to check for it. */
17789 if (fcp->dbg_tick != debug_tick)
17790 {
Bram Moolenaar05159a02005-02-26 23:04:13 +000017791 fcp->breakpoint = dbg_find_breakpoint(FALSE, fp->uf_name,
Bram Moolenaar071d4272004-06-13 20:20:40 +000017792 sourcing_lnum);
17793 fcp->dbg_tick = debug_tick;
17794 }
Bram Moolenaar05159a02005-02-26 23:04:13 +000017795#ifdef FEAT_PROFILE
17796 if (do_profiling)
17797 func_line_end(cookie);
17798#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000017799
Bram Moolenaar05159a02005-02-26 23:04:13 +000017800 gap = &fp->uf_lines;
17801 if ((fp->uf_flags & FC_ABORT) && did_emsg && !aborted_in_try())
Bram Moolenaar071d4272004-06-13 20:20:40 +000017802 retval = NULL;
17803 else if (fcp->returned || fcp->linenr >= gap->ga_len)
17804 retval = NULL;
17805 else
17806 {
17807 retval = vim_strsave(((char_u **)(gap->ga_data))[fcp->linenr++]);
17808 sourcing_lnum = fcp->linenr;
Bram Moolenaar05159a02005-02-26 23:04:13 +000017809#ifdef FEAT_PROFILE
17810 if (do_profiling)
17811 func_line_start(cookie);
17812#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000017813 }
17814
17815 /* Did we encounter a breakpoint? */
17816 if (fcp->breakpoint != 0 && fcp->breakpoint <= sourcing_lnum)
17817 {
Bram Moolenaar05159a02005-02-26 23:04:13 +000017818 dbg_breakpoint(fp->uf_name, sourcing_lnum);
Bram Moolenaar071d4272004-06-13 20:20:40 +000017819 /* Find next breakpoint. */
Bram Moolenaar05159a02005-02-26 23:04:13 +000017820 fcp->breakpoint = dbg_find_breakpoint(FALSE, fp->uf_name,
Bram Moolenaar071d4272004-06-13 20:20:40 +000017821 sourcing_lnum);
17822 fcp->dbg_tick = debug_tick;
17823 }
17824
17825 return retval;
17826}
17827
Bram Moolenaar05159a02005-02-26 23:04:13 +000017828#if defined(FEAT_PROFILE) || defined(PROTO)
17829/*
17830 * Called when starting to read a function line.
17831 * "sourcing_lnum" must be correct!
17832 * When skipping lines it may not actually be executed, but we won't find out
17833 * until later and we need to store the time now.
17834 */
17835 void
17836func_line_start(cookie)
17837 void *cookie;
17838{
17839 funccall_T *fcp = (funccall_T *)cookie;
17840 ufunc_T *fp = fcp->func;
17841
17842 if (fp->uf_profiling && sourcing_lnum >= 1
17843 && sourcing_lnum <= fp->uf_lines.ga_len)
17844 {
17845 fp->uf_tml_idx = sourcing_lnum - 1;
17846 fp->uf_tml_execed = FALSE;
17847 profile_start(&fp->uf_tml_start);
17848 profile_zero(&fp->uf_tml_children);
17849 profile_get_wait(&fp->uf_tml_wait);
17850 }
17851}
17852
17853/*
17854 * Called when actually executing a function line.
17855 */
17856 void
17857func_line_exec(cookie)
17858 void *cookie;
17859{
17860 funccall_T *fcp = (funccall_T *)cookie;
17861 ufunc_T *fp = fcp->func;
17862
17863 if (fp->uf_profiling && fp->uf_tml_idx >= 0)
17864 fp->uf_tml_execed = TRUE;
17865}
17866
17867/*
17868 * Called when done with a function line.
17869 */
17870 void
17871func_line_end(cookie)
17872 void *cookie;
17873{
17874 funccall_T *fcp = (funccall_T *)cookie;
17875 ufunc_T *fp = fcp->func;
17876
17877 if (fp->uf_profiling && fp->uf_tml_idx >= 0)
17878 {
17879 if (fp->uf_tml_execed)
17880 {
17881 ++fp->uf_tml_count[fp->uf_tml_idx];
17882 profile_end(&fp->uf_tml_start);
17883 profile_sub_wait(&fp->uf_tml_wait, &fp->uf_tml_start);
17884 profile_add(&fp->uf_tml_self[fp->uf_tml_idx], &fp->uf_tml_start);
17885 profile_add(&fp->uf_tml_total[fp->uf_tml_idx], &fp->uf_tml_start);
17886 profile_sub(&fp->uf_tml_self[fp->uf_tml_idx], &fp->uf_tml_children);
17887 }
17888 fp->uf_tml_idx = -1;
17889 }
17890}
17891#endif
17892
Bram Moolenaar071d4272004-06-13 20:20:40 +000017893/*
17894 * Return TRUE if the currently active function should be ended, because a
17895 * return was encountered or an error occured. Used inside a ":while".
17896 */
17897 int
17898func_has_ended(cookie)
17899 void *cookie;
17900{
Bram Moolenaar33570922005-01-25 22:26:29 +000017901 funccall_T *fcp = (funccall_T *)cookie;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017902
17903 /* Ignore the "abort" flag if the abortion behavior has been changed due to
17904 * an error inside a try conditional. */
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000017905 return (((fcp->func->uf_flags & FC_ABORT) && did_emsg && !aborted_in_try())
Bram Moolenaar071d4272004-06-13 20:20:40 +000017906 || fcp->returned);
17907}
17908
17909/*
17910 * return TRUE if cookie indicates a function which "abort"s on errors.
17911 */
17912 int
17913func_has_abort(cookie)
17914 void *cookie;
17915{
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000017916 return ((funccall_T *)cookie)->func->uf_flags & FC_ABORT;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017917}
17918
17919#if defined(FEAT_VIMINFO) || defined(FEAT_SESSION)
17920typedef enum
17921{
17922 VAR_FLAVOUR_DEFAULT,
17923 VAR_FLAVOUR_SESSION,
17924 VAR_FLAVOUR_VIMINFO
17925} var_flavour_T;
17926
17927static var_flavour_T var_flavour __ARGS((char_u *varname));
17928
17929 static var_flavour_T
17930var_flavour(varname)
17931 char_u *varname;
17932{
17933 char_u *p = varname;
17934
17935 if (ASCII_ISUPPER(*p))
17936 {
17937 while (*(++p))
17938 if (ASCII_ISLOWER(*p))
17939 return VAR_FLAVOUR_SESSION;
17940 return VAR_FLAVOUR_VIMINFO;
17941 }
17942 else
17943 return VAR_FLAVOUR_DEFAULT;
17944}
17945#endif
17946
17947#if defined(FEAT_VIMINFO) || defined(PROTO)
17948/*
17949 * Restore global vars that start with a capital from the viminfo file
17950 */
17951 int
17952read_viminfo_varlist(virp, writing)
17953 vir_T *virp;
17954 int writing;
17955{
17956 char_u *tab;
17957 int is_string = FALSE;
Bram Moolenaar33570922005-01-25 22:26:29 +000017958 typval_T tv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017959
17960 if (!writing && (find_viminfo_parameter('!') != NULL))
17961 {
17962 tab = vim_strchr(virp->vir_line + 1, '\t');
17963 if (tab != NULL)
17964 {
17965 *tab++ = '\0'; /* isolate the variable name */
17966 if (*tab == 'S') /* string var */
17967 is_string = TRUE;
17968
17969 tab = vim_strchr(tab, '\t');
17970 if (tab != NULL)
17971 {
Bram Moolenaar071d4272004-06-13 20:20:40 +000017972 if (is_string)
17973 {
Bram Moolenaar3d60ec22005-01-05 22:19:46 +000017974 tv.v_type = VAR_STRING;
17975 tv.vval.v_string = viminfo_readstring(virp,
Bram Moolenaar071d4272004-06-13 20:20:40 +000017976 (int)(tab - virp->vir_line + 1), TRUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +000017977 }
17978 else
17979 {
Bram Moolenaar3d60ec22005-01-05 22:19:46 +000017980 tv.v_type = VAR_NUMBER;
17981 tv.vval.v_number = atol((char *)tab + 1);
Bram Moolenaar071d4272004-06-13 20:20:40 +000017982 }
Bram Moolenaar3d60ec22005-01-05 22:19:46 +000017983 set_var(virp->vir_line + 1, &tv, FALSE);
17984 if (is_string)
17985 vim_free(tv.vval.v_string);
Bram Moolenaar071d4272004-06-13 20:20:40 +000017986 }
17987 }
17988 }
17989
17990 return viminfo_readline(virp);
17991}
17992
17993/*
17994 * Write global vars that start with a capital to the viminfo file
17995 */
17996 void
17997write_viminfo_varlist(fp)
17998 FILE *fp;
17999{
Bram Moolenaar33570922005-01-25 22:26:29 +000018000 hashitem_T *hi;
18001 dictitem_T *this_var;
Bram Moolenaara7043832005-01-21 11:56:39 +000018002 int todo;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000018003 char *s;
Bram Moolenaar81bf7082005-02-12 14:31:42 +000018004 char_u *p;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000018005 char_u *tofree;
Bram Moolenaar8a283e52005-01-06 23:28:25 +000018006 char_u numbuf[NUMBUFLEN];
Bram Moolenaar071d4272004-06-13 20:20:40 +000018007
18008 if (find_viminfo_parameter('!') == NULL)
18009 return;
18010
18011 fprintf(fp, _("\n# global variables:\n"));
Bram Moolenaara7043832005-01-21 11:56:39 +000018012
Bram Moolenaar33570922005-01-25 22:26:29 +000018013 todo = globvarht.ht_used;
18014 for (hi = globvarht.ht_array; todo > 0; ++hi)
Bram Moolenaar071d4272004-06-13 20:20:40 +000018015 {
Bram Moolenaara7043832005-01-21 11:56:39 +000018016 if (!HASHITEM_EMPTY(hi))
Bram Moolenaar071d4272004-06-13 20:20:40 +000018017 {
Bram Moolenaara7043832005-01-21 11:56:39 +000018018 --todo;
Bram Moolenaar33570922005-01-25 22:26:29 +000018019 this_var = HI2DI(hi);
18020 if (var_flavour(this_var->di_key) == VAR_FLAVOUR_VIMINFO)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000018021 {
Bram Moolenaar33570922005-01-25 22:26:29 +000018022 switch (this_var->di_tv.v_type)
Bram Moolenaara7043832005-01-21 11:56:39 +000018023 {
18024 case VAR_STRING: s = "STR"; break;
18025 case VAR_NUMBER: s = "NUM"; break;
18026 default: continue;
18027 }
Bram Moolenaar33570922005-01-25 22:26:29 +000018028 fprintf(fp, "!%s\t%s\t", this_var->di_key, s);
Bram Moolenaar81bf7082005-02-12 14:31:42 +000018029 p = echo_string(&this_var->di_tv, &tofree, numbuf);
18030 if (p != NULL)
18031 viminfo_writestring(fp, p);
Bram Moolenaara7043832005-01-21 11:56:39 +000018032 vim_free(tofree);
18033 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000018034 }
18035 }
18036}
18037#endif
18038
18039#if defined(FEAT_SESSION) || defined(PROTO)
18040 int
18041store_session_globals(fd)
18042 FILE *fd;
18043{
Bram Moolenaar33570922005-01-25 22:26:29 +000018044 hashitem_T *hi;
18045 dictitem_T *this_var;
Bram Moolenaara7043832005-01-21 11:56:39 +000018046 int todo;
Bram Moolenaar071d4272004-06-13 20:20:40 +000018047 char_u *p, *t;
18048
Bram Moolenaar33570922005-01-25 22:26:29 +000018049 todo = globvarht.ht_used;
18050 for (hi = globvarht.ht_array; todo > 0; ++hi)
Bram Moolenaar071d4272004-06-13 20:20:40 +000018051 {
Bram Moolenaara7043832005-01-21 11:56:39 +000018052 if (!HASHITEM_EMPTY(hi))
Bram Moolenaar071d4272004-06-13 20:20:40 +000018053 {
Bram Moolenaara7043832005-01-21 11:56:39 +000018054 --todo;
Bram Moolenaar33570922005-01-25 22:26:29 +000018055 this_var = HI2DI(hi);
18056 if ((this_var->di_tv.v_type == VAR_NUMBER
18057 || this_var->di_tv.v_type == VAR_STRING)
18058 && var_flavour(this_var->di_key) == VAR_FLAVOUR_SESSION)
Bram Moolenaar3d60ec22005-01-05 22:19:46 +000018059 {
Bram Moolenaara7043832005-01-21 11:56:39 +000018060 /* Escape special characters with a backslash. Turn a LF and
18061 * CR into \n and \r. */
Bram Moolenaar33570922005-01-25 22:26:29 +000018062 p = vim_strsave_escaped(get_tv_string(&this_var->di_tv),
Bram Moolenaara7043832005-01-21 11:56:39 +000018063 (char_u *)"\\\"\n\r");
18064 if (p == NULL) /* out of memory */
18065 break;
18066 for (t = p; *t != NUL; ++t)
18067 if (*t == '\n')
18068 *t = 'n';
18069 else if (*t == '\r')
18070 *t = 'r';
18071 if ((fprintf(fd, "let %s = %c%s%c",
Bram Moolenaar33570922005-01-25 22:26:29 +000018072 this_var->di_key,
18073 (this_var->di_tv.v_type == VAR_STRING) ? '"'
18074 : ' ',
18075 p,
18076 (this_var->di_tv.v_type == VAR_STRING) ? '"'
18077 : ' ') < 0)
Bram Moolenaara7043832005-01-21 11:56:39 +000018078 || put_eol(fd) == FAIL)
18079 {
18080 vim_free(p);
18081 return FAIL;
18082 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000018083 vim_free(p);
18084 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000018085 }
18086 }
18087 return OK;
18088}
18089#endif
18090
18091#endif /* FEAT_EVAL */
18092
18093#if defined(FEAT_MODIFY_FNAME) || defined(FEAT_EVAL) || defined(PROTO)
18094
18095
18096#ifdef WIN3264
18097/*
18098 * Functions for ":8" filename modifier: get 8.3 version of a filename.
18099 */
18100static int get_short_pathname __ARGS((char_u **fnamep, char_u **bufp, int *fnamelen));
18101static int shortpath_for_invalid_fname __ARGS((char_u **fname, char_u **bufp, int *fnamelen));
18102static int shortpath_for_partial __ARGS((char_u **fnamep, char_u **bufp, int *fnamelen));
18103
18104/*
18105 * Get the short pathname of a file.
18106 * Returns 1 on success. *fnamelen is 0 for nonexistant path.
18107 */
18108 static int
18109get_short_pathname(fnamep, bufp, fnamelen)
18110 char_u **fnamep;
18111 char_u **bufp;
18112 int *fnamelen;
18113{
18114 int l,len;
18115 char_u *newbuf;
18116
18117 len = *fnamelen;
18118
18119 l = GetShortPathName(*fnamep, *fnamep, len);
18120 if (l > len - 1)
18121 {
18122 /* If that doesn't work (not enough space), then save the string
18123 * and try again with a new buffer big enough
18124 */
18125 newbuf = vim_strnsave(*fnamep, l);
18126 if (newbuf == NULL)
18127 return 0;
18128
18129 vim_free(*bufp);
18130 *fnamep = *bufp = newbuf;
18131
18132 l = GetShortPathName(*fnamep,*fnamep,l+1);
18133
18134 /* Really should always succeed, as the buffer is big enough */
18135 }
18136
18137 *fnamelen = l;
18138 return 1;
18139}
18140
18141/*
18142 * Create a short path name. Returns the length of the buffer it needs.
18143 * Doesn't copy over the end of the buffer passed in.
18144 */
18145 static int
18146shortpath_for_invalid_fname(fname, bufp, fnamelen)
18147 char_u **fname;
18148 char_u **bufp;
18149 int *fnamelen;
18150{
18151 char_u *s, *p, *pbuf2, *pbuf3;
18152 char_u ch;
Bram Moolenaar75c50c42005-06-04 22:06:24 +000018153 int len, len2, plen, slen;
Bram Moolenaar071d4272004-06-13 20:20:40 +000018154
18155 /* Make a copy */
18156 len2 = *fnamelen;
18157 pbuf2 = vim_strnsave(*fname, len2);
18158 pbuf3 = NULL;
18159
18160 s = pbuf2 + len2 - 1; /* Find the end */
18161 slen = 1;
18162 plen = len2;
18163
Bram Moolenaar1cd871b2004-12-19 22:46:22 +000018164 if (after_pathsep(pbuf2, s + 1))
Bram Moolenaar071d4272004-06-13 20:20:40 +000018165 {
18166 --s;
18167 ++slen;
18168 --plen;
18169 }
18170
18171 do
18172 {
18173 /* Go back one path-seperator */
Bram Moolenaar1cd871b2004-12-19 22:46:22 +000018174 while (s > pbuf2 && !after_pathsep(pbuf2, s + 1))
Bram Moolenaar071d4272004-06-13 20:20:40 +000018175 {
18176 --s;
18177 ++slen;
18178 --plen;
18179 }
18180 if (s <= pbuf2)
18181 break;
18182
18183 /* Remeber the character that is about to be blatted */
18184 ch = *s;
18185 *s = 0; /* get_short_pathname requires a null-terminated string */
18186
18187 /* Try it in situ */
18188 p = pbuf2;
18189 if (!get_short_pathname(&p, &pbuf3, &plen))
18190 {
18191 vim_free(pbuf2);
18192 return -1;
18193 }
18194 *s = ch; /* Preserve the string */
18195 } while (plen == 0);
18196
18197 if (plen > 0)
18198 {
18199 /* Remeber the length of the new string. */
18200 *fnamelen = len = plen + slen;
18201 vim_free(*bufp);
18202 if (len > len2)
18203 {
18204 /* If there's not enough space in the currently allocated string,
18205 * then copy it to a buffer big enough.
18206 */
18207 *fname= *bufp = vim_strnsave(p, len);
18208 if (*fname == NULL)
18209 return -1;
18210 }
18211 else
18212 {
18213 /* Transfer pbuf2 to being the main buffer (it's big enough) */
18214 *fname = *bufp = pbuf2;
18215 if (p != pbuf2)
18216 strncpy(*fname, p, plen);
18217 pbuf2 = NULL;
18218 }
18219 /* Concat the next bit */
18220 strncpy(*fname + plen, s, slen);
18221 (*fname)[len] = '\0';
18222 }
18223 vim_free(pbuf3);
18224 vim_free(pbuf2);
18225 return 0;
18226}
18227
18228/*
18229 * Get a pathname for a partial path.
18230 */
18231 static int
18232shortpath_for_partial(fnamep, bufp, fnamelen)
18233 char_u **fnamep;
18234 char_u **bufp;
18235 int *fnamelen;
18236{
18237 int sepcount, len, tflen;
18238 char_u *p;
18239 char_u *pbuf, *tfname;
18240 int hasTilde;
18241
18242 /* Count up the path seperators from the RHS.. so we know which part
18243 * of the path to return.
18244 */
18245 sepcount = 0;
Bram Moolenaar1cd871b2004-12-19 22:46:22 +000018246 for (p = *fnamep; p < *fnamep + *fnamelen; mb_ptr_adv(p))
Bram Moolenaar071d4272004-06-13 20:20:40 +000018247 if (vim_ispathsep(*p))
18248 ++sepcount;
18249
18250 /* Need full path first (use expand_env() to remove a "~/") */
18251 hasTilde = (**fnamep == '~');
18252 if (hasTilde)
18253 pbuf = tfname = expand_env_save(*fnamep);
18254 else
18255 pbuf = tfname = FullName_save(*fnamep, FALSE);
18256
18257 len = tflen = STRLEN(tfname);
18258
18259 if (!get_short_pathname(&tfname, &pbuf, &len))
18260 return -1;
18261
18262 if (len == 0)
18263 {
18264 /* Don't have a valid filename, so shorten the rest of the
18265 * path if we can. This CAN give us invalid 8.3 filenames, but
18266 * there's not a lot of point in guessing what it might be.
18267 */
18268 len = tflen;
18269 if (shortpath_for_invalid_fname(&tfname, &pbuf, &len) == -1)
18270 return -1;
18271 }
18272
18273 /* Count the paths backward to find the beginning of the desired string. */
18274 for (p = tfname + len - 1; p >= tfname; --p)
Bram Moolenaar1cd871b2004-12-19 22:46:22 +000018275 {
18276#ifdef FEAT_MBYTE
18277 if (has_mbyte)
18278 p -= mb_head_off(tfname, p);
18279#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000018280 if (vim_ispathsep(*p))
18281 {
18282 if (sepcount == 0 || (hasTilde && sepcount == 1))
18283 break;
18284 else
18285 sepcount --;
18286 }
Bram Moolenaar1cd871b2004-12-19 22:46:22 +000018287 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000018288 if (hasTilde)
18289 {
18290 --p;
18291 if (p >= tfname)
18292 *p = '~';
18293 else
18294 return -1;
18295 }
18296 else
18297 ++p;
18298
18299 /* Copy in the string - p indexes into tfname - allocated at pbuf */
18300 vim_free(*bufp);
18301 *fnamelen = (int)STRLEN(p);
18302 *bufp = pbuf;
18303 *fnamep = p;
18304
18305 return 0;
18306}
18307#endif /* WIN3264 */
18308
18309/*
18310 * Adjust a filename, according to a string of modifiers.
18311 * *fnamep must be NUL terminated when called. When returning, the length is
18312 * determined by *fnamelen.
18313 * Returns valid flags.
18314 * When there is an error, *fnamep is set to NULL.
18315 */
18316 int
18317modify_fname(src, usedlen, fnamep, bufp, fnamelen)
18318 char_u *src; /* string with modifiers */
18319 int *usedlen; /* characters after src that are used */
18320 char_u **fnamep; /* file name so far */
18321 char_u **bufp; /* buffer for allocated file name or NULL */
18322 int *fnamelen; /* length of fnamep */
18323{
18324 int valid = 0;
18325 char_u *tail;
18326 char_u *s, *p, *pbuf;
18327 char_u dirname[MAXPATHL];
18328 int c;
18329 int has_fullname = 0;
18330#ifdef WIN3264
18331 int has_shortname = 0;
18332#endif
18333
18334repeat:
18335 /* ":p" - full path/file_name */
18336 if (src[*usedlen] == ':' && src[*usedlen + 1] == 'p')
18337 {
18338 has_fullname = 1;
18339
18340 valid |= VALID_PATH;
18341 *usedlen += 2;
18342
18343 /* Expand "~/path" for all systems and "~user/path" for Unix and VMS */
18344 if ((*fnamep)[0] == '~'
18345#if !defined(UNIX) && !(defined(VMS) && defined(USER_HOME))
18346 && ((*fnamep)[1] == '/'
18347# ifdef BACKSLASH_IN_FILENAME
18348 || (*fnamep)[1] == '\\'
18349# endif
18350 || (*fnamep)[1] == NUL)
18351
18352#endif
18353 )
18354 {
18355 *fnamep = expand_env_save(*fnamep);
18356 vim_free(*bufp); /* free any allocated file name */
18357 *bufp = *fnamep;
18358 if (*fnamep == NULL)
18359 return -1;
18360 }
18361
18362 /* When "/." or "/.." is used: force expansion to get rid of it. */
Bram Moolenaar1cd871b2004-12-19 22:46:22 +000018363 for (p = *fnamep; *p != NUL; mb_ptr_adv(p))
Bram Moolenaar071d4272004-06-13 20:20:40 +000018364 {
18365 if (vim_ispathsep(*p)
18366 && p[1] == '.'
18367 && (p[2] == NUL
18368 || vim_ispathsep(p[2])
18369 || (p[2] == '.'
18370 && (p[3] == NUL || vim_ispathsep(p[3])))))
18371 break;
18372 }
18373
18374 /* FullName_save() is slow, don't use it when not needed. */
18375 if (*p != NUL || !vim_isAbsName(*fnamep))
18376 {
18377 *fnamep = FullName_save(*fnamep, *p != NUL);
18378 vim_free(*bufp); /* free any allocated file name */
18379 *bufp = *fnamep;
18380 if (*fnamep == NULL)
18381 return -1;
18382 }
18383
18384 /* Append a path separator to a directory. */
18385 if (mch_isdir(*fnamep))
18386 {
18387 /* Make room for one or two extra characters. */
18388 *fnamep = vim_strnsave(*fnamep, (int)STRLEN(*fnamep) + 2);
18389 vim_free(*bufp); /* free any allocated file name */
18390 *bufp = *fnamep;
18391 if (*fnamep == NULL)
18392 return -1;
18393 add_pathsep(*fnamep);
18394 }
18395 }
18396
18397 /* ":." - path relative to the current directory */
18398 /* ":~" - path relative to the home directory */
18399 /* ":8" - shortname path - postponed till after */
18400 while (src[*usedlen] == ':'
18401 && ((c = src[*usedlen + 1]) == '.' || c == '~' || c == '8'))
18402 {
18403 *usedlen += 2;
18404 if (c == '8')
18405 {
18406#ifdef WIN3264
18407 has_shortname = 1; /* Postpone this. */
18408#endif
18409 continue;
18410 }
18411 pbuf = NULL;
18412 /* Need full path first (use expand_env() to remove a "~/") */
18413 if (!has_fullname)
18414 {
18415 if (c == '.' && **fnamep == '~')
18416 p = pbuf = expand_env_save(*fnamep);
18417 else
18418 p = pbuf = FullName_save(*fnamep, FALSE);
18419 }
18420 else
18421 p = *fnamep;
18422
18423 has_fullname = 0;
18424
18425 if (p != NULL)
18426 {
18427 if (c == '.')
18428 {
18429 mch_dirname(dirname, MAXPATHL);
18430 s = shorten_fname(p, dirname);
18431 if (s != NULL)
18432 {
18433 *fnamep = s;
18434 if (pbuf != NULL)
18435 {
18436 vim_free(*bufp); /* free any allocated file name */
18437 *bufp = pbuf;
18438 pbuf = NULL;
18439 }
18440 }
18441 }
18442 else
18443 {
18444 home_replace(NULL, p, dirname, MAXPATHL, TRUE);
18445 /* Only replace it when it starts with '~' */
18446 if (*dirname == '~')
18447 {
18448 s = vim_strsave(dirname);
18449 if (s != NULL)
18450 {
18451 *fnamep = s;
18452 vim_free(*bufp);
18453 *bufp = s;
18454 }
18455 }
18456 }
18457 vim_free(pbuf);
18458 }
18459 }
18460
18461 tail = gettail(*fnamep);
18462 *fnamelen = (int)STRLEN(*fnamep);
18463
18464 /* ":h" - head, remove "/file_name", can be repeated */
18465 /* Don't remove the first "/" or "c:\" */
18466 while (src[*usedlen] == ':' && src[*usedlen + 1] == 'h')
18467 {
18468 valid |= VALID_HEAD;
18469 *usedlen += 2;
18470 s = get_past_head(*fnamep);
Bram Moolenaar1cd871b2004-12-19 22:46:22 +000018471 while (tail > s && after_pathsep(s, tail))
Bram Moolenaar071d4272004-06-13 20:20:40 +000018472 --tail;
18473 *fnamelen = (int)(tail - *fnamep);
18474#ifdef VMS
18475 if (*fnamelen > 0)
18476 *fnamelen += 1; /* the path separator is part of the path */
18477#endif
Bram Moolenaar1cd871b2004-12-19 22:46:22 +000018478 while (tail > s && !after_pathsep(s, tail))
18479 mb_ptr_back(*fnamep, tail);
Bram Moolenaar071d4272004-06-13 20:20:40 +000018480 }
18481
18482 /* ":8" - shortname */
18483 if (src[*usedlen] == ':' && src[*usedlen + 1] == '8')
18484 {
18485 *usedlen += 2;
18486#ifdef WIN3264
18487 has_shortname = 1;
18488#endif
18489 }
18490
18491#ifdef WIN3264
18492 /* Check shortname after we have done 'heads' and before we do 'tails'
18493 */
18494 if (has_shortname)
18495 {
18496 pbuf = NULL;
18497 /* Copy the string if it is shortened by :h */
18498 if (*fnamelen < (int)STRLEN(*fnamep))
18499 {
18500 p = vim_strnsave(*fnamep, *fnamelen);
18501 if (p == 0)
18502 return -1;
18503 vim_free(*bufp);
18504 *bufp = *fnamep = p;
18505 }
18506
18507 /* Split into two implementations - makes it easier. First is where
18508 * there isn't a full name already, second is where there is.
18509 */
18510 if (!has_fullname && !vim_isAbsName(*fnamep))
18511 {
18512 if (shortpath_for_partial(fnamep, bufp, fnamelen) == -1)
18513 return -1;
18514 }
18515 else
18516 {
18517 int l;
18518
18519 /* Simple case, already have the full-name
18520 * Nearly always shorter, so try first time. */
18521 l = *fnamelen;
18522 if (!get_short_pathname(fnamep, bufp, &l))
18523 return -1;
18524
18525 if (l == 0)
18526 {
18527 /* Couldn't find the filename.. search the paths.
18528 */
18529 l = *fnamelen;
18530 if (shortpath_for_invalid_fname(fnamep, bufp, &l ) == -1)
18531 return -1;
18532 }
18533 *fnamelen = l;
18534 }
18535 }
18536#endif /* WIN3264 */
18537
18538 /* ":t" - tail, just the basename */
18539 if (src[*usedlen] == ':' && src[*usedlen + 1] == 't')
18540 {
18541 *usedlen += 2;
18542 *fnamelen -= (int)(tail - *fnamep);
18543 *fnamep = tail;
18544 }
18545
18546 /* ":e" - extension, can be repeated */
18547 /* ":r" - root, without extension, can be repeated */
18548 while (src[*usedlen] == ':'
18549 && (src[*usedlen + 1] == 'e' || src[*usedlen + 1] == 'r'))
18550 {
18551 /* find a '.' in the tail:
18552 * - for second :e: before the current fname
18553 * - otherwise: The last '.'
18554 */
18555 if (src[*usedlen + 1] == 'e' && *fnamep > tail)
18556 s = *fnamep - 2;
18557 else
18558 s = *fnamep + *fnamelen - 1;
18559 for ( ; s > tail; --s)
18560 if (s[0] == '.')
18561 break;
18562 if (src[*usedlen + 1] == 'e') /* :e */
18563 {
18564 if (s > tail)
18565 {
18566 *fnamelen += (int)(*fnamep - (s + 1));
18567 *fnamep = s + 1;
18568#ifdef VMS
18569 /* cut version from the extension */
18570 s = *fnamep + *fnamelen - 1;
18571 for ( ; s > *fnamep; --s)
18572 if (s[0] == ';')
18573 break;
18574 if (s > *fnamep)
18575 *fnamelen = s - *fnamep;
18576#endif
18577 }
18578 else if (*fnamep <= tail)
18579 *fnamelen = 0;
18580 }
18581 else /* :r */
18582 {
18583 if (s > tail) /* remove one extension */
18584 *fnamelen = (int)(s - *fnamep);
18585 }
18586 *usedlen += 2;
18587 }
18588
18589 /* ":s?pat?foo?" - substitute */
18590 /* ":gs?pat?foo?" - global substitute */
18591 if (src[*usedlen] == ':'
18592 && (src[*usedlen + 1] == 's'
18593 || (src[*usedlen + 1] == 'g' && src[*usedlen + 2] == 's')))
18594 {
18595 char_u *str;
18596 char_u *pat;
18597 char_u *sub;
18598 int sep;
18599 char_u *flags;
18600 int didit = FALSE;
18601
18602 flags = (char_u *)"";
18603 s = src + *usedlen + 2;
18604 if (src[*usedlen + 1] == 'g')
18605 {
18606 flags = (char_u *)"g";
18607 ++s;
18608 }
18609
18610 sep = *s++;
18611 if (sep)
18612 {
18613 /* find end of pattern */
18614 p = vim_strchr(s, sep);
18615 if (p != NULL)
18616 {
18617 pat = vim_strnsave(s, (int)(p - s));
18618 if (pat != NULL)
18619 {
18620 s = p + 1;
18621 /* find end of substitution */
18622 p = vim_strchr(s, sep);
18623 if (p != NULL)
18624 {
18625 sub = vim_strnsave(s, (int)(p - s));
18626 str = vim_strnsave(*fnamep, *fnamelen);
18627 if (sub != NULL && str != NULL)
18628 {
18629 *usedlen = (int)(p + 1 - src);
18630 s = do_string_sub(str, pat, sub, flags);
18631 if (s != NULL)
18632 {
18633 *fnamep = s;
18634 *fnamelen = (int)STRLEN(s);
18635 vim_free(*bufp);
18636 *bufp = s;
18637 didit = TRUE;
18638 }
18639 }
18640 vim_free(sub);
18641 vim_free(str);
18642 }
18643 vim_free(pat);
18644 }
18645 }
18646 /* after using ":s", repeat all the modifiers */
18647 if (didit)
18648 goto repeat;
18649 }
18650 }
18651
18652 return valid;
18653}
18654
18655/*
18656 * Perform a substitution on "str" with pattern "pat" and substitute "sub".
18657 * "flags" can be "g" to do a global substitute.
18658 * Returns an allocated string, NULL for error.
18659 */
18660 char_u *
18661do_string_sub(str, pat, sub, flags)
18662 char_u *str;
18663 char_u *pat;
18664 char_u *sub;
18665 char_u *flags;
18666{
18667 int sublen;
18668 regmatch_T regmatch;
18669 int i;
18670 int do_all;
18671 char_u *tail;
18672 garray_T ga;
18673 char_u *ret;
18674 char_u *save_cpo;
18675
18676 /* Make 'cpoptions' empty, so that the 'l' flag doesn't work here */
18677 save_cpo = p_cpo;
18678 p_cpo = (char_u *)"";
18679
18680 ga_init2(&ga, 1, 200);
18681
18682 do_all = (flags[0] == 'g');
18683
18684 regmatch.rm_ic = p_ic;
18685 regmatch.regprog = vim_regcomp(pat, RE_MAGIC + RE_STRING);
18686 if (regmatch.regprog != NULL)
18687 {
18688 tail = str;
18689 while (vim_regexec_nl(&regmatch, str, (colnr_T)(tail - str)))
18690 {
18691 /*
18692 * Get some space for a temporary buffer to do the substitution
18693 * into. It will contain:
18694 * - The text up to where the match is.
18695 * - The substituted text.
18696 * - The text after the match.
18697 */
18698 sublen = vim_regsub(&regmatch, sub, tail, FALSE, TRUE, FALSE);
18699 if (ga_grow(&ga, (int)(STRLEN(tail) + sublen -
18700 (regmatch.endp[0] - regmatch.startp[0]))) == FAIL)
18701 {
18702 ga_clear(&ga);
18703 break;
18704 }
18705
18706 /* copy the text up to where the match is */
18707 i = (int)(regmatch.startp[0] - tail);
18708 mch_memmove((char_u *)ga.ga_data + ga.ga_len, tail, (size_t)i);
18709 /* add the substituted text */
18710 (void)vim_regsub(&regmatch, sub, (char_u *)ga.ga_data
18711 + ga.ga_len + i, TRUE, TRUE, FALSE);
18712 ga.ga_len += i + sublen - 1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000018713 /* avoid getting stuck on a match with an empty string */
18714 if (tail == regmatch.endp[0])
18715 {
18716 if (*tail == NUL)
18717 break;
18718 *((char_u *)ga.ga_data + ga.ga_len) = *tail++;
18719 ++ga.ga_len;
Bram Moolenaar071d4272004-06-13 20:20:40 +000018720 }
18721 else
18722 {
18723 tail = regmatch.endp[0];
18724 if (*tail == NUL)
18725 break;
18726 }
18727 if (!do_all)
18728 break;
18729 }
18730
18731 if (ga.ga_data != NULL)
18732 STRCPY((char *)ga.ga_data + ga.ga_len, tail);
18733
18734 vim_free(regmatch.regprog);
18735 }
18736
18737 ret = vim_strsave(ga.ga_data == NULL ? str : (char_u *)ga.ga_data);
18738 ga_clear(&ga);
18739 p_cpo = save_cpo;
18740
18741 return ret;
18742}
18743
18744#endif /* defined(FEAT_MODIFY_FNAME) || defined(FEAT_EVAL) */