blob: bde12e56e16615f7d2ccd050a5839221a4db479b [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 Moolenaare9a41262005-01-15 22:18:47 +000098static char *e_listdictarg = N_("E712: Argument of %s must be a List or Dictionaary");
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 Moolenaar49cd9572005-01-03 21:06:01 +0000110
111/*
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 */
123hashtab_T compat_hashtab;
124
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 Moolenaar5313dcb2005-02-22 08:56:13 +0000191hashtab_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
267#define VV_NAME(s, t) s, sizeof(s) - 1, {{t}}, {0}
268
269static struct vimvar
270{
271 char *vv_name; /* name of variable, without v: */
272 int vv_len; /* length of name */
273 dictitem_T vv_di; /* value and name for key */
274 char vv_filler[16]; /* space for LONGEST name below!!! */
275 char vv_flags; /* VV_COMPAT, VV_RO, VV_RO_SBX */
276} vimvars[VV_LEN] =
277{
278 /*
279 * The order here must match the VV_ defines in vim.h!
280 * Initializing a union does not work, leave tv.vval empty to get zero's.
281 */
282 {VV_NAME("count", VAR_NUMBER), VV_COMPAT+VV_RO},
283 {VV_NAME("count1", VAR_NUMBER), VV_RO},
284 {VV_NAME("prevcount", VAR_NUMBER), VV_RO},
285 {VV_NAME("errmsg", VAR_STRING), VV_COMPAT},
286 {VV_NAME("warningmsg", VAR_STRING), 0},
287 {VV_NAME("statusmsg", VAR_STRING), 0},
288 {VV_NAME("shell_error", VAR_NUMBER), VV_COMPAT+VV_RO},
289 {VV_NAME("this_session", VAR_STRING), VV_COMPAT},
290 {VV_NAME("version", VAR_NUMBER), VV_COMPAT+VV_RO},
291 {VV_NAME("lnum", VAR_NUMBER), VV_RO_SBX},
292 {VV_NAME("termresponse", VAR_STRING), VV_RO},
293 {VV_NAME("fname", VAR_STRING), VV_RO},
294 {VV_NAME("lang", VAR_STRING), VV_RO},
295 {VV_NAME("lc_time", VAR_STRING), VV_RO},
296 {VV_NAME("ctype", VAR_STRING), VV_RO},
297 {VV_NAME("charconvert_from", VAR_STRING), VV_RO},
298 {VV_NAME("charconvert_to", VAR_STRING), VV_RO},
299 {VV_NAME("fname_in", VAR_STRING), VV_RO},
300 {VV_NAME("fname_out", VAR_STRING), VV_RO},
301 {VV_NAME("fname_new", VAR_STRING), VV_RO},
302 {VV_NAME("fname_diff", VAR_STRING), VV_RO},
303 {VV_NAME("cmdarg", VAR_STRING), VV_RO},
304 {VV_NAME("foldstart", VAR_NUMBER), VV_RO_SBX},
305 {VV_NAME("foldend", VAR_NUMBER), VV_RO_SBX},
306 {VV_NAME("folddashes", VAR_STRING), VV_RO_SBX},
307 {VV_NAME("foldlevel", VAR_NUMBER), VV_RO_SBX},
308 {VV_NAME("progname", VAR_STRING), VV_RO},
309 {VV_NAME("servername", VAR_STRING), VV_RO},
310 {VV_NAME("dying", VAR_NUMBER), VV_RO},
311 {VV_NAME("exception", VAR_STRING), VV_RO},
312 {VV_NAME("throwpoint", VAR_STRING), VV_RO},
313 {VV_NAME("register", VAR_STRING), VV_RO},
314 {VV_NAME("cmdbang", VAR_NUMBER), VV_RO},
315 {VV_NAME("insertmode", VAR_STRING), VV_RO},
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +0000316 {VV_NAME("val", VAR_UNKNOWN), VV_RO},
317 {VV_NAME("key", VAR_UNKNOWN), VV_RO},
Bram Moolenaar05159a02005-02-26 23:04:13 +0000318 {VV_NAME("profiling", VAR_NUMBER), VV_RO},
Bram Moolenaar33570922005-01-25 22:26:29 +0000319};
320
321/* shorthand */
322#define vv_type vv_di.di_tv.v_type
323#define vv_nr vv_di.di_tv.vval.v_number
324#define vv_str vv_di.di_tv.vval.v_string
325#define vv_tv vv_di.di_tv
326
327/*
328 * The v: variables are stored in dictionary "vimvardict".
329 * "vimvars_var" is the variable that is used for the "l:" scope.
330 */
331static dict_T vimvardict;
332static dictitem_T vimvars_var;
333#define vimvarht vimvardict.dv_hashtab
334
335static int eval0 __ARGS((char_u *arg, typval_T *rettv, char_u **nextcmd, int evaluate));
336static int eval1 __ARGS((char_u **arg, typval_T *rettv, int evaluate));
337static int eval2 __ARGS((char_u **arg, typval_T *rettv, int evaluate));
338static int eval3 __ARGS((char_u **arg, typval_T *rettv, int evaluate));
339static int eval4 __ARGS((char_u **arg, typval_T *rettv, int evaluate));
340static int eval5 __ARGS((char_u **arg, typval_T *rettv, int evaluate));
341static int eval6 __ARGS((char_u **arg, typval_T *rettv, int evaluate));
342static int eval7 __ARGS((char_u **arg, typval_T *rettv, int evaluate));
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +0000343static int eval_index __ARGS((char_u **arg, typval_T *rettv, int evaluate, int verbose));
Bram Moolenaar33570922005-01-25 22:26:29 +0000344static int get_option_tv __ARGS((char_u **arg, typval_T *rettv, int evaluate));
345static int get_string_tv __ARGS((char_u **arg, typval_T *rettv, int evaluate));
346static int get_lit_string_tv __ARGS((char_u **arg, typval_T *rettv, int evaluate));
347static int get_list_tv __ARGS((char_u **arg, typval_T *rettv, int evaluate));
348static list_T *list_alloc __ARGS((void));
349static void list_unref __ARGS((list_T *l));
350static void list_free __ARGS((list_T *l));
351static listitem_T *listitem_alloc __ARGS((void));
352static void listitem_free __ARGS((listitem_T *item));
353static void listitem_remove __ARGS((list_T *l, listitem_T *item));
354static long list_len __ARGS((list_T *l));
355static int list_equal __ARGS((list_T *l1, list_T *l2, int ic));
356static int dict_equal __ARGS((dict_T *d1, dict_T *d2, int ic));
357static int tv_equal __ARGS((typval_T *tv1, typval_T *tv2, int ic));
358static int string_isa_number __ARGS((char_u *s));
359static listitem_T *list_find __ARGS((list_T *l, long n));
360static long list_idx_of_item __ARGS((list_T *l, listitem_T *item));
Bram Moolenaar33570922005-01-25 22:26:29 +0000361static void list_append __ARGS((list_T *l, listitem_T *item));
362static int list_append_tv __ARGS((list_T *l, typval_T *tv));
363static int list_insert_tv __ARGS((list_T *l, typval_T *tv, listitem_T *item));
364static int list_extend __ARGS((list_T *l1, list_T *l2, listitem_T *bef));
365static int list_concat __ARGS((list_T *l1, list_T *l2, typval_T *tv));
Bram Moolenaar81bf7082005-02-12 14:31:42 +0000366static list_T *list_copy __ARGS((list_T *orig, int deep, int copyID));
Bram Moolenaar33570922005-01-25 22:26:29 +0000367static void list_remove __ARGS((list_T *l, listitem_T *item, listitem_T *item2));
368static char_u *list2string __ARGS((typval_T *tv));
Bram Moolenaar81bf7082005-02-12 14:31:42 +0000369static int list_join __ARGS((garray_T *gap, list_T *l, char_u *sep, int echo));
Bram Moolenaar33570922005-01-25 22:26:29 +0000370
Bram Moolenaar33570922005-01-25 22:26:29 +0000371static void dict_unref __ARGS((dict_T *d));
372static void dict_free __ARGS((dict_T *d));
373static dictitem_T *dictitem_alloc __ARGS((char_u *key));
374static dictitem_T *dictitem_copy __ARGS((dictitem_T *org));
375static void dictitem_remove __ARGS((dict_T *dict, dictitem_T *item));
376static void dictitem_free __ARGS((dictitem_T *item));
Bram Moolenaar81bf7082005-02-12 14:31:42 +0000377static dict_T *dict_copy __ARGS((dict_T *orig, int deep, int copyID));
Bram Moolenaar33570922005-01-25 22:26:29 +0000378static int dict_add __ARGS((dict_T *d, dictitem_T *item));
379static long dict_len __ARGS((dict_T *d));
380static dictitem_T *dict_find __ARGS((dict_T *d, char_u *key, int len));
381static char_u *dict2string __ARGS((typval_T *tv));
382static int get_dict_tv __ARGS((char_u **arg, typval_T *rettv, int evaluate));
383
384static char_u *echo_string __ARGS((typval_T *tv, char_u **tofree, char_u *numbuf));
385static char_u *tv2string __ARGS((typval_T *tv, char_u **tofree, char_u *numbuf));
386static char_u *string_quote __ARGS((char_u *str, int function));
387static int get_env_tv __ARGS((char_u **arg, typval_T *rettv, int evaluate));
388static int find_internal_func __ARGS((char_u *name));
389static char_u *deref_func_name __ARGS((char_u *name, int *lenp));
390static 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));
391static 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 +0000392static void emsg_funcname __ARGS((char *msg, char_u *name));
Bram Moolenaar33570922005-01-25 22:26:29 +0000393
394static void f_add __ARGS((typval_T *argvars, typval_T *rettv));
395static void f_append __ARGS((typval_T *argvars, typval_T *rettv));
396static void f_argc __ARGS((typval_T *argvars, typval_T *rettv));
397static void f_argidx __ARGS((typval_T *argvars, typval_T *rettv));
398static void f_argv __ARGS((typval_T *argvars, typval_T *rettv));
399static void f_browse __ARGS((typval_T *argvars, typval_T *rettv));
400static void f_browsedir __ARGS((typval_T *argvars, typval_T *rettv));
401static void f_bufexists __ARGS((typval_T *argvars, typval_T *rettv));
402static void f_buflisted __ARGS((typval_T *argvars, typval_T *rettv));
403static void f_bufloaded __ARGS((typval_T *argvars, typval_T *rettv));
404static void f_bufname __ARGS((typval_T *argvars, typval_T *rettv));
405static void f_bufnr __ARGS((typval_T *argvars, typval_T *rettv));
406static void f_bufwinnr __ARGS((typval_T *argvars, typval_T *rettv));
407static void f_byte2line __ARGS((typval_T *argvars, typval_T *rettv));
408static void f_byteidx __ARGS((typval_T *argvars, typval_T *rettv));
409static void f_call __ARGS((typval_T *argvars, typval_T *rettv));
410static void f_char2nr __ARGS((typval_T *argvars, typval_T *rettv));
411static void f_cindent __ARGS((typval_T *argvars, typval_T *rettv));
412static void f_col __ARGS((typval_T *argvars, typval_T *rettv));
413static void f_confirm __ARGS((typval_T *argvars, typval_T *rettv));
414static void f_copy __ARGS((typval_T *argvars, typval_T *rettv));
415static void f_count __ARGS((typval_T *argvars, typval_T *rettv));
416static void f_cscope_connection __ARGS((typval_T *argvars, typval_T *rettv));
417static void f_cursor __ARGS((typval_T *argsvars, typval_T *rettv));
418static void f_deepcopy __ARGS((typval_T *argvars, typval_T *rettv));
419static void f_delete __ARGS((typval_T *argvars, typval_T *rettv));
420static void f_did_filetype __ARGS((typval_T *argvars, typval_T *rettv));
421static void f_diff_filler __ARGS((typval_T *argvars, typval_T *rettv));
422static void f_diff_hlID __ARGS((typval_T *argvars, typval_T *rettv));
423static void f_empty __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar05159a02005-02-26 23:04:13 +0000424static void f_errorlist __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar33570922005-01-25 22:26:29 +0000425static void f_escape __ARGS((typval_T *argvars, typval_T *rettv));
426static void f_eval __ARGS((typval_T *argvars, typval_T *rettv));
427static void f_eventhandler __ARGS((typval_T *argvars, typval_T *rettv));
428static void f_executable __ARGS((typval_T *argvars, typval_T *rettv));
429static void f_exists __ARGS((typval_T *argvars, typval_T *rettv));
430static void f_expand __ARGS((typval_T *argvars, typval_T *rettv));
431static void f_extend __ARGS((typval_T *argvars, typval_T *rettv));
432static void f_filereadable __ARGS((typval_T *argvars, typval_T *rettv));
433static void f_filewritable __ARGS((typval_T *argvars, typval_T *rettv));
434static void f_filter __ARGS((typval_T *argvars, typval_T *rettv));
435static void f_finddir __ARGS((typval_T *argvars, typval_T *rettv));
436static void f_findfile __ARGS((typval_T *argvars, typval_T *rettv));
437static void f_fnamemodify __ARGS((typval_T *argvars, typval_T *rettv));
438static void f_foldclosed __ARGS((typval_T *argvars, typval_T *rettv));
439static void f_foldclosedend __ARGS((typval_T *argvars, typval_T *rettv));
440static void f_foldlevel __ARGS((typval_T *argvars, typval_T *rettv));
441static void f_foldtext __ARGS((typval_T *argvars, typval_T *rettv));
442static void f_foldtextresult __ARGS((typval_T *argvars, typval_T *rettv));
443static void f_foreground __ARGS((typval_T *argvars, typval_T *rettv));
444static void f_function __ARGS((typval_T *argvars, typval_T *rettv));
445static void f_get __ARGS((typval_T *argvars, typval_T *rettv));
446static void f_getbufvar __ARGS((typval_T *argvars, typval_T *rettv));
447static void f_getchar __ARGS((typval_T *argvars, typval_T *rettv));
448static void f_getcharmod __ARGS((typval_T *argvars, typval_T *rettv));
449static void f_getcmdline __ARGS((typval_T *argvars, typval_T *rettv));
450static void f_getcmdpos __ARGS((typval_T *argvars, typval_T *rettv));
451static void f_getcwd __ARGS((typval_T *argvars, typval_T *rettv));
452static void f_getfontname __ARGS((typval_T *argvars, typval_T *rettv));
453static void f_getfperm __ARGS((typval_T *argvars, typval_T *rettv));
454static void f_getfsize __ARGS((typval_T *argvars, typval_T *rettv));
455static void f_getftime __ARGS((typval_T *argvars, typval_T *rettv));
456static void f_getftype __ARGS((typval_T *argvars, typval_T *rettv));
457static void f_getline __ARGS((typval_T *argvars, typval_T *rettv));
458static void f_getreg __ARGS((typval_T *argvars, typval_T *rettv));
459static void f_getregtype __ARGS((typval_T *argvars, typval_T *rettv));
460static void f_getwinposx __ARGS((typval_T *argvars, typval_T *rettv));
461static void f_getwinposy __ARGS((typval_T *argvars, typval_T *rettv));
462static void f_getwinvar __ARGS((typval_T *argvars, typval_T *rettv));
463static void f_glob __ARGS((typval_T *argvars, typval_T *rettv));
464static void f_globpath __ARGS((typval_T *argvars, typval_T *rettv));
465static void f_has __ARGS((typval_T *argvars, typval_T *rettv));
466static void f_has_key __ARGS((typval_T *argvars, typval_T *rettv));
467static void f_hasmapto __ARGS((typval_T *argvars, typval_T *rettv));
468static void f_histadd __ARGS((typval_T *argvars, typval_T *rettv));
469static void f_histdel __ARGS((typval_T *argvars, typval_T *rettv));
470static void f_histget __ARGS((typval_T *argvars, typval_T *rettv));
471static void f_histnr __ARGS((typval_T *argvars, typval_T *rettv));
472static void f_hlID __ARGS((typval_T *argvars, typval_T *rettv));
473static void f_hlexists __ARGS((typval_T *argvars, typval_T *rettv));
474static void f_hostname __ARGS((typval_T *argvars, typval_T *rettv));
475static void f_iconv __ARGS((typval_T *argvars, typval_T *rettv));
476static void f_indent __ARGS((typval_T *argvars, typval_T *rettv));
477static void f_index __ARGS((typval_T *argvars, typval_T *rettv));
478static void f_input __ARGS((typval_T *argvars, typval_T *rettv));
479static void f_inputdialog __ARGS((typval_T *argvars, typval_T *rettv));
480static void f_inputrestore __ARGS((typval_T *argvars, typval_T *rettv));
481static void f_inputsave __ARGS((typval_T *argvars, typval_T *rettv));
482static void f_inputsecret __ARGS((typval_T *argvars, typval_T *rettv));
483static void f_insert __ARGS((typval_T *argvars, typval_T *rettv));
484static void f_isdirectory __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar2e6aff32005-01-31 19:25:36 +0000485static void f_islocked __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar33570922005-01-25 22:26:29 +0000486static void f_items __ARGS((typval_T *argvars, typval_T *rettv));
487static void f_join __ARGS((typval_T *argvars, typval_T *rettv));
488static void f_keys __ARGS((typval_T *argvars, typval_T *rettv));
489static void f_last_buffer_nr __ARGS((typval_T *argvars, typval_T *rettv));
490static void f_len __ARGS((typval_T *argvars, typval_T *rettv));
491static void f_libcall __ARGS((typval_T *argvars, typval_T *rettv));
492static void f_libcallnr __ARGS((typval_T *argvars, typval_T *rettv));
493static void f_line __ARGS((typval_T *argvars, typval_T *rettv));
494static void f_line2byte __ARGS((typval_T *argvars, typval_T *rettv));
495static void f_lispindent __ARGS((typval_T *argvars, typval_T *rettv));
496static void f_localtime __ARGS((typval_T *argvars, typval_T *rettv));
497static void f_map __ARGS((typval_T *argvars, typval_T *rettv));
498static void f_maparg __ARGS((typval_T *argvars, typval_T *rettv));
499static void f_mapcheck __ARGS((typval_T *argvars, typval_T *rettv));
500static void f_match __ARGS((typval_T *argvars, typval_T *rettv));
501static void f_matchend __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +0000502static void f_matchlist __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar33570922005-01-25 22:26:29 +0000503static void f_matchstr __ARGS((typval_T *argvars, typval_T *rettv));
504static void f_max __ARGS((typval_T *argvars, typval_T *rettv));
505static void f_min __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000506#ifdef vim_mkdir
507static void f_mkdir __ARGS((typval_T *argvars, typval_T *rettv));
508#endif
Bram Moolenaar33570922005-01-25 22:26:29 +0000509static void f_mode __ARGS((typval_T *argvars, typval_T *rettv));
510static void f_nextnonblank __ARGS((typval_T *argvars, typval_T *rettv));
511static void f_nr2char __ARGS((typval_T *argvars, typval_T *rettv));
512static void f_prevnonblank __ARGS((typval_T *argvars, typval_T *rettv));
513static void f_range __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +0000514static void f_readfile __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar33570922005-01-25 22:26:29 +0000515static void f_remote_expr __ARGS((typval_T *argvars, typval_T *rettv));
516static void f_remote_foreground __ARGS((typval_T *argvars, typval_T *rettv));
517static void f_remote_peek __ARGS((typval_T *argvars, typval_T *rettv));
518static void f_remote_read __ARGS((typval_T *argvars, typval_T *rettv));
519static void f_remote_send __ARGS((typval_T *argvars, typval_T *rettv));
520static void f_remove __ARGS((typval_T *argvars, typval_T *rettv));
521static void f_rename __ARGS((typval_T *argvars, typval_T *rettv));
522static void f_repeat __ARGS((typval_T *argvars, typval_T *rettv));
523static void f_resolve __ARGS((typval_T *argvars, typval_T *rettv));
524static void f_reverse __ARGS((typval_T *argvars, typval_T *rettv));
525static void f_search __ARGS((typval_T *argvars, typval_T *rettv));
526static void f_searchpair __ARGS((typval_T *argvars, typval_T *rettv));
527static void f_server2client __ARGS((typval_T *argvars, typval_T *rettv));
528static void f_serverlist __ARGS((typval_T *argvars, typval_T *rettv));
529static void f_setbufvar __ARGS((typval_T *argvars, typval_T *rettv));
530static void f_setcmdpos __ARGS((typval_T *argvars, typval_T *rettv));
531static void f_setline __ARGS((typval_T *argvars, typval_T *rettv));
532static void f_setreg __ARGS((typval_T *argvars, typval_T *rettv));
533static void f_setwinvar __ARGS((typval_T *argvars, typval_T *rettv));
534static void f_simplify __ARGS((typval_T *argvars, typval_T *rettv));
535static void f_sort __ARGS((typval_T *argvars, typval_T *rettv));
536static void f_split __ARGS((typval_T *argvars, typval_T *rettv));
537#ifdef HAVE_STRFTIME
538static void f_strftime __ARGS((typval_T *argvars, typval_T *rettv));
539#endif
540static void f_stridx __ARGS((typval_T *argvars, typval_T *rettv));
541static void f_string __ARGS((typval_T *argvars, typval_T *rettv));
542static void f_strlen __ARGS((typval_T *argvars, typval_T *rettv));
543static void f_strpart __ARGS((typval_T *argvars, typval_T *rettv));
544static void f_strridx __ARGS((typval_T *argvars, typval_T *rettv));
545static void f_strtrans __ARGS((typval_T *argvars, typval_T *rettv));
546static void f_submatch __ARGS((typval_T *argvars, typval_T *rettv));
547static void f_substitute __ARGS((typval_T *argvars, typval_T *rettv));
548static void f_synID __ARGS((typval_T *argvars, typval_T *rettv));
549static void f_synIDattr __ARGS((typval_T *argvars, typval_T *rettv));
550static void f_synIDtrans __ARGS((typval_T *argvars, typval_T *rettv));
551static void f_system __ARGS((typval_T *argvars, typval_T *rettv));
552static void f_tempname __ARGS((typval_T *argvars, typval_T *rettv));
553static void f_tolower __ARGS((typval_T *argvars, typval_T *rettv));
554static void f_toupper __ARGS((typval_T *argvars, typval_T *rettv));
555static void f_tr __ARGS((typval_T *argvars, typval_T *rettv));
556static void f_type __ARGS((typval_T *argvars, typval_T *rettv));
557static void f_values __ARGS((typval_T *argvars, typval_T *rettv));
558static void f_virtcol __ARGS((typval_T *argvars, typval_T *rettv));
559static void f_visualmode __ARGS((typval_T *argvars, typval_T *rettv));
560static void f_winbufnr __ARGS((typval_T *argvars, typval_T *rettv));
561static void f_wincol __ARGS((typval_T *argvars, typval_T *rettv));
562static void f_winheight __ARGS((typval_T *argvars, typval_T *rettv));
563static void f_winline __ARGS((typval_T *argvars, typval_T *rettv));
564static void f_winnr __ARGS((typval_T *argvars, typval_T *rettv));
565static void f_winrestcmd __ARGS((typval_T *argvars, typval_T *rettv));
566static void f_winwidth __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +0000567static void f_writefile __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar33570922005-01-25 22:26:29 +0000568
569static win_T *find_win_by_nr __ARGS((typval_T *vp));
570static pos_T *var2fpos __ARGS((typval_T *varp, int lnum));
571static int get_env_len __ARGS((char_u **arg));
572static int get_id_len __ARGS((char_u **arg));
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +0000573static int get_name_len __ARGS((char_u **arg, char_u **alias, int evaluate, int verbose));
Bram Moolenaar33570922005-01-25 22:26:29 +0000574static char_u *find_name_end __ARGS((char_u *arg, char_u **expr_start, char_u **expr_end, int incl_br));
575static int eval_isnamec __ARGS((int c));
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +0000576static int get_var_tv __ARGS((char_u *name, int len, typval_T *rettv, int verbose));
577static int handle_subscript __ARGS((char_u **arg, typval_T *rettv, int evaluate, int verbose));
Bram Moolenaar33570922005-01-25 22:26:29 +0000578static typval_T *alloc_tv __ARGS((void));
579static typval_T *alloc_string_tv __ARGS((char_u *string));
580static void free_tv __ARGS((typval_T *varp));
581static void clear_tv __ARGS((typval_T *varp));
582static void init_tv __ARGS((typval_T *varp));
583static long get_tv_number __ARGS((typval_T *varp));
584static linenr_T get_tv_lnum __ARGS((typval_T *argvars));
585static char_u *get_tv_string __ARGS((typval_T *varp));
586static char_u *get_tv_string_buf __ARGS((typval_T *varp, char_u *buf));
587static dictitem_T *find_var __ARGS((char_u *name, hashtab_T **htp));
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000588static dictitem_T *find_var_in_ht __ARGS((hashtab_T *ht, char_u *varname, int writing));
Bram Moolenaar33570922005-01-25 22:26:29 +0000589static hashtab_T *find_var_ht __ARGS((char_u *name, char_u **varname));
590static void vars_clear_ext __ARGS((hashtab_T *ht, int free_val));
591static void delete_var __ARGS((hashtab_T *ht, hashitem_T *hi));
592static void list_one_var __ARGS((dictitem_T *v, char_u *prefix));
593static void list_one_var_a __ARGS((char_u *prefix, char_u *name, int type, char_u *string));
594static void set_var __ARGS((char_u *name, typval_T *varp, int copy));
595static int var_check_ro __ARGS((int flags, char_u *name));
Bram Moolenaar2e6aff32005-01-31 19:25:36 +0000596static int tv_check_lock __ARGS((int lock, char_u *name));
Bram Moolenaar33570922005-01-25 22:26:29 +0000597static void copy_tv __ARGS((typval_T *from, typval_T *to));
Bram Moolenaar81bf7082005-02-12 14:31:42 +0000598static int item_copy __ARGS((typval_T *from, typval_T *to, int deep, int copyID));
Bram Moolenaar33570922005-01-25 22:26:29 +0000599static char_u *find_option_end __ARGS((char_u **arg, int *opt_flags));
600static char_u *trans_function_name __ARGS((char_u **pp, int skip, int flags, funcdict_T *fd));
601static int eval_fname_script __ARGS((char_u *p));
602static int eval_fname_sid __ARGS((char_u *p));
603static void list_func_head __ARGS((ufunc_T *fp, int indent));
604static void cat_func_name __ARGS((char_u *buf, ufunc_T *fp));
605static ufunc_T *find_func __ARGS((char_u *name));
606static int function_exists __ARGS((char_u *name));
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +0000607static int builtin_function __ARGS((char_u *name));
Bram Moolenaar05159a02005-02-26 23:04:13 +0000608#ifdef FEAT_PROFILE
609static void func_do_profile __ARGS((ufunc_T *fp));
Bram Moolenaar73830342005-02-28 22:48:19 +0000610static void prof_sort_list __ARGS((FILE *fd, ufunc_T **sorttab, int st_len, char *title, int prefer_self));
611static void prof_func_line __ARGS((FILE *fd, int count, proftime_T *total, proftime_T *self, int prefer_self));
612static int
613# ifdef __BORLANDC__
614 _RTLENTRYF
615# endif
616 prof_total_cmp __ARGS((const void *s1, const void *s2));
617static int
618# ifdef __BORLANDC__
619 _RTLENTRYF
620# endif
621 prof_self_cmp __ARGS((const void *s1, const void *s2));
Bram Moolenaar05159a02005-02-26 23:04:13 +0000622#endif
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000623static int script_autoload __ARGS((char_u *name));
624static char_u *autoload_name __ARGS((char_u *name));
Bram Moolenaar33570922005-01-25 22:26:29 +0000625static void func_free __ARGS((ufunc_T *fp));
626static void func_unref __ARGS((char_u *name));
627static void func_ref __ARGS((char_u *name));
628static 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));
629static void add_nr_var __ARGS((dict_T *dp, dictitem_T *v, char *name, varnumber_T nr));
630
631static char_u * make_expanded_name __ARGS((char_u *in_start, char_u *expr_start, char_u *expr_end, char_u *in_end));
632
633static int ex_let_vars __ARGS((char_u *arg, typval_T *tv, int copy, int semicolon, int var_count, char_u *nextchars));
634static char_u *skip_var_list __ARGS((char_u *arg, int *var_count, int *semicolon));
635static char_u *skip_var_one __ARGS((char_u *arg));
636static void list_hashtable_vars __ARGS((hashtab_T *ht, char_u *prefix, int empty));
637static void list_glob_vars __ARGS((void));
638static void list_buf_vars __ARGS((void));
639static void list_win_vars __ARGS((void));
640static void list_vim_vars __ARGS((void));
641static char_u *list_arg_vars __ARGS((exarg_T *eap, char_u *arg));
642static char_u *ex_let_one __ARGS((char_u *arg, typval_T *tv, int copy, char_u *endchars, char_u *op));
643static int check_changedtick __ARGS((char_u *arg));
644static char_u *get_lval __ARGS((char_u *name, typval_T *rettv, lval_T *lp, int unlet, int skip, int quiet));
645static void clear_lval __ARGS((lval_T *lp));
646static void set_var_lval __ARGS((lval_T *lp, char_u *endp, typval_T *rettv, int copy, char_u *op));
647static int tv_op __ARGS((typval_T *tv1, typval_T *tv2, char_u *op));
648static void list_add_watch __ARGS((list_T *l, listwatch_T *lw));
649static void list_rem_watch __ARGS((list_T *l, listwatch_T *lwrem));
650static void list_fix_watch __ARGS((list_T *l, listitem_T *item));
Bram Moolenaar2e6aff32005-01-31 19:25:36 +0000651static void ex_unletlock __ARGS((exarg_T *eap, char_u *argstart, int deep));
Bram Moolenaar33570922005-01-25 22:26:29 +0000652static int do_unlet_var __ARGS((lval_T *lp, char_u *name_end, int forceit));
Bram Moolenaar2e6aff32005-01-31 19:25:36 +0000653static int do_lock_var __ARGS((lval_T *lp, char_u *name_end, int deep, int lock));
654static void item_lock __ARGS((typval_T *tv, int deep, int lock));
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000655static int tv_islocked __ARGS((typval_T *tv));
Bram Moolenaar33570922005-01-25 22:26:29 +0000656
657/*
658 * Initialize the global and v: variables.
Bram Moolenaara7043832005-01-21 11:56:39 +0000659 */
660 void
661eval_init()
662{
Bram Moolenaar33570922005-01-25 22:26:29 +0000663 int i;
664 struct vimvar *p;
665
666 init_var_dict(&globvardict, &globvars_var);
667 init_var_dict(&vimvardict, &vimvars_var);
Bram Moolenaar532c7802005-01-27 14:44:31 +0000668 hash_init(&compat_hashtab);
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000669 hash_init(&func_hashtab);
Bram Moolenaar33570922005-01-25 22:26:29 +0000670
671 for (i = 0; i < VV_LEN; ++i)
672 {
673 p = &vimvars[i];
674 STRCPY(p->vv_di.di_key, p->vv_name);
675 if (p->vv_flags & VV_RO)
676 p->vv_di.di_flags = DI_FLAGS_RO | DI_FLAGS_FIX;
677 else if (p->vv_flags & VV_RO_SBX)
678 p->vv_di.di_flags = DI_FLAGS_RO_SBX | DI_FLAGS_FIX;
679 else
680 p->vv_di.di_flags = DI_FLAGS_FIX;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +0000681
682 /* add to v: scope dict, unless the value is not always available */
683 if (p->vv_type != VAR_UNKNOWN)
684 hash_add(&vimvarht, p->vv_di.di_key);
Bram Moolenaar33570922005-01-25 22:26:29 +0000685 if (p->vv_flags & VV_COMPAT)
Bram Moolenaar532c7802005-01-27 14:44:31 +0000686 /* add to compat scope dict */
687 hash_add(&compat_hashtab, p->vv_di.di_key);
Bram Moolenaar33570922005-01-25 22:26:29 +0000688 }
Bram Moolenaara7043832005-01-21 11:56:39 +0000689}
690
Bram Moolenaar9ef486d2005-01-17 22:23:00 +0000691/*
Bram Moolenaar071d4272004-06-13 20:20:40 +0000692 * Return the name of the executed function.
693 */
694 char_u *
695func_name(cookie)
696 void *cookie;
697{
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000698 return ((funccall_T *)cookie)->func->uf_name;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000699}
700
701/*
702 * Return the address holding the next breakpoint line for a funccall cookie.
703 */
704 linenr_T *
705func_breakpoint(cookie)
706 void *cookie;
707{
Bram Moolenaar33570922005-01-25 22:26:29 +0000708 return &((funccall_T *)cookie)->breakpoint;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000709}
710
711/*
712 * Return the address holding the debug tick for a funccall cookie.
713 */
714 int *
715func_dbg_tick(cookie)
716 void *cookie;
717{
Bram Moolenaar33570922005-01-25 22:26:29 +0000718 return &((funccall_T *)cookie)->dbg_tick;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000719}
720
721/*
722 * Return the nesting level for a funccall cookie.
723 */
724 int
725func_level(cookie)
726 void *cookie;
727{
Bram Moolenaar33570922005-01-25 22:26:29 +0000728 return ((funccall_T *)cookie)->level;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000729}
730
731/* pointer to funccal for currently active function */
Bram Moolenaar33570922005-01-25 22:26:29 +0000732funccall_T *current_funccal = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000733
734/*
735 * Return TRUE when a function was ended by a ":return" command.
736 */
737 int
738current_func_returned()
739{
740 return current_funccal->returned;
741}
742
743
744/*
Bram Moolenaar071d4272004-06-13 20:20:40 +0000745 * Set an internal variable to a string value. Creates the variable if it does
746 * not already exist.
747 */
748 void
749set_internal_string_var(name, value)
750 char_u *name;
751 char_u *value;
752{
Bram Moolenaar49cd9572005-01-03 21:06:01 +0000753 char_u *val;
Bram Moolenaar33570922005-01-25 22:26:29 +0000754 typval_T *tvp;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000755
756 val = vim_strsave(value);
757 if (val != NULL)
758 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000759 tvp = alloc_string_tv(val);
Bram Moolenaar49cd9572005-01-03 21:06:01 +0000760 if (tvp != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000761 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +0000762 set_var(name, tvp, FALSE);
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000763 free_tv(tvp);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000764 }
765 }
766}
767
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000768static lval_T *redir_lval = NULL;
769static char_u *redir_endp = NULL;
770static char_u *redir_varname = NULL;
771
772/*
773 * Start recording command output to a variable
774 * Returns OK if successfully completed the setup. FAIL otherwise.
775 */
776 int
777var_redir_start(name, append)
778 char_u *name;
779 int append; /* append to an existing variable */
780{
781 int save_emsg;
782 int err;
783 typval_T tv;
784
785 /* Make sure a valid variable name is specified */
786 if (!eval_isnamec(*name) || VIM_ISDIGIT(*name))
787 {
788 EMSG(_(e_invarg));
789 return FAIL;
790 }
791
792 redir_varname = vim_strsave(name);
793 if (redir_varname == NULL)
794 return FAIL;
795
796 redir_lval = (lval_T *)alloc_clear((unsigned)sizeof(lval_T));
797 if (redir_lval == NULL)
798 {
799 var_redir_stop();
800 return FAIL;
801 }
802
803 /* Parse the variable name (can be a dict or list entry). */
804 redir_endp = get_lval(redir_varname, NULL, redir_lval, FALSE, FALSE, FALSE);
805 if (redir_endp == NULL || redir_lval->ll_name == NULL || *redir_endp != NUL)
806 {
807 if (redir_endp != NULL && *redir_endp != NUL)
808 /* Trailing characters are present after the variable name */
809 EMSG(_(e_trailing));
810 else
811 EMSG(_(e_invarg));
812 var_redir_stop();
813 return FAIL;
814 }
815
816 /* check if we can write to the variable: set it to or append an empty
817 * string */
818 save_emsg = did_emsg;
819 did_emsg = FALSE;
820 tv.v_type = VAR_STRING;
821 tv.vval.v_string = (char_u *)"";
822 if (append)
823 set_var_lval(redir_lval, redir_endp, &tv, TRUE, (char_u *)".");
824 else
825 set_var_lval(redir_lval, redir_endp, &tv, TRUE, (char_u *)"=");
826 err = did_emsg;
827 did_emsg += save_emsg;
828 if (err)
829 {
830 var_redir_stop();
831 return FAIL;
832 }
833 if (redir_lval->ll_newkey != NULL)
834 {
835 /* Dictionary item was created, don't do it again. */
836 vim_free(redir_lval->ll_newkey);
837 redir_lval->ll_newkey = NULL;
838 }
839
840 return OK;
841}
842
843/*
844 * Append "value[len]" to the variable set by var_redir_start().
845 */
846 void
847var_redir_str(value, len)
848 char_u *value;
849 int len;
850{
851 char_u *val;
852 typval_T tv;
853 int save_emsg;
854 int err;
855
856 if (redir_lval == NULL)
857 return;
858
859 if (len == -1)
860 /* Append the entire string */
861 val = vim_strsave(value);
862 else
863 /* Append only the specified number of characters */
864 val = vim_strnsave(value, len);
865 if (val == NULL)
866 return;
867
868 tv.v_type = VAR_STRING;
869 tv.vval.v_string = val;
870
871 save_emsg = did_emsg;
872 did_emsg = FALSE;
873 set_var_lval(redir_lval, redir_endp, &tv, FALSE, (char_u *)".");
874 err = did_emsg;
875 did_emsg += save_emsg;
876 if (err)
877 var_redir_stop();
878
879 vim_free(tv.vval.v_string);
880}
881
882/*
883 * Stop redirecting command output to a variable.
884 */
885 void
886var_redir_stop()
887{
888 if (redir_lval != NULL)
889 {
890 clear_lval(redir_lval);
891 vim_free(redir_lval);
892 redir_lval = NULL;
893 }
894 vim_free(redir_varname);
895 redir_varname = NULL;
896}
897
Bram Moolenaar071d4272004-06-13 20:20:40 +0000898# if defined(FEAT_MBYTE) || defined(PROTO)
899 int
900eval_charconvert(enc_from, enc_to, fname_from, fname_to)
901 char_u *enc_from;
902 char_u *enc_to;
903 char_u *fname_from;
904 char_u *fname_to;
905{
906 int err = FALSE;
907
908 set_vim_var_string(VV_CC_FROM, enc_from, -1);
909 set_vim_var_string(VV_CC_TO, enc_to, -1);
910 set_vim_var_string(VV_FNAME_IN, fname_from, -1);
911 set_vim_var_string(VV_FNAME_OUT, fname_to, -1);
912 if (eval_to_bool(p_ccv, &err, NULL, FALSE))
913 err = TRUE;
914 set_vim_var_string(VV_CC_FROM, NULL, -1);
915 set_vim_var_string(VV_CC_TO, NULL, -1);
916 set_vim_var_string(VV_FNAME_IN, NULL, -1);
917 set_vim_var_string(VV_FNAME_OUT, NULL, -1);
918
919 if (err)
920 return FAIL;
921 return OK;
922}
923# endif
924
925# if defined(FEAT_POSTSCRIPT) || defined(PROTO)
926 int
927eval_printexpr(fname, args)
928 char_u *fname;
929 char_u *args;
930{
931 int err = FALSE;
932
933 set_vim_var_string(VV_FNAME_IN, fname, -1);
934 set_vim_var_string(VV_CMDARG, args, -1);
935 if (eval_to_bool(p_pexpr, &err, NULL, FALSE))
936 err = TRUE;
937 set_vim_var_string(VV_FNAME_IN, NULL, -1);
938 set_vim_var_string(VV_CMDARG, NULL, -1);
939
940 if (err)
941 {
942 mch_remove(fname);
943 return FAIL;
944 }
945 return OK;
946}
947# endif
948
949# if defined(FEAT_DIFF) || defined(PROTO)
950 void
951eval_diff(origfile, newfile, outfile)
952 char_u *origfile;
953 char_u *newfile;
954 char_u *outfile;
955{
956 int err = FALSE;
957
958 set_vim_var_string(VV_FNAME_IN, origfile, -1);
959 set_vim_var_string(VV_FNAME_NEW, newfile, -1);
960 set_vim_var_string(VV_FNAME_OUT, outfile, -1);
961 (void)eval_to_bool(p_dex, &err, NULL, FALSE);
962 set_vim_var_string(VV_FNAME_IN, NULL, -1);
963 set_vim_var_string(VV_FNAME_NEW, NULL, -1);
964 set_vim_var_string(VV_FNAME_OUT, NULL, -1);
965}
966
967 void
968eval_patch(origfile, difffile, outfile)
969 char_u *origfile;
970 char_u *difffile;
971 char_u *outfile;
972{
973 int err;
974
975 set_vim_var_string(VV_FNAME_IN, origfile, -1);
976 set_vim_var_string(VV_FNAME_DIFF, difffile, -1);
977 set_vim_var_string(VV_FNAME_OUT, outfile, -1);
978 (void)eval_to_bool(p_pex, &err, NULL, FALSE);
979 set_vim_var_string(VV_FNAME_IN, NULL, -1);
980 set_vim_var_string(VV_FNAME_DIFF, NULL, -1);
981 set_vim_var_string(VV_FNAME_OUT, NULL, -1);
982}
983# endif
984
985/*
986 * Top level evaluation function, returning a boolean.
987 * Sets "error" to TRUE if there was an error.
988 * Return TRUE or FALSE.
989 */
990 int
991eval_to_bool(arg, error, nextcmd, skip)
992 char_u *arg;
993 int *error;
994 char_u **nextcmd;
995 int skip; /* only parse, don't execute */
996{
Bram Moolenaar33570922005-01-25 22:26:29 +0000997 typval_T tv;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000998 int retval = FALSE;
999
1000 if (skip)
1001 ++emsg_skip;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001002 if (eval0(arg, &tv, nextcmd, !skip) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001003 *error = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001004 else
1005 {
1006 *error = FALSE;
1007 if (!skip)
1008 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001009 retval = (get_tv_number(&tv) != 0);
1010 clear_tv(&tv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001011 }
1012 }
1013 if (skip)
1014 --emsg_skip;
1015
1016 return retval;
1017}
1018
1019/*
1020 * Top level evaluation function, returning a string. If "skip" is TRUE,
1021 * only parsing to "nextcmd" is done, without reporting errors. Return
1022 * pointer to allocated memory, or NULL for failure or when "skip" is TRUE.
1023 */
1024 char_u *
1025eval_to_string_skip(arg, nextcmd, skip)
1026 char_u *arg;
1027 char_u **nextcmd;
1028 int skip; /* only parse, don't execute */
1029{
Bram Moolenaar33570922005-01-25 22:26:29 +00001030 typval_T tv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001031 char_u *retval;
1032
1033 if (skip)
1034 ++emsg_skip;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001035 if (eval0(arg, &tv, nextcmd, !skip) == FAIL || skip)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001036 retval = NULL;
1037 else
1038 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001039 retval = vim_strsave(get_tv_string(&tv));
1040 clear_tv(&tv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001041 }
1042 if (skip)
1043 --emsg_skip;
1044
1045 return retval;
1046}
1047
1048/*
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001049 * Skip over an expression at "*pp".
1050 * Return FAIL for an error, OK otherwise.
1051 */
1052 int
1053skip_expr(pp)
1054 char_u **pp;
1055{
Bram Moolenaar33570922005-01-25 22:26:29 +00001056 typval_T rettv;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001057
1058 *pp = skipwhite(*pp);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001059 return eval1(pp, &rettv, FALSE);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001060}
1061
1062/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00001063 * Top level evaluation function, returning a string.
1064 * Return pointer to allocated memory, or NULL for failure.
1065 */
1066 char_u *
1067eval_to_string(arg, nextcmd)
1068 char_u *arg;
1069 char_u **nextcmd;
1070{
Bram Moolenaar33570922005-01-25 22:26:29 +00001071 typval_T tv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001072 char_u *retval;
1073
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001074 if (eval0(arg, &tv, nextcmd, TRUE) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001075 retval = NULL;
1076 else
1077 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001078 retval = vim_strsave(get_tv_string(&tv));
1079 clear_tv(&tv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001080 }
1081
1082 return retval;
1083}
1084
1085/*
1086 * Call eval_to_string() with "sandbox" set and not using local variables.
1087 */
1088 char_u *
1089eval_to_string_safe(arg, nextcmd)
1090 char_u *arg;
1091 char_u **nextcmd;
1092{
1093 char_u *retval;
1094 void *save_funccalp;
1095
1096 save_funccalp = save_funccal();
1097 ++sandbox;
1098 retval = eval_to_string(arg, nextcmd);
1099 --sandbox;
1100 restore_funccal(save_funccalp);
1101 return retval;
1102}
1103
Bram Moolenaar071d4272004-06-13 20:20:40 +00001104/*
1105 * Top level evaluation function, returning a number.
1106 * Evaluates "expr" silently.
1107 * Returns -1 for an error.
1108 */
1109 int
1110eval_to_number(expr)
1111 char_u *expr;
1112{
Bram Moolenaar33570922005-01-25 22:26:29 +00001113 typval_T rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001114 int retval;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00001115 char_u *p = skipwhite(expr);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001116
1117 ++emsg_off;
1118
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001119 if (eval1(&p, &rettv, TRUE) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001120 retval = -1;
1121 else
1122 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001123 retval = get_tv_number(&rettv);
1124 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001125 }
1126 --emsg_off;
1127
1128 return retval;
1129}
1130
1131#if (defined(FEAT_USR_CMDS) && defined(FEAT_CMDL_COMPL)) || defined(PROTO)
1132/*
1133 * Call some vimL function and return the result as a string
1134 * Uses argv[argc] for the function arguments.
1135 */
1136 char_u *
1137call_vim_function(func, argc, argv, safe)
1138 char_u *func;
1139 int argc;
1140 char_u **argv;
1141 int safe; /* use the sandbox */
1142{
1143 char_u *retval = NULL;
Bram Moolenaar33570922005-01-25 22:26:29 +00001144 typval_T rettv;
1145 typval_T *argvars;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001146 long n;
1147 int len;
1148 int i;
1149 int doesrange;
1150 void *save_funccalp = NULL;
1151
Bram Moolenaar33570922005-01-25 22:26:29 +00001152 argvars = (typval_T *)alloc((unsigned)(argc * sizeof(typval_T)));
Bram Moolenaar071d4272004-06-13 20:20:40 +00001153 if (argvars == NULL)
1154 return NULL;
1155
1156 for (i = 0; i < argc; i++)
1157 {
Bram Moolenaarcfbc5ee2004-07-02 15:38:35 +00001158 /* Pass a NULL or empty argument as an empty string */
1159 if (argv[i] == NULL || *argv[i] == NUL)
1160 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +00001161 argvars[i].v_type = VAR_STRING;
1162 argvars[i].vval.v_string = (char_u *)"";
Bram Moolenaarcfbc5ee2004-07-02 15:38:35 +00001163 continue;
1164 }
1165
Bram Moolenaar071d4272004-06-13 20:20:40 +00001166 /* Recognize a number argument, the others must be strings. */
1167 vim_str2nr(argv[i], NULL, &len, TRUE, TRUE, &n, NULL);
1168 if (len != 0 && len == (int)STRLEN(argv[i]))
1169 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +00001170 argvars[i].v_type = VAR_NUMBER;
1171 argvars[i].vval.v_number = n;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001172 }
1173 else
1174 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +00001175 argvars[i].v_type = VAR_STRING;
1176 argvars[i].vval.v_string = argv[i];
Bram Moolenaar071d4272004-06-13 20:20:40 +00001177 }
1178 }
1179
1180 if (safe)
1181 {
1182 save_funccalp = save_funccal();
1183 ++sandbox;
1184 }
1185
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001186 rettv.v_type = VAR_UNKNOWN; /* clear_tv() uses this */
1187 if (call_func(func, (int)STRLEN(func), &rettv, argc, argvars,
Bram Moolenaar071d4272004-06-13 20:20:40 +00001188 curwin->w_cursor.lnum, curwin->w_cursor.lnum,
Bram Moolenaare9a41262005-01-15 22:18:47 +00001189 &doesrange, TRUE, NULL) == OK)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001190 retval = vim_strsave(get_tv_string(&rettv));
Bram Moolenaar071d4272004-06-13 20:20:40 +00001191
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001192 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001193 vim_free(argvars);
1194
1195 if (safe)
1196 {
1197 --sandbox;
1198 restore_funccal(save_funccalp);
1199 }
1200 return retval;
1201}
1202#endif
1203
1204/*
1205 * Save the current function call pointer, and set it to NULL.
1206 * Used when executing autocommands and for ":source".
1207 */
1208 void *
1209save_funccal()
1210{
Bram Moolenaar05159a02005-02-26 23:04:13 +00001211 funccall_T *fc = current_funccal;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001212
Bram Moolenaar071d4272004-06-13 20:20:40 +00001213 current_funccal = NULL;
1214 return (void *)fc;
1215}
1216
1217 void
Bram Moolenaar05159a02005-02-26 23:04:13 +00001218restore_funccal(vfc)
1219 void *vfc;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001220{
Bram Moolenaar05159a02005-02-26 23:04:13 +00001221 funccall_T *fc = (funccall_T *)vfc;
1222
1223 current_funccal = fc;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001224}
1225
Bram Moolenaar05159a02005-02-26 23:04:13 +00001226#if defined(FEAT_PROFILE) || defined(PROTO)
1227/*
1228 * Prepare profiling for entering a child or something else that is not
1229 * counted for the script/function itself.
1230 * Should always be called in pair with prof_child_exit().
1231 */
1232 void
1233prof_child_enter(tm)
1234 proftime_T *tm; /* place to store waittime */
1235{
1236 funccall_T *fc = current_funccal;
1237
1238 if (fc != NULL && fc->func->uf_profiling)
1239 profile_start(&fc->prof_child);
1240 script_prof_save(tm);
1241}
1242
1243/*
1244 * Take care of time spent in a child.
1245 * Should always be called after prof_child_enter().
1246 */
1247 void
1248prof_child_exit(tm)
1249 proftime_T *tm; /* where waittime was stored */
1250{
1251 funccall_T *fc = current_funccal;
1252
1253 if (fc != NULL && fc->func->uf_profiling)
1254 {
1255 profile_end(&fc->prof_child);
1256 profile_sub_wait(tm, &fc->prof_child); /* don't count waiting time */
1257 profile_add(&fc->func->uf_tm_children, &fc->prof_child);
1258 profile_add(&fc->func->uf_tml_children, &fc->prof_child);
1259 }
1260 script_prof_restore(tm);
1261}
1262#endif
1263
1264
Bram Moolenaar071d4272004-06-13 20:20:40 +00001265#ifdef FEAT_FOLDING
1266/*
1267 * Evaluate 'foldexpr'. Returns the foldlevel, and any character preceding
1268 * it in "*cp". Doesn't give error messages.
1269 */
1270 int
1271eval_foldexpr(arg, cp)
1272 char_u *arg;
1273 int *cp;
1274{
Bram Moolenaar33570922005-01-25 22:26:29 +00001275 typval_T tv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001276 int retval;
1277 char_u *s;
1278
1279 ++emsg_off;
1280 ++sandbox;
1281 *cp = NUL;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001282 if (eval0(arg, &tv, NULL, TRUE) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001283 retval = 0;
1284 else
1285 {
1286 /* If the result is a number, just return the number. */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001287 if (tv.v_type == VAR_NUMBER)
1288 retval = tv.vval.v_number;
Bram Moolenaar758711c2005-02-02 23:11:38 +00001289 else if (tv.v_type != VAR_STRING || tv.vval.v_string == NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001290 retval = 0;
1291 else
1292 {
1293 /* If the result is a string, check if there is a non-digit before
1294 * the number. */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001295 s = tv.vval.v_string;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001296 if (!VIM_ISDIGIT(*s) && *s != '-')
1297 *cp = *s++;
1298 retval = atol((char *)s);
1299 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001300 clear_tv(&tv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001301 }
1302 --emsg_off;
1303 --sandbox;
1304
1305 return retval;
1306}
1307#endif
1308
Bram Moolenaar071d4272004-06-13 20:20:40 +00001309/*
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001310 * ":let" list all variable values
1311 * ":let var1 var2" list variable values
1312 * ":let var = expr" assignment command.
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001313 * ":let var += expr" assignment command.
1314 * ":let var -= expr" assignment command.
1315 * ":let var .= expr" assignment command.
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001316 * ":let [var1, var2] = expr" unpack list.
Bram Moolenaar071d4272004-06-13 20:20:40 +00001317 */
1318 void
1319ex_let(eap)
1320 exarg_T *eap;
1321{
1322 char_u *arg = eap->arg;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001323 char_u *expr = NULL;
Bram Moolenaar33570922005-01-25 22:26:29 +00001324 typval_T rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001325 int i;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001326 int var_count = 0;
1327 int semicolon = 0;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001328 char_u op[2];
Bram Moolenaar071d4272004-06-13 20:20:40 +00001329
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001330 expr = skip_var_list(arg, &var_count, &semicolon);
1331 if (expr == NULL)
1332 return;
1333 expr = vim_strchr(expr, '=');
1334 if (expr == NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001335 {
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00001336 /*
1337 * ":let" without "=": list variables
1338 */
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001339 if (*arg == '[')
1340 EMSG(_(e_invarg));
1341 else if (!ends_excmd(*arg))
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001342 /* ":let var1 var2" */
1343 arg = list_arg_vars(eap, arg);
1344 else if (!eap->skip)
Bram Moolenaara7043832005-01-21 11:56:39 +00001345 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001346 /* ":let" */
Bram Moolenaara7043832005-01-21 11:56:39 +00001347 list_glob_vars();
1348 list_buf_vars();
1349 list_win_vars();
1350 list_vim_vars();
1351 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001352 eap->nextcmd = check_nextcmd(arg);
1353 }
1354 else
1355 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001356 op[0] = '=';
1357 op[1] = NUL;
1358 if (expr > arg)
1359 {
1360 if (vim_strchr((char_u *)"+-.", expr[-1]) != NULL)
1361 op[0] = expr[-1]; /* +=, -= or .= */
1362 }
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001363 expr = skipwhite(expr + 1);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001364
Bram Moolenaar071d4272004-06-13 20:20:40 +00001365 if (eap->skip)
1366 ++emsg_skip;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001367 i = eval0(expr, &rettv, &eap->nextcmd, !eap->skip);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001368 if (eap->skip)
1369 {
1370 if (i != FAIL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001371 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001372 --emsg_skip;
1373 }
1374 else if (i != FAIL)
1375 {
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001376 (void)ex_let_vars(eap->arg, &rettv, FALSE, semicolon, var_count,
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001377 op);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001378 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001379 }
1380 }
1381}
1382
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001383/*
1384 * Assign the typevalue "tv" to the variable or variables at "arg_start".
1385 * Handles both "var" with any type and "[var, var; var]" with a list type.
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001386 * When "nextchars" is not NULL it points to a string with characters that
1387 * must appear after the variable(s). Use "+", "-" or "." for add, subtract
1388 * or concatenate.
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001389 * Returns OK or FAIL;
1390 */
1391 static int
1392ex_let_vars(arg_start, tv, copy, semicolon, var_count, nextchars)
1393 char_u *arg_start;
Bram Moolenaar33570922005-01-25 22:26:29 +00001394 typval_T *tv;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001395 int copy; /* copy values from "tv", don't move */
1396 int semicolon; /* from skip_var_list() */
1397 int var_count; /* from skip_var_list() */
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001398 char_u *nextchars;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001399{
1400 char_u *arg = arg_start;
Bram Moolenaar33570922005-01-25 22:26:29 +00001401 list_T *l;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001402 int i;
Bram Moolenaar33570922005-01-25 22:26:29 +00001403 listitem_T *item;
1404 typval_T ltv;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001405
1406 if (*arg != '[')
1407 {
1408 /*
1409 * ":let var = expr" or ":for var in list"
1410 */
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001411 if (ex_let_one(arg, tv, copy, nextchars, nextchars) == NULL)
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001412 return FAIL;
1413 return OK;
1414 }
1415
1416 /*
1417 * ":let [v1, v2] = list" or ":for [v1, v2] in listlist"
1418 */
Bram Moolenaar758711c2005-02-02 23:11:38 +00001419 if (tv->v_type != VAR_LIST || (l = tv->vval.v_list) == NULL)
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001420 {
1421 EMSG(_(e_listreq));
1422 return FAIL;
1423 }
1424
1425 i = list_len(l);
1426 if (semicolon == 0 && var_count < i)
1427 {
Bram Moolenaare49b69a2005-01-08 16:11:57 +00001428 EMSG(_("E687: Less targets than List items"));
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001429 return FAIL;
1430 }
1431 if (var_count - semicolon > i)
1432 {
Bram Moolenaare49b69a2005-01-08 16:11:57 +00001433 EMSG(_("E688: More targets than List items"));
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001434 return FAIL;
1435 }
1436
1437 item = l->lv_first;
1438 while (*arg != ']')
1439 {
1440 arg = skipwhite(arg + 1);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001441 arg = ex_let_one(arg, &item->li_tv, TRUE, (char_u *)",;]", nextchars);
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001442 item = item->li_next;
1443 if (arg == NULL)
1444 return FAIL;
1445
1446 arg = skipwhite(arg);
1447 if (*arg == ';')
1448 {
1449 /* Put the rest of the list (may be empty) in the var after ';'.
1450 * Create a new list for this. */
1451 l = list_alloc();
1452 if (l == NULL)
1453 return FAIL;
1454 while (item != NULL)
1455 {
1456 list_append_tv(l, &item->li_tv);
1457 item = item->li_next;
1458 }
1459
1460 ltv.v_type = VAR_LIST;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00001461 ltv.v_lock = 0;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001462 ltv.vval.v_list = l;
1463 l->lv_refcount = 1;
1464
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001465 arg = ex_let_one(skipwhite(arg + 1), &ltv, FALSE,
1466 (char_u *)"]", nextchars);
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001467 clear_tv(&ltv);
1468 if (arg == NULL)
1469 return FAIL;
1470 break;
1471 }
1472 else if (*arg != ',' && *arg != ']')
1473 {
1474 EMSG2(_(e_intern2), "ex_let_vars()");
1475 return FAIL;
1476 }
1477 }
1478
1479 return OK;
1480}
1481
1482/*
1483 * Skip over assignable variable "var" or list of variables "[var, var]".
1484 * Used for ":let varvar = expr" and ":for varvar in expr".
1485 * For "[var, var]" increment "*var_count" for each variable.
1486 * for "[var, var; var]" set "semicolon".
1487 * Return NULL for an error.
1488 */
1489 static char_u *
1490skip_var_list(arg, var_count, semicolon)
1491 char_u *arg;
1492 int *var_count;
1493 int *semicolon;
1494{
1495 char_u *p, *s;
1496
1497 if (*arg == '[')
1498 {
1499 /* "[var, var]": find the matching ']'. */
1500 p = arg;
1501 while (1)
1502 {
1503 p = skipwhite(p + 1); /* skip whites after '[', ';' or ',' */
1504 s = skip_var_one(p);
1505 if (s == p)
1506 {
1507 EMSG2(_(e_invarg2), p);
1508 return NULL;
1509 }
1510 ++*var_count;
1511
1512 p = skipwhite(s);
1513 if (*p == ']')
1514 break;
1515 else if (*p == ';')
1516 {
1517 if (*semicolon == 1)
1518 {
1519 EMSG(_("Double ; in list of variables"));
1520 return NULL;
1521 }
1522 *semicolon = 1;
1523 }
1524 else if (*p != ',')
1525 {
1526 EMSG2(_(e_invarg2), p);
1527 return NULL;
1528 }
1529 }
1530 return p + 1;
1531 }
1532 else
1533 return skip_var_one(arg);
1534}
1535
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001536/*
1537 * Skip one (assignable) variable name, includig $VAR, d.key, l[idx].
1538 */
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001539 static char_u *
1540skip_var_one(arg)
1541 char_u *arg;
1542{
1543 if (vim_strchr((char_u *)"$@&", *arg) != NULL)
1544 ++arg;
1545 return find_name_end(arg, NULL, NULL, TRUE);
1546}
1547
Bram Moolenaara7043832005-01-21 11:56:39 +00001548/*
Bram Moolenaar33570922005-01-25 22:26:29 +00001549 * List variables for hashtab "ht" with prefix "prefix".
1550 * If "empty" is TRUE also list NULL strings as empty strings.
Bram Moolenaara7043832005-01-21 11:56:39 +00001551 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001552 static void
Bram Moolenaar33570922005-01-25 22:26:29 +00001553list_hashtable_vars(ht, prefix, empty)
1554 hashtab_T *ht;
Bram Moolenaara7043832005-01-21 11:56:39 +00001555 char_u *prefix;
Bram Moolenaar33570922005-01-25 22:26:29 +00001556 int empty;
Bram Moolenaara7043832005-01-21 11:56:39 +00001557{
Bram Moolenaar33570922005-01-25 22:26:29 +00001558 hashitem_T *hi;
1559 dictitem_T *di;
Bram Moolenaara7043832005-01-21 11:56:39 +00001560 int todo;
1561
1562 todo = ht->ht_used;
1563 for (hi = ht->ht_array; todo > 0 && !got_int; ++hi)
1564 {
1565 if (!HASHITEM_EMPTY(hi))
1566 {
1567 --todo;
Bram Moolenaar33570922005-01-25 22:26:29 +00001568 di = HI2DI(hi);
1569 if (empty || di->di_tv.v_type != VAR_STRING
1570 || di->di_tv.vval.v_string != NULL)
1571 list_one_var(di, prefix);
Bram Moolenaara7043832005-01-21 11:56:39 +00001572 }
1573 }
1574}
1575
1576/*
1577 * List global variables.
1578 */
1579 static void
1580list_glob_vars()
1581{
Bram Moolenaar33570922005-01-25 22:26:29 +00001582 list_hashtable_vars(&globvarht, (char_u *)"", TRUE);
Bram Moolenaara7043832005-01-21 11:56:39 +00001583}
1584
1585/*
1586 * List buffer variables.
1587 */
1588 static void
1589list_buf_vars()
1590{
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001591 char_u numbuf[NUMBUFLEN];
1592
Bram Moolenaar33570922005-01-25 22:26:29 +00001593 list_hashtable_vars(&curbuf->b_vars.dv_hashtab, (char_u *)"b:", TRUE);
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001594
1595 sprintf((char *)numbuf, "%ld", (long)curbuf->b_changedtick);
1596 list_one_var_a((char_u *)"b:", (char_u *)"changedtick", VAR_NUMBER, numbuf);
Bram Moolenaara7043832005-01-21 11:56:39 +00001597}
1598
1599/*
1600 * List window variables.
1601 */
1602 static void
1603list_win_vars()
1604{
Bram Moolenaar33570922005-01-25 22:26:29 +00001605 list_hashtable_vars(&curwin->w_vars.dv_hashtab, (char_u *)"w:", TRUE);
Bram Moolenaara7043832005-01-21 11:56:39 +00001606}
1607
1608/*
1609 * List Vim variables.
1610 */
1611 static void
1612list_vim_vars()
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001613{
Bram Moolenaar33570922005-01-25 22:26:29 +00001614 list_hashtable_vars(&vimvarht, (char_u *)"v:", FALSE);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001615}
1616
1617/*
1618 * List variables in "arg".
1619 */
1620 static char_u *
1621list_arg_vars(eap, arg)
1622 exarg_T *eap;
1623 char_u *arg;
1624{
1625 int error = FALSE;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001626 int len;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001627 char_u *name;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001628 char_u *name_start;
1629 char_u *arg_subsc;
1630 char_u *tofree;
1631 typval_T tv;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001632
1633 while (!ends_excmd(*arg) && !got_int)
1634 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001635 if (error || eap->skip)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001636 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001637 arg = find_name_end(arg, NULL, NULL, TRUE);
1638 if (!vim_iswhite(*arg) && !ends_excmd(*arg))
1639 {
1640 emsg_severe = TRUE;
1641 EMSG(_(e_trailing));
1642 break;
1643 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001644 }
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001645 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001646 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001647 /* get_name_len() takes care of expanding curly braces */
1648 name_start = name = arg;
1649 len = get_name_len(&arg, &tofree, TRUE, TRUE);
1650 if (len <= 0)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001651 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001652 /* This is mainly to keep test 49 working: when expanding
1653 * curly braces fails overrule the exception error message. */
1654 if (len < 0 && !aborting())
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001655 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001656 emsg_severe = TRUE;
1657 EMSG2(_(e_invarg2), arg);
1658 break;
1659 }
1660 error = TRUE;
1661 }
1662 else
1663 {
1664 if (tofree != NULL)
1665 name = tofree;
1666 if (get_var_tv(name, len, &tv, TRUE) == FAIL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001667 error = TRUE;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001668 else
1669 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001670 /* handle d.key, l[idx], f(expr) */
1671 arg_subsc = arg;
1672 if (handle_subscript(&arg, &tv, TRUE, TRUE) == FAIL)
Bram Moolenaara7043832005-01-21 11:56:39 +00001673 error = TRUE;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001674 else
Bram Moolenaara7043832005-01-21 11:56:39 +00001675 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001676 if (arg == arg_subsc && len == 2 && name[1] == ':')
Bram Moolenaara7043832005-01-21 11:56:39 +00001677 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001678 switch (*name)
Bram Moolenaara7043832005-01-21 11:56:39 +00001679 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001680 case 'g': list_glob_vars(); break;
1681 case 'b': list_buf_vars(); break;
1682 case 'w': list_win_vars(); break;
1683 case 'v': list_vim_vars(); break;
1684 default:
1685 EMSG2(_("E738: Can't list variables for %s"), name);
Bram Moolenaara7043832005-01-21 11:56:39 +00001686 }
Bram Moolenaara7043832005-01-21 11:56:39 +00001687 }
1688 else
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001689 {
1690 char_u numbuf[NUMBUFLEN];
1691 char_u *tf;
1692 int c;
1693 char_u *s;
1694
1695 s = echo_string(&tv, &tf, numbuf);
1696 c = *arg;
1697 *arg = NUL;
1698 list_one_var_a((char_u *)"",
1699 arg == arg_subsc ? name : name_start,
1700 tv.v_type, s == NULL ? (char_u *)"" : s);
1701 *arg = c;
1702 vim_free(tf);
1703 }
1704 clear_tv(&tv);
Bram Moolenaara7043832005-01-21 11:56:39 +00001705 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001706 }
1707 }
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001708
1709 vim_free(tofree);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001710 }
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001711
1712 arg = skipwhite(arg);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001713 }
1714
1715 return arg;
1716}
1717
1718/*
1719 * Set one item of ":let var = expr" or ":let [v1, v2] = list" to its value.
1720 * Returns a pointer to the char just after the var name.
1721 * Returns NULL if there is an error.
1722 */
1723 static char_u *
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001724ex_let_one(arg, tv, copy, endchars, op)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001725 char_u *arg; /* points to variable name */
Bram Moolenaar33570922005-01-25 22:26:29 +00001726 typval_T *tv; /* value to assign to variable */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001727 int copy; /* copy value from "tv" */
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001728 char_u *endchars; /* valid chars after variable name or NULL */
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001729 char_u *op; /* "+", "-", "." or NULL*/
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001730{
1731 int c1;
1732 char_u *name;
1733 char_u *p;
1734 char_u *arg_end = NULL;
1735 int len;
1736 int opt_flags;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001737 char_u *tofree = NULL;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001738
1739 /*
1740 * ":let $VAR = expr": Set environment variable.
1741 */
1742 if (*arg == '$')
1743 {
1744 /* Find the end of the name. */
1745 ++arg;
1746 name = arg;
1747 len = get_env_len(&arg);
1748 if (len == 0)
1749 EMSG2(_(e_invarg2), name - 1);
1750 else
1751 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001752 if (op != NULL && (*op == '+' || *op == '-'))
1753 EMSG2(_(e_letwrong), op);
1754 else if (endchars != NULL
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001755 && vim_strchr(endchars, *skipwhite(arg)) == NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001756 EMSG(_(e_letunexp));
1757 else
1758 {
1759 c1 = name[len];
1760 name[len] = NUL;
1761 p = get_tv_string(tv);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001762 if (op != NULL && *op == '.')
1763 {
1764 int mustfree = FALSE;
1765 char_u *s = vim_getenv(name, &mustfree);
1766
1767 if (s != NULL)
1768 {
1769 p = tofree = concat_str(s, p);
1770 if (mustfree)
1771 vim_free(s);
1772 }
1773 }
1774 if (p != NULL)
1775 vim_setenv(name, p);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001776 if (STRICMP(name, "HOME") == 0)
1777 init_homedir();
1778 else if (didset_vim && STRICMP(name, "VIM") == 0)
1779 didset_vim = FALSE;
1780 else if (didset_vimruntime && STRICMP(name, "VIMRUNTIME") == 0)
1781 didset_vimruntime = FALSE;
1782 name[len] = c1;
1783 arg_end = arg;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001784 vim_free(tofree);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001785 }
1786 }
1787 }
1788
1789 /*
1790 * ":let &option = expr": Set option value.
1791 * ":let &l:option = expr": Set local option value.
1792 * ":let &g:option = expr": Set global option value.
1793 */
1794 else if (*arg == '&')
1795 {
1796 /* Find the end of the name. */
1797 p = find_option_end(&arg, &opt_flags);
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001798 if (p == NULL || (endchars != NULL
1799 && vim_strchr(endchars, *skipwhite(p)) == NULL))
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001800 EMSG(_(e_letunexp));
1801 else
1802 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001803 long n;
1804 int opt_type;
1805 long numval;
1806 char_u *stringval = NULL;
1807 char_u *s;
1808
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001809 c1 = *p;
1810 *p = NUL;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001811
1812 n = get_tv_number(tv);
1813 s = get_tv_string(tv);
1814 if (op != NULL && *op != '=')
1815 {
1816 opt_type = get_option_value(arg, &numval,
1817 &stringval, opt_flags);
1818 if ((opt_type == 1 && *op == '.')
1819 || (opt_type == 0 && *op != '.'))
1820 EMSG2(_(e_letwrong), op);
1821 else
1822 {
1823 if (opt_type == 1) /* number */
1824 {
1825 if (*op == '+')
1826 n = numval + n;
1827 else
1828 n = numval - n;
1829 }
1830 else if (opt_type == 0 && stringval != NULL) /* string */
1831 {
1832 s = concat_str(stringval, s);
1833 vim_free(stringval);
1834 stringval = s;
1835 }
1836 }
1837 }
1838 set_option_value(arg, n, s, opt_flags);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001839 *p = c1;
1840 arg_end = p;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001841 vim_free(stringval);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001842 }
1843 }
1844
1845 /*
1846 * ":let @r = expr": Set register contents.
1847 */
1848 else if (*arg == '@')
1849 {
1850 ++arg;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001851 if (op != NULL && (*op == '+' || *op == '-'))
1852 EMSG2(_(e_letwrong), op);
1853 else if (endchars != NULL
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001854 && vim_strchr(endchars, *skipwhite(arg + 1)) == NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001855 EMSG(_(e_letunexp));
1856 else
1857 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001858 char_u *tofree = NULL;
1859 char_u *s;
1860
1861 p = get_tv_string(tv);
1862 if (op != NULL && *op == '.')
1863 {
1864 s = get_reg_contents(*arg == '@' ? '"' : *arg, FALSE);
1865 if (s != NULL)
1866 {
1867 p = tofree = concat_str(s, p);
1868 vim_free(s);
1869 }
1870 }
1871 if (p != NULL)
1872 write_reg_contents(*arg == '@' ? '"' : *arg, p, -1, FALSE);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001873 arg_end = arg + 1;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001874 vim_free(tofree);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001875 }
1876 }
1877
1878 /*
1879 * ":let var = expr": Set internal variable.
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00001880 * ":let {expr} = expr": Idem, name made with curly braces
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001881 */
Bram Moolenaare9a41262005-01-15 22:18:47 +00001882 else if ((eval_isnamec(*arg) && !VIM_ISDIGIT(*arg)) || *arg == '{')
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001883 {
Bram Moolenaar33570922005-01-25 22:26:29 +00001884 lval_T lv;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001885
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00001886 p = get_lval(arg, tv, &lv, FALSE, FALSE, FALSE);
1887 if (p != NULL && lv.ll_name != NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001888 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00001889 if (endchars != NULL && vim_strchr(endchars, *skipwhite(p)) == NULL)
1890 EMSG(_(e_letunexp));
1891 else
1892 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001893 set_var_lval(&lv, p, tv, copy, op);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00001894 arg_end = p;
1895 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001896 }
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00001897 clear_lval(&lv);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001898 }
1899
1900 else
1901 EMSG2(_(e_invarg2), arg);
1902
1903 return arg_end;
1904}
1905
1906/*
Bram Moolenaar8c711452005-01-14 21:53:12 +00001907 * If "arg" is equal to "b:changedtick" give an error and return TRUE.
1908 */
1909 static int
1910check_changedtick(arg)
1911 char_u *arg;
1912{
1913 if (STRNCMP(arg, "b:changedtick", 13) == 0 && !eval_isnamec(arg[13]))
1914 {
1915 EMSG2(_(e_readonlyvar), arg);
1916 return TRUE;
1917 }
1918 return FALSE;
1919}
1920
1921/*
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00001922 * Get an lval: variable, Dict item or List item that can be assigned a value
1923 * to: "name", "na{me}", "name[expr]", "name[expr:expr]", "name[expr][expr]",
1924 * "name.key", "name.key[expr]" etc.
1925 * Indexing only works if "name" is an existing List or Dictionary.
1926 * "name" points to the start of the name.
1927 * If "rettv" is not NULL it points to the value to be assigned.
1928 * "unlet" is TRUE for ":unlet": slightly different behavior when something is
1929 * wrong; must end in space or cmd separator.
1930 *
1931 * Returns a pointer to just after the name, including indexes.
Bram Moolenaara7043832005-01-21 11:56:39 +00001932 * When an evaluation error occurs "lp->ll_name" is NULL;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00001933 * Returns NULL for a parsing error. Still need to free items in "lp"!
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001934 */
1935 static char_u *
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00001936get_lval(name, rettv, lp, unlet, skip, quiet)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001937 char_u *name;
Bram Moolenaar33570922005-01-25 22:26:29 +00001938 typval_T *rettv;
1939 lval_T *lp;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00001940 int unlet;
1941 int skip;
1942 int quiet; /* don't give error messages */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001943{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001944 char_u *p;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00001945 char_u *expr_start, *expr_end;
1946 int cc;
Bram Moolenaar33570922005-01-25 22:26:29 +00001947 dictitem_T *v;
1948 typval_T var1;
1949 typval_T var2;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00001950 int empty1 = FALSE;
Bram Moolenaar33570922005-01-25 22:26:29 +00001951 listitem_T *ni;
Bram Moolenaar8c711452005-01-14 21:53:12 +00001952 char_u *key = NULL;
Bram Moolenaar8c711452005-01-14 21:53:12 +00001953 int len;
Bram Moolenaar33570922005-01-25 22:26:29 +00001954 hashtab_T *ht;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001955
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00001956 /* Clear everything in "lp". */
Bram Moolenaar33570922005-01-25 22:26:29 +00001957 vim_memset(lp, 0, sizeof(lval_T));
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00001958
1959 if (skip)
1960 {
1961 /* When skipping just find the end of the name. */
1962 lp->ll_name = name;
1963 return find_name_end(name, NULL, NULL, TRUE);
1964 }
1965
1966 /* Find the end of the name. */
1967 p = find_name_end(name, &expr_start, &expr_end, FALSE);
1968 if (expr_start != NULL)
1969 {
1970 /* Don't expand the name when we already know there is an error. */
1971 if (unlet && !vim_iswhite(*p) && !ends_excmd(*p)
1972 && *p != '[' && *p != '.')
1973 {
1974 EMSG(_(e_trailing));
1975 return NULL;
1976 }
1977
1978 lp->ll_exp_name = make_expanded_name(name, expr_start, expr_end, p);
1979 if (lp->ll_exp_name == NULL)
1980 {
1981 /* Report an invalid expression in braces, unless the
1982 * expression evaluation has been cancelled due to an
1983 * aborting error, an interrupt, or an exception. */
1984 if (!aborting() && !quiet)
1985 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00001986 emsg_severe = TRUE;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00001987 EMSG2(_(e_invarg2), name);
1988 return NULL;
1989 }
1990 }
1991 lp->ll_name = lp->ll_exp_name;
1992 }
1993 else
1994 lp->ll_name = name;
1995
1996 /* Without [idx] or .key we are done. */
1997 if ((*p != '[' && *p != '.') || lp->ll_name == NULL)
1998 return p;
1999
2000 cc = *p;
2001 *p = NUL;
Bram Moolenaara7043832005-01-21 11:56:39 +00002002 v = find_var(lp->ll_name, &ht);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002003 if (v == NULL && !quiet)
2004 EMSG2(_(e_undefvar), lp->ll_name);
2005 *p = cc;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002006 if (v == NULL)
2007 return NULL;
2008
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002009 /*
2010 * Loop until no more [idx] or .key is following.
2011 */
Bram Moolenaar33570922005-01-25 22:26:29 +00002012 lp->ll_tv = &v->di_tv;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002013 while (*p == '[' || (*p == '.' && lp->ll_tv->v_type == VAR_DICT))
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002014 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002015 if (!(lp->ll_tv->v_type == VAR_LIST && lp->ll_tv->vval.v_list != NULL)
2016 && !(lp->ll_tv->v_type == VAR_DICT
2017 && lp->ll_tv->vval.v_dict != NULL))
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002018 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002019 if (!quiet)
2020 EMSG(_("E689: Can only index a List or Dictionary"));
2021 return NULL;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002022 }
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002023 if (lp->ll_range)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002024 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002025 if (!quiet)
2026 EMSG(_("E708: [:] must come last"));
2027 return NULL;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002028 }
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002029
Bram Moolenaar8c711452005-01-14 21:53:12 +00002030 len = -1;
2031 if (*p == '.')
2032 {
2033 key = p + 1;
2034 for (len = 0; ASCII_ISALNUM(key[len]) || key[len] == '_'; ++len)
2035 ;
2036 if (len == 0)
2037 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002038 if (!quiet)
2039 EMSG(_(e_emptykey));
2040 return NULL;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002041 }
2042 p = key + len;
2043 }
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002044 else
2045 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00002046 /* Get the index [expr] or the first index [expr: ]. */
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002047 p = skipwhite(p + 1);
Bram Moolenaar8c711452005-01-14 21:53:12 +00002048 if (*p == ':')
2049 empty1 = TRUE;
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002050 else
2051 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00002052 empty1 = FALSE;
2053 if (eval1(&p, &var1, TRUE) == FAIL) /* recursive! */
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002054 return NULL;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002055 }
2056
2057 /* Optionally get the second index [ :expr]. */
2058 if (*p == ':')
2059 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002060 if (lp->ll_tv->v_type == VAR_DICT)
Bram Moolenaar8c711452005-01-14 21:53:12 +00002061 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002062 if (!quiet)
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002063 EMSG(_(e_dictrange));
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002064 if (!empty1)
2065 clear_tv(&var1);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002066 return NULL;
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002067 }
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002068 if (rettv != NULL && (rettv->v_type != VAR_LIST
2069 || rettv->vval.v_list == NULL))
Bram Moolenaar8c711452005-01-14 21:53:12 +00002070 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002071 if (!quiet)
2072 EMSG(_("E709: [:] requires a List value"));
Bram Moolenaar8c711452005-01-14 21:53:12 +00002073 if (!empty1)
2074 clear_tv(&var1);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002075 return NULL;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002076 }
2077 p = skipwhite(p + 1);
2078 if (*p == ']')
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002079 lp->ll_empty2 = TRUE;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002080 else
2081 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002082 lp->ll_empty2 = FALSE;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002083 if (eval1(&p, &var2, TRUE) == FAIL) /* recursive! */
2084 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00002085 if (!empty1)
2086 clear_tv(&var1);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002087 return NULL;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002088 }
2089 }
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002090 lp->ll_range = TRUE;
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002091 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00002092 else
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002093 lp->ll_range = FALSE;
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002094
Bram Moolenaar8c711452005-01-14 21:53:12 +00002095 if (*p != ']')
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002096 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002097 if (!quiet)
2098 EMSG(_(e_missbrac));
Bram Moolenaar8c711452005-01-14 21:53:12 +00002099 if (!empty1)
2100 clear_tv(&var1);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002101 if (lp->ll_range && !lp->ll_empty2)
Bram Moolenaar8c711452005-01-14 21:53:12 +00002102 clear_tv(&var2);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002103 return NULL;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002104 }
2105
2106 /* Skip to past ']'. */
2107 ++p;
2108 }
2109
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002110 if (lp->ll_tv->v_type == VAR_DICT)
Bram Moolenaar8c711452005-01-14 21:53:12 +00002111 {
2112 if (len == -1)
2113 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002114 /* "[key]": get key from "var1" */
Bram Moolenaar8c711452005-01-14 21:53:12 +00002115 key = get_tv_string(&var1);
2116 if (*key == NUL)
2117 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002118 if (!quiet)
2119 EMSG(_(e_emptykey));
Bram Moolenaar8c711452005-01-14 21:53:12 +00002120 clear_tv(&var1);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002121 return NULL;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002122 }
2123 }
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002124 lp->ll_list = NULL;
2125 lp->ll_dict = lp->ll_tv->vval.v_dict;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00002126 lp->ll_di = dict_find(lp->ll_dict, key, len);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002127 if (lp->ll_di == NULL)
Bram Moolenaar8c711452005-01-14 21:53:12 +00002128 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00002129 /* Key does not exist in dict: may need to add it. */
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002130 if (*p == '[' || *p == '.' || unlet)
Bram Moolenaar8c711452005-01-14 21:53:12 +00002131 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002132 if (!quiet)
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002133 EMSG2(_(e_dictkey), key);
Bram Moolenaar8c711452005-01-14 21:53:12 +00002134 if (len == -1)
2135 clear_tv(&var1);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002136 return NULL;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002137 }
2138 if (len == -1)
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002139 lp->ll_newkey = vim_strsave(key);
Bram Moolenaar8c711452005-01-14 21:53:12 +00002140 else
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002141 lp->ll_newkey = vim_strnsave(key, len);
Bram Moolenaar8c711452005-01-14 21:53:12 +00002142 if (len == -1)
2143 clear_tv(&var1);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002144 if (lp->ll_newkey == NULL)
Bram Moolenaar8c711452005-01-14 21:53:12 +00002145 p = NULL;
2146 break;
2147 }
2148 if (len == -1)
2149 clear_tv(&var1);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002150 lp->ll_tv = &lp->ll_di->di_tv;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002151 }
2152 else
2153 {
2154 /*
2155 * Get the number and item for the only or first index of the List.
2156 */
2157 if (empty1)
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002158 lp->ll_n1 = 0;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002159 else
2160 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002161 lp->ll_n1 = get_tv_number(&var1);
Bram Moolenaar8c711452005-01-14 21:53:12 +00002162 clear_tv(&var1);
2163 }
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002164 lp->ll_dict = NULL;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002165 lp->ll_list = lp->ll_tv->vval.v_list;
2166 lp->ll_li = list_find(lp->ll_list, lp->ll_n1);
2167 if (lp->ll_li == NULL)
Bram Moolenaar8c711452005-01-14 21:53:12 +00002168 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002169 if (!quiet)
2170 EMSGN(_(e_listidx), lp->ll_n1);
2171 if (lp->ll_range && !lp->ll_empty2)
Bram Moolenaar8c711452005-01-14 21:53:12 +00002172 clear_tv(&var2);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002173 return NULL;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002174 }
2175
2176 /*
2177 * May need to find the item or absolute index for the second
2178 * index of a range.
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002179 * When no index given: "lp->ll_empty2" is TRUE.
2180 * Otherwise "lp->ll_n2" is set to the second index.
Bram Moolenaar8c711452005-01-14 21:53:12 +00002181 */
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002182 if (lp->ll_range && !lp->ll_empty2)
Bram Moolenaar8c711452005-01-14 21:53:12 +00002183 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002184 lp->ll_n2 = get_tv_number(&var2);
Bram Moolenaar8c711452005-01-14 21:53:12 +00002185 clear_tv(&var2);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002186 if (lp->ll_n2 < 0)
Bram Moolenaar8c711452005-01-14 21:53:12 +00002187 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002188 ni = list_find(lp->ll_list, lp->ll_n2);
Bram Moolenaar8c711452005-01-14 21:53:12 +00002189 if (ni == NULL)
2190 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002191 if (!quiet)
2192 EMSGN(_(e_listidx), lp->ll_n2);
2193 return NULL;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002194 }
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002195 lp->ll_n2 = list_idx_of_item(lp->ll_list, ni);
Bram Moolenaar8c711452005-01-14 21:53:12 +00002196 }
2197
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002198 /* Check that lp->ll_n2 isn't before lp->ll_n1. */
2199 if (lp->ll_n1 < 0)
2200 lp->ll_n1 = list_idx_of_item(lp->ll_list, lp->ll_li);
2201 if (lp->ll_n2 < lp->ll_n1)
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002202 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002203 if (!quiet)
2204 EMSGN(_(e_listidx), lp->ll_n2);
2205 return NULL;
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002206 }
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002207 }
2208
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002209 lp->ll_tv = &lp->ll_li->li_tv;
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002210 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002211 }
2212
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002213 return p;
2214}
2215
2216/*
Bram Moolenaar33570922005-01-25 22:26:29 +00002217 * Clear lval "lp" that was filled by get_lval().
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002218 */
2219 static void
2220clear_lval(lp)
Bram Moolenaar33570922005-01-25 22:26:29 +00002221 lval_T *lp;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002222{
2223 vim_free(lp->ll_exp_name);
2224 vim_free(lp->ll_newkey);
2225}
2226
2227/*
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00002228 * Set a variable that was parsed by get_lval() to "rettv".
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002229 * "endp" points to just after the parsed name.
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002230 * "op" is NULL, "+" for "+=", "-" for "-=", "." for ".=" or "=" for "=".
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002231 */
2232 static void
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002233set_var_lval(lp, endp, rettv, copy, op)
Bram Moolenaar33570922005-01-25 22:26:29 +00002234 lval_T *lp;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002235 char_u *endp;
Bram Moolenaar33570922005-01-25 22:26:29 +00002236 typval_T *rettv;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002237 int copy;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002238 char_u *op;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002239{
2240 int cc;
Bram Moolenaar33570922005-01-25 22:26:29 +00002241 listitem_T *ni;
2242 listitem_T *ri;
2243 dictitem_T *di;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002244
2245 if (lp->ll_tv == NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002246 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002247 if (!check_changedtick(lp->ll_name))
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002248 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002249 cc = *endp;
2250 *endp = NUL;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002251 if (op != NULL && *op != '=')
2252 {
Bram Moolenaar33570922005-01-25 22:26:29 +00002253 typval_T tv;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002254
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00002255 /* handle +=, -= and .= */
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00002256 if (get_var_tv(lp->ll_name, STRLEN(lp->ll_name),
2257 &tv, TRUE) == OK)
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002258 {
2259 if (tv_op(&tv, rettv, op) == OK)
2260 set_var(lp->ll_name, &tv, FALSE);
2261 clear_tv(&tv);
2262 }
2263 }
2264 else
2265 set_var(lp->ll_name, rettv, copy);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002266 *endp = cc;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002267 }
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002268 }
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00002269 else if (tv_check_lock(lp->ll_newkey == NULL
2270 ? lp->ll_tv->v_lock
2271 : lp->ll_tv->vval.v_dict->dv_lock, lp->ll_name))
2272 ;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002273 else if (lp->ll_range)
2274 {
2275 /*
2276 * Assign the List values to the list items.
2277 */
2278 for (ri = rettv->vval.v_list->lv_first; ri != NULL; )
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002279 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002280 if (op != NULL && *op != '=')
2281 tv_op(&lp->ll_li->li_tv, &ri->li_tv, op);
2282 else
2283 {
2284 clear_tv(&lp->ll_li->li_tv);
2285 copy_tv(&ri->li_tv, &lp->ll_li->li_tv);
2286 }
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002287 ri = ri->li_next;
2288 if (ri == NULL || (!lp->ll_empty2 && lp->ll_n2 == lp->ll_n1))
2289 break;
2290 if (lp->ll_li->li_next == NULL)
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002291 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002292 /* Need to add an empty item. */
2293 ni = listitem_alloc();
2294 if (ni == NULL)
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002295 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002296 ri = NULL;
2297 break;
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002298 }
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002299 ni->li_tv.v_type = VAR_NUMBER;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00002300 ni->li_tv.v_lock = 0;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002301 ni->li_tv.vval.v_number = 0;
2302 list_append(lp->ll_list, ni);
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002303 }
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002304 lp->ll_li = lp->ll_li->li_next;
2305 ++lp->ll_n1;
2306 }
2307 if (ri != NULL)
2308 EMSG(_("E710: List value has more items than target"));
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002309 else if (lp->ll_empty2
2310 ? (lp->ll_li != NULL && lp->ll_li->li_next != NULL)
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002311 : lp->ll_n1 != lp->ll_n2)
2312 EMSG(_("E711: List value has not enough items"));
2313 }
2314 else
2315 {
2316 /*
2317 * Assign to a List or Dictionary item.
2318 */
2319 if (lp->ll_newkey != NULL)
2320 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002321 if (op != NULL && *op != '=')
2322 {
2323 EMSG2(_(e_letwrong), op);
2324 return;
2325 }
2326
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002327 /* Need to add an item to the Dictionary. */
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00002328 di = dictitem_alloc(lp->ll_newkey);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002329 if (di == NULL)
2330 return;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00002331 if (dict_add(lp->ll_tv->vval.v_dict, di) == FAIL)
2332 {
2333 vim_free(di);
2334 return;
2335 }
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002336 lp->ll_tv = &di->di_tv;
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002337 }
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002338 else if (op != NULL && *op != '=')
2339 {
2340 tv_op(lp->ll_tv, rettv, op);
2341 return;
2342 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002343 else
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002344 clear_tv(lp->ll_tv);
Bram Moolenaar8c711452005-01-14 21:53:12 +00002345
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002346 /*
2347 * Assign the value to the variable or list item.
2348 */
2349 if (copy)
2350 copy_tv(rettv, lp->ll_tv);
2351 else
2352 {
2353 *lp->ll_tv = *rettv;
Bram Moolenaar758711c2005-02-02 23:11:38 +00002354 lp->ll_tv->v_lock = 0;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002355 init_tv(rettv);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002356 }
2357 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002358}
2359
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002360/*
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002361 * Handle "tv1 += tv2", "tv1 -= tv2" and "tv1 .= tv2"
2362 * Returns OK or FAIL.
2363 */
2364 static int
2365tv_op(tv1, tv2, op)
Bram Moolenaar33570922005-01-25 22:26:29 +00002366 typval_T *tv1;
2367 typval_T *tv2;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002368 char_u *op;
2369{
2370 long n;
2371 char_u numbuf[NUMBUFLEN];
2372 char_u *s;
2373
2374 /* Can't do anything with a Funcref or a Dict on the right. */
2375 if (tv2->v_type != VAR_FUNC && tv2->v_type != VAR_DICT)
2376 {
2377 switch (tv1->v_type)
2378 {
2379 case VAR_DICT:
2380 case VAR_FUNC:
2381 break;
2382
2383 case VAR_LIST:
2384 if (*op != '+' || tv2->v_type != VAR_LIST)
2385 break;
2386 /* List += List */
2387 if (tv1->vval.v_list != NULL && tv2->vval.v_list != NULL)
2388 list_extend(tv1->vval.v_list, tv2->vval.v_list, NULL);
2389 return OK;
2390
2391 case VAR_NUMBER:
2392 case VAR_STRING:
2393 if (tv2->v_type == VAR_LIST)
2394 break;
2395 if (*op == '+' || *op == '-')
2396 {
2397 /* nr += nr or nr -= nr*/
2398 n = get_tv_number(tv1);
2399 if (*op == '+')
2400 n += get_tv_number(tv2);
2401 else
2402 n -= get_tv_number(tv2);
2403 clear_tv(tv1);
2404 tv1->v_type = VAR_NUMBER;
2405 tv1->vval.v_number = n;
2406 }
2407 else
2408 {
2409 /* str .= str */
2410 s = get_tv_string(tv1);
2411 s = concat_str(s, get_tv_string_buf(tv2, numbuf));
2412 clear_tv(tv1);
2413 tv1->v_type = VAR_STRING;
2414 tv1->vval.v_string = s;
2415 }
2416 return OK;
2417 }
2418 }
2419
2420 EMSG2(_(e_letwrong), op);
2421 return FAIL;
2422}
2423
2424/*
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002425 * Add a watcher to a list.
2426 */
2427 static void
2428list_add_watch(l, lw)
Bram Moolenaar33570922005-01-25 22:26:29 +00002429 list_T *l;
2430 listwatch_T *lw;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002431{
2432 lw->lw_next = l->lv_watch;
2433 l->lv_watch = lw;
2434}
2435
2436/*
Bram Moolenaar758711c2005-02-02 23:11:38 +00002437 * Remove a watcher from a list.
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002438 * No warning when it isn't found...
2439 */
2440 static void
2441list_rem_watch(l, lwrem)
Bram Moolenaar33570922005-01-25 22:26:29 +00002442 list_T *l;
2443 listwatch_T *lwrem;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002444{
Bram Moolenaar33570922005-01-25 22:26:29 +00002445 listwatch_T *lw, **lwp;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002446
2447 lwp = &l->lv_watch;
2448 for (lw = l->lv_watch; lw != NULL; lw = lw->lw_next)
2449 {
2450 if (lw == lwrem)
2451 {
2452 *lwp = lw->lw_next;
2453 break;
2454 }
2455 lwp = &lw->lw_next;
2456 }
2457}
2458
2459/*
2460 * Just before removing an item from a list: advance watchers to the next
2461 * item.
2462 */
2463 static void
2464list_fix_watch(l, item)
Bram Moolenaar33570922005-01-25 22:26:29 +00002465 list_T *l;
2466 listitem_T *item;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002467{
Bram Moolenaar33570922005-01-25 22:26:29 +00002468 listwatch_T *lw;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002469
2470 for (lw = l->lv_watch; lw != NULL; lw = lw->lw_next)
2471 if (lw->lw_item == item)
2472 lw->lw_item = item->li_next;
2473}
2474
2475/*
2476 * Evaluate the expression used in a ":for var in expr" command.
2477 * "arg" points to "var".
2478 * Set "*errp" to TRUE for an error, FALSE otherwise;
2479 * Return a pointer that holds the info. Null when there is an error.
2480 */
2481 void *
2482eval_for_line(arg, errp, nextcmdp, skip)
2483 char_u *arg;
2484 int *errp;
2485 char_u **nextcmdp;
2486 int skip;
2487{
Bram Moolenaar33570922005-01-25 22:26:29 +00002488 forinfo_T *fi;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002489 char_u *expr;
Bram Moolenaar33570922005-01-25 22:26:29 +00002490 typval_T tv;
2491 list_T *l;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002492
2493 *errp = TRUE; /* default: there is an error */
2494
Bram Moolenaar33570922005-01-25 22:26:29 +00002495 fi = (forinfo_T *)alloc_clear(sizeof(forinfo_T));
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002496 if (fi == NULL)
2497 return NULL;
2498
2499 expr = skip_var_list(arg, &fi->fi_varcount, &fi->fi_semicolon);
2500 if (expr == NULL)
2501 return fi;
2502
2503 expr = skipwhite(expr);
2504 if (expr[0] != 'i' || expr[1] != 'n' || !vim_iswhite(expr[2]))
2505 {
Bram Moolenaare49b69a2005-01-08 16:11:57 +00002506 EMSG(_("E690: Missing \"in\" after :for"));
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002507 return fi;
2508 }
2509
2510 if (skip)
2511 ++emsg_skip;
2512 if (eval0(skipwhite(expr + 2), &tv, nextcmdp, !skip) == OK)
2513 {
2514 *errp = FALSE;
2515 if (!skip)
2516 {
2517 l = tv.vval.v_list;
2518 if (tv.v_type != VAR_LIST || l == NULL)
2519 EMSG(_(e_listreq));
2520 else
2521 {
2522 fi->fi_list = l;
2523 list_add_watch(l, &fi->fi_lw);
2524 fi->fi_lw.lw_item = l->lv_first;
2525 }
2526 }
2527 }
2528 if (skip)
2529 --emsg_skip;
2530
2531 return fi;
2532}
2533
2534/*
2535 * Use the first item in a ":for" list. Advance to the next.
2536 * Assign the values to the variable (list). "arg" points to the first one.
2537 * Return TRUE when a valid item was found, FALSE when at end of list or
2538 * something wrong.
2539 */
2540 int
2541next_for_item(fi_void, arg)
2542 void *fi_void;
2543 char_u *arg;
2544{
Bram Moolenaar33570922005-01-25 22:26:29 +00002545 forinfo_T *fi = (forinfo_T *)fi_void;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002546 int result;
Bram Moolenaar33570922005-01-25 22:26:29 +00002547 listitem_T *item;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002548
2549 item = fi->fi_lw.lw_item;
2550 if (item == NULL)
2551 result = FALSE;
2552 else
2553 {
2554 fi->fi_lw.lw_item = item->li_next;
2555 result = (ex_let_vars(arg, &item->li_tv, TRUE,
2556 fi->fi_semicolon, fi->fi_varcount, NULL) == OK);
2557 }
2558 return result;
2559}
2560
2561/*
2562 * Free the structure used to store info used by ":for".
2563 */
2564 void
2565free_for_info(fi_void)
2566 void *fi_void;
2567{
Bram Moolenaar33570922005-01-25 22:26:29 +00002568 forinfo_T *fi = (forinfo_T *)fi_void;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002569
Bram Moolenaarab7013c2005-01-09 21:23:56 +00002570 if (fi != NULL && fi->fi_list != NULL)
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002571 list_rem_watch(fi->fi_list, &fi->fi_lw);
2572 vim_free(fi);
2573}
2574
Bram Moolenaar071d4272004-06-13 20:20:40 +00002575#if defined(FEAT_CMDL_COMPL) || defined(PROTO)
2576
2577 void
2578set_context_for_expression(xp, arg, cmdidx)
2579 expand_T *xp;
2580 char_u *arg;
2581 cmdidx_T cmdidx;
2582{
2583 int got_eq = FALSE;
2584 int c;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002585 char_u *p;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002586
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002587 if (cmdidx == CMD_let)
2588 {
2589 xp->xp_context = EXPAND_USER_VARS;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00002590 if (vim_strpbrk(arg, (char_u *)"\"'+-*/%.=!?~|&$([<>,#") == NULL)
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002591 {
2592 /* ":let var1 var2 ...": find last space. */
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00002593 for (p = arg + STRLEN(arg); p >= arg; )
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002594 {
2595 xp->xp_pattern = p;
Bram Moolenaar33570922005-01-25 22:26:29 +00002596 mb_ptr_back(arg, p);
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002597 if (vim_iswhite(*p))
2598 break;
2599 }
2600 return;
2601 }
2602 }
2603 else
2604 xp->xp_context = cmdidx == CMD_call ? EXPAND_FUNCTIONS
2605 : EXPAND_EXPRESSION;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002606 while ((xp->xp_pattern = vim_strpbrk(arg,
2607 (char_u *)"\"'+-*/%.=!?~|&$([<>,#")) != NULL)
2608 {
2609 c = *xp->xp_pattern;
2610 if (c == '&')
2611 {
2612 c = xp->xp_pattern[1];
2613 if (c == '&')
2614 {
2615 ++xp->xp_pattern;
2616 xp->xp_context = cmdidx != CMD_let || got_eq
2617 ? EXPAND_EXPRESSION : EXPAND_NOTHING;
2618 }
2619 else if (c != ' ')
2620 xp->xp_context = EXPAND_SETTINGS;
2621 }
2622 else if (c == '$')
2623 {
2624 /* environment variable */
2625 xp->xp_context = EXPAND_ENV_VARS;
2626 }
2627 else if (c == '=')
2628 {
2629 got_eq = TRUE;
2630 xp->xp_context = EXPAND_EXPRESSION;
2631 }
2632 else if (c == '<'
2633 && xp->xp_context == EXPAND_FUNCTIONS
2634 && vim_strchr(xp->xp_pattern, '(') == NULL)
2635 {
2636 /* Function name can start with "<SNR>" */
2637 break;
2638 }
2639 else if (cmdidx != CMD_let || got_eq)
2640 {
2641 if (c == '"') /* string */
2642 {
2643 while ((c = *++xp->xp_pattern) != NUL && c != '"')
2644 if (c == '\\' && xp->xp_pattern[1] != NUL)
2645 ++xp->xp_pattern;
2646 xp->xp_context = EXPAND_NOTHING;
2647 }
2648 else if (c == '\'') /* literal string */
2649 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00002650 /* Trick: '' is like stopping and starting a literal string. */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002651 while ((c = *++xp->xp_pattern) != NUL && c != '\'')
2652 /* skip */ ;
2653 xp->xp_context = EXPAND_NOTHING;
2654 }
2655 else if (c == '|')
2656 {
2657 if (xp->xp_pattern[1] == '|')
2658 {
2659 ++xp->xp_pattern;
2660 xp->xp_context = EXPAND_EXPRESSION;
2661 }
2662 else
2663 xp->xp_context = EXPAND_COMMANDS;
2664 }
2665 else
2666 xp->xp_context = EXPAND_EXPRESSION;
2667 }
2668 else
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002669 /* Doesn't look like something valid, expand as an expression
2670 * anyway. */
2671 xp->xp_context = EXPAND_EXPRESSION;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002672 arg = xp->xp_pattern;
2673 if (*arg != NUL)
2674 while ((c = *++arg) != NUL && (c == ' ' || c == '\t'))
2675 /* skip */ ;
2676 }
2677 xp->xp_pattern = arg;
2678}
2679
2680#endif /* FEAT_CMDL_COMPL */
2681
2682/*
2683 * ":1,25call func(arg1, arg2)" function call.
2684 */
2685 void
2686ex_call(eap)
2687 exarg_T *eap;
2688{
2689 char_u *arg = eap->arg;
2690 char_u *startarg;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002691 char_u *name;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002692 char_u *tofree;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002693 int len;
Bram Moolenaar33570922005-01-25 22:26:29 +00002694 typval_T rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002695 linenr_T lnum;
2696 int doesrange;
2697 int failed = FALSE;
Bram Moolenaar33570922005-01-25 22:26:29 +00002698 funcdict_T fudi;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002699
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00002700 tofree = trans_function_name(&arg, eap->skip, TFN_INT, &fudi);
2701 vim_free(fudi.fd_newkey);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002702 if (tofree == NULL)
2703 return;
2704
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00002705 /* Increase refcount on dictionary, it could get deleted when evaluating
2706 * the arguments. */
2707 if (fudi.fd_dict != NULL)
2708 ++fudi.fd_dict->dv_refcount;
2709
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002710 /* If it is the name of a variable of type VAR_FUNC use its contents. */
2711 len = STRLEN(tofree);
2712 name = deref_func_name(tofree, &len);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002713
Bram Moolenaar532c7802005-01-27 14:44:31 +00002714 /* Skip white space to allow ":call func ()". Not good, but required for
2715 * backward compatibility. */
2716 startarg = skipwhite(arg);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002717 rettv.v_type = VAR_UNKNOWN; /* clear_tv() uses this */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002718
2719 if (*startarg != '(')
2720 {
Bram Moolenaar81bf7082005-02-12 14:31:42 +00002721 EMSG2(_("E107: Missing braces: %s"), eap->arg);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002722 goto end;
2723 }
2724
2725 /*
2726 * When skipping, evaluate the function once, to find the end of the
2727 * arguments.
2728 * When the function takes a range, this is discovered after the first
2729 * call, and the loop is broken.
2730 */
2731 if (eap->skip)
2732 {
2733 ++emsg_skip;
2734 lnum = eap->line2; /* do it once, also with an invalid range */
2735 }
2736 else
2737 lnum = eap->line1;
2738 for ( ; lnum <= eap->line2; ++lnum)
2739 {
2740 if (!eap->skip && eap->addr_count > 0)
2741 {
2742 curwin->w_cursor.lnum = lnum;
2743 curwin->w_cursor.col = 0;
2744 }
2745 arg = startarg;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002746 if (get_func_tv(name, STRLEN(name), &rettv, &arg,
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00002747 eap->line1, eap->line2, &doesrange,
2748 !eap->skip, fudi.fd_dict) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002749 {
2750 failed = TRUE;
2751 break;
2752 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002753 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002754 if (doesrange || eap->skip)
2755 break;
2756 /* Stop when immediately aborting on error, or when an interrupt
Bram Moolenaar49cd9572005-01-03 21:06:01 +00002757 * occurred or an exception was thrown but not caught.
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002758 * get_func_tv() returned OK, so that the check for trailing
Bram Moolenaar49cd9572005-01-03 21:06:01 +00002759 * characters below is executed. */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002760 if (aborting())
2761 break;
2762 }
2763 if (eap->skip)
2764 --emsg_skip;
2765
2766 if (!failed)
2767 {
2768 /* Check for trailing illegal characters and a following command. */
2769 if (!ends_excmd(*arg))
2770 {
2771 emsg_severe = TRUE;
2772 EMSG(_(e_trailing));
2773 }
2774 else
2775 eap->nextcmd = check_nextcmd(arg);
2776 }
2777
2778end:
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00002779 dict_unref(fudi.fd_dict);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002780 vim_free(tofree);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002781}
2782
2783/*
2784 * ":unlet[!] var1 ... " command.
2785 */
2786 void
2787ex_unlet(eap)
2788 exarg_T *eap;
2789{
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00002790 ex_unletlock(eap, eap->arg, 0);
2791}
2792
2793/*
2794 * ":lockvar" and ":unlockvar" commands
2795 */
2796 void
2797ex_lockvar(eap)
2798 exarg_T *eap;
2799{
Bram Moolenaar071d4272004-06-13 20:20:40 +00002800 char_u *arg = eap->arg;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00002801 int deep = 2;
2802
2803 if (eap->forceit)
2804 deep = -1;
2805 else if (vim_isdigit(*arg))
2806 {
2807 deep = getdigits(&arg);
2808 arg = skipwhite(arg);
2809 }
2810
2811 ex_unletlock(eap, arg, deep);
2812}
2813
2814/*
2815 * ":unlet", ":lockvar" and ":unlockvar" are quite similar.
2816 */
2817 static void
2818ex_unletlock(eap, argstart, deep)
2819 exarg_T *eap;
2820 char_u *argstart;
2821 int deep;
2822{
2823 char_u *arg = argstart;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002824 char_u *name_end;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002825 int error = FALSE;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00002826 lval_T lv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002827
2828 do
2829 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002830 /* Parse the name and find the end. */
2831 name_end = get_lval(arg, NULL, &lv, TRUE, eap->skip || error, FALSE);
2832 if (lv.ll_name == NULL)
2833 error = TRUE; /* error but continue parsing */
2834 if (name_end == NULL || (!vim_iswhite(*name_end)
2835 && !ends_excmd(*name_end)))
Bram Moolenaar071d4272004-06-13 20:20:40 +00002836 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002837 if (name_end != NULL)
2838 {
2839 emsg_severe = TRUE;
2840 EMSG(_(e_trailing));
2841 }
2842 if (!(eap->skip || error))
2843 clear_lval(&lv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002844 break;
2845 }
2846
2847 if (!error && !eap->skip)
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00002848 {
2849 if (eap->cmdidx == CMD_unlet)
2850 {
2851 if (do_unlet_var(&lv, name_end, eap->forceit) == FAIL)
2852 error = TRUE;
2853 }
2854 else
2855 {
2856 if (do_lock_var(&lv, name_end, deep,
2857 eap->cmdidx == CMD_lockvar) == FAIL)
2858 error = TRUE;
2859 }
2860 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00002861
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002862 if (!eap->skip)
2863 clear_lval(&lv);
2864
Bram Moolenaar071d4272004-06-13 20:20:40 +00002865 arg = skipwhite(name_end);
2866 } while (!ends_excmd(*arg));
2867
2868 eap->nextcmd = check_nextcmd(arg);
2869}
2870
Bram Moolenaar8c711452005-01-14 21:53:12 +00002871 static int
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002872do_unlet_var(lp, name_end, forceit)
Bram Moolenaar33570922005-01-25 22:26:29 +00002873 lval_T *lp;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002874 char_u *name_end;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002875 int forceit;
2876{
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002877 int ret = OK;
2878 int cc;
2879
2880 if (lp->ll_tv == NULL)
Bram Moolenaar8c711452005-01-14 21:53:12 +00002881 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002882 cc = *name_end;
2883 *name_end = NUL;
2884
2885 /* Normal name or expanded name. */
2886 if (check_changedtick(lp->ll_name))
2887 ret = FAIL;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00002888 else if (do_unlet(lp->ll_name, forceit) == FAIL)
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002889 ret = FAIL;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002890 *name_end = cc;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002891 }
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00002892 else if (tv_check_lock(lp->ll_tv->v_lock, lp->ll_name))
2893 return FAIL;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002894 else if (lp->ll_range)
2895 {
Bram Moolenaar33570922005-01-25 22:26:29 +00002896 listitem_T *li;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002897
2898 /* Delete a range of List items. */
2899 while (lp->ll_li != NULL && (lp->ll_empty2 || lp->ll_n2 >= lp->ll_n1))
2900 {
2901 li = lp->ll_li->li_next;
2902 listitem_remove(lp->ll_list, lp->ll_li);
2903 lp->ll_li = li;
2904 ++lp->ll_n1;
2905 }
2906 }
2907 else
2908 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002909 if (lp->ll_list != NULL)
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002910 /* unlet a List item. */
2911 listitem_remove(lp->ll_list, lp->ll_li);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002912 else
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002913 /* unlet a Dictionary item. */
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00002914 dictitem_remove(lp->ll_dict, lp->ll_di);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002915 }
2916
2917 return ret;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002918}
2919
Bram Moolenaar071d4272004-06-13 20:20:40 +00002920/*
2921 * "unlet" a variable. Return OK if it existed, FAIL if not.
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00002922 * When "forceit" is TRUE don't complain if the variable doesn't exist.
Bram Moolenaar071d4272004-06-13 20:20:40 +00002923 */
2924 int
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00002925do_unlet(name, forceit)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002926 char_u *name;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00002927 int forceit;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002928{
Bram Moolenaar33570922005-01-25 22:26:29 +00002929 hashtab_T *ht;
2930 hashitem_T *hi;
Bram Moolenaara7043832005-01-21 11:56:39 +00002931 char_u *varname;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002932
Bram Moolenaar33570922005-01-25 22:26:29 +00002933 ht = find_var_ht(name, &varname);
2934 if (ht != NULL && *varname != NUL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002935 {
Bram Moolenaar33570922005-01-25 22:26:29 +00002936 hi = hash_find(ht, varname);
2937 if (!HASHITEM_EMPTY(hi))
Bram Moolenaara7043832005-01-21 11:56:39 +00002938 {
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00002939 if (var_check_ro(HI2DI(hi)->di_flags, name))
2940 return FAIL;
2941 delete_var(ht, hi);
2942 return OK;
Bram Moolenaara7043832005-01-21 11:56:39 +00002943 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00002944 }
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00002945 if (forceit)
2946 return OK;
2947 EMSG2(_("E108: No such variable: \"%s\""), name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002948 return FAIL;
2949}
2950
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00002951/*
2952 * Lock or unlock variable indicated by "lp".
2953 * "deep" is the levels to go (-1 for unlimited);
2954 * "lock" is TRUE for ":lockvar", FALSE for ":unlockvar".
2955 */
2956 static int
2957do_lock_var(lp, name_end, deep, lock)
2958 lval_T *lp;
2959 char_u *name_end;
2960 int deep;
2961 int lock;
2962{
2963 int ret = OK;
2964 int cc;
2965 dictitem_T *di;
2966
2967 if (deep == 0) /* nothing to do */
2968 return OK;
2969
2970 if (lp->ll_tv == NULL)
2971 {
2972 cc = *name_end;
2973 *name_end = NUL;
2974
2975 /* Normal name or expanded name. */
2976 if (check_changedtick(lp->ll_name))
2977 ret = FAIL;
2978 else
2979 {
2980 di = find_var(lp->ll_name, NULL);
2981 if (di == NULL)
2982 ret = FAIL;
2983 else
2984 {
2985 if (lock)
2986 di->di_flags |= DI_FLAGS_LOCK;
2987 else
2988 di->di_flags &= ~DI_FLAGS_LOCK;
2989 item_lock(&di->di_tv, deep, lock);
2990 }
2991 }
2992 *name_end = cc;
2993 }
2994 else if (lp->ll_range)
2995 {
2996 listitem_T *li = lp->ll_li;
2997
2998 /* (un)lock a range of List items. */
2999 while (li != NULL && (lp->ll_empty2 || lp->ll_n2 >= lp->ll_n1))
3000 {
3001 item_lock(&li->li_tv, deep, lock);
3002 li = li->li_next;
3003 ++lp->ll_n1;
3004 }
3005 }
3006 else if (lp->ll_list != NULL)
3007 /* (un)lock a List item. */
3008 item_lock(&lp->ll_li->li_tv, deep, lock);
3009 else
3010 /* un(lock) a Dictionary item. */
3011 item_lock(&lp->ll_di->di_tv, deep, lock);
3012
3013 return ret;
3014}
3015
3016/*
3017 * Lock or unlock an item. "deep" is nr of levels to go.
3018 */
3019 static void
3020item_lock(tv, deep, lock)
3021 typval_T *tv;
3022 int deep;
3023 int lock;
3024{
3025 static int recurse = 0;
3026 list_T *l;
3027 listitem_T *li;
3028 dict_T *d;
3029 hashitem_T *hi;
3030 int todo;
3031
3032 if (recurse >= DICT_MAXNEST)
3033 {
3034 EMSG(_("E743: variable nested too deep for (un)lock"));
3035 return;
3036 }
3037 if (deep == 0)
3038 return;
3039 ++recurse;
3040
3041 /* lock/unlock the item itself */
3042 if (lock)
3043 tv->v_lock |= VAR_LOCKED;
3044 else
3045 tv->v_lock &= ~VAR_LOCKED;
3046
3047 switch (tv->v_type)
3048 {
3049 case VAR_LIST:
3050 if ((l = tv->vval.v_list) != NULL)
3051 {
3052 if (lock)
3053 l->lv_lock |= VAR_LOCKED;
3054 else
3055 l->lv_lock &= ~VAR_LOCKED;
3056 if (deep < 0 || deep > 1)
3057 /* recursive: lock/unlock the items the List contains */
3058 for (li = l->lv_first; li != NULL; li = li->li_next)
3059 item_lock(&li->li_tv, deep - 1, lock);
3060 }
3061 break;
3062 case VAR_DICT:
3063 if ((d = tv->vval.v_dict) != NULL)
3064 {
3065 if (lock)
3066 d->dv_lock |= VAR_LOCKED;
3067 else
3068 d->dv_lock &= ~VAR_LOCKED;
3069 if (deep < 0 || deep > 1)
3070 {
3071 /* recursive: lock/unlock the items the List contains */
3072 todo = d->dv_hashtab.ht_used;
3073 for (hi = d->dv_hashtab.ht_array; todo > 0; ++hi)
3074 {
3075 if (!HASHITEM_EMPTY(hi))
3076 {
3077 --todo;
3078 item_lock(&HI2DI(hi)->di_tv, deep - 1, lock);
3079 }
3080 }
3081 }
3082 }
3083 }
3084 --recurse;
3085}
3086
Bram Moolenaar071d4272004-06-13 20:20:40 +00003087#if (defined(FEAT_MENU) && defined(FEAT_MULTI_LANG)) || defined(PROTO)
3088/*
3089 * Delete all "menutrans_" variables.
3090 */
3091 void
3092del_menutrans_vars()
3093{
Bram Moolenaar33570922005-01-25 22:26:29 +00003094 hashitem_T *hi;
Bram Moolenaara7043832005-01-21 11:56:39 +00003095 int todo;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003096
Bram Moolenaar33570922005-01-25 22:26:29 +00003097 hash_lock(&globvarht);
3098 todo = globvarht.ht_used;
3099 for (hi = globvarht.ht_array; todo > 0 && !got_int; ++hi)
Bram Moolenaara7043832005-01-21 11:56:39 +00003100 {
3101 if (!HASHITEM_EMPTY(hi))
3102 {
3103 --todo;
Bram Moolenaar33570922005-01-25 22:26:29 +00003104 if (STRNCMP(HI2DI(hi)->di_key, "menutrans_", 10) == 0)
3105 delete_var(&globvarht, hi);
Bram Moolenaara7043832005-01-21 11:56:39 +00003106 }
3107 }
Bram Moolenaar33570922005-01-25 22:26:29 +00003108 hash_unlock(&globvarht);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003109}
3110#endif
3111
3112#if defined(FEAT_CMDL_COMPL) || defined(PROTO)
3113
3114/*
3115 * Local string buffer for the next two functions to store a variable name
3116 * with its prefix. Allocated in cat_prefix_varname(), freed later in
3117 * get_user_var_name().
3118 */
3119
3120static char_u *cat_prefix_varname __ARGS((int prefix, char_u *name));
3121
3122static char_u *varnamebuf = NULL;
3123static int varnamebuflen = 0;
3124
3125/*
3126 * Function to concatenate a prefix and a variable name.
3127 */
3128 static char_u *
3129cat_prefix_varname(prefix, name)
3130 int prefix;
3131 char_u *name;
3132{
3133 int len;
3134
3135 len = (int)STRLEN(name) + 3;
3136 if (len > varnamebuflen)
3137 {
3138 vim_free(varnamebuf);
3139 len += 10; /* some additional space */
3140 varnamebuf = alloc(len);
3141 if (varnamebuf == NULL)
3142 {
3143 varnamebuflen = 0;
3144 return NULL;
3145 }
3146 varnamebuflen = len;
3147 }
3148 *varnamebuf = prefix;
3149 varnamebuf[1] = ':';
3150 STRCPY(varnamebuf + 2, name);
3151 return varnamebuf;
3152}
3153
3154/*
3155 * Function given to ExpandGeneric() to obtain the list of user defined
3156 * (global/buffer/window/built-in) variable names.
3157 */
3158/*ARGSUSED*/
3159 char_u *
3160get_user_var_name(xp, idx)
3161 expand_T *xp;
3162 int idx;
3163{
Bram Moolenaar532c7802005-01-27 14:44:31 +00003164 static long_u gdone;
3165 static long_u bdone;
3166 static long_u wdone;
3167 static int vidx;
3168 static hashitem_T *hi;
3169 hashtab_T *ht;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003170
3171 if (idx == 0)
Bram Moolenaara7043832005-01-21 11:56:39 +00003172 gdone = bdone = wdone = vidx = 0;
Bram Moolenaar33570922005-01-25 22:26:29 +00003173
3174 /* Global variables */
3175 if (gdone < globvarht.ht_used)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003176 {
Bram Moolenaara7043832005-01-21 11:56:39 +00003177 if (gdone++ == 0)
Bram Moolenaar33570922005-01-25 22:26:29 +00003178 hi = globvarht.ht_array;
Bram Moolenaar532c7802005-01-27 14:44:31 +00003179 else
3180 ++hi;
Bram Moolenaara7043832005-01-21 11:56:39 +00003181 while (HASHITEM_EMPTY(hi))
3182 ++hi;
3183 if (STRNCMP("g:", xp->xp_pattern, 2) == 0)
3184 return cat_prefix_varname('g', hi->hi_key);
3185 return hi->hi_key;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003186 }
Bram Moolenaar33570922005-01-25 22:26:29 +00003187
3188 /* b: variables */
3189 ht = &curbuf->b_vars.dv_hashtab;
3190 if (bdone < ht->ht_used)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003191 {
Bram Moolenaara7043832005-01-21 11:56:39 +00003192 if (bdone++ == 0)
Bram Moolenaar33570922005-01-25 22:26:29 +00003193 hi = ht->ht_array;
Bram Moolenaar532c7802005-01-27 14:44:31 +00003194 else
3195 ++hi;
Bram Moolenaara7043832005-01-21 11:56:39 +00003196 while (HASHITEM_EMPTY(hi))
3197 ++hi;
3198 return cat_prefix_varname('b', hi->hi_key);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003199 }
Bram Moolenaar33570922005-01-25 22:26:29 +00003200 if (bdone == ht->ht_used)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003201 {
Bram Moolenaara7043832005-01-21 11:56:39 +00003202 ++bdone;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003203 return (char_u *)"b:changedtick";
3204 }
Bram Moolenaar33570922005-01-25 22:26:29 +00003205
3206 /* w: variables */
3207 ht = &curwin->w_vars.dv_hashtab;
3208 if (wdone < ht->ht_used)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003209 {
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +00003210 if (wdone++ == 0)
Bram Moolenaar33570922005-01-25 22:26:29 +00003211 hi = ht->ht_array;
Bram Moolenaar532c7802005-01-27 14:44:31 +00003212 else
3213 ++hi;
Bram Moolenaara7043832005-01-21 11:56:39 +00003214 while (HASHITEM_EMPTY(hi))
3215 ++hi;
3216 return cat_prefix_varname('w', hi->hi_key);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003217 }
Bram Moolenaar33570922005-01-25 22:26:29 +00003218
3219 /* v: variables */
3220 if (vidx < VV_LEN)
3221 return cat_prefix_varname('v', (char_u *)vimvars[vidx++].vv_name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003222
3223 vim_free(varnamebuf);
3224 varnamebuf = NULL;
3225 varnamebuflen = 0;
3226 return NULL;
3227}
3228
3229#endif /* FEAT_CMDL_COMPL */
3230
3231/*
3232 * types for expressions.
3233 */
3234typedef enum
3235{
3236 TYPE_UNKNOWN = 0
3237 , TYPE_EQUAL /* == */
3238 , TYPE_NEQUAL /* != */
3239 , TYPE_GREATER /* > */
3240 , TYPE_GEQUAL /* >= */
3241 , TYPE_SMALLER /* < */
3242 , TYPE_SEQUAL /* <= */
3243 , TYPE_MATCH /* =~ */
3244 , TYPE_NOMATCH /* !~ */
3245} exptype_T;
3246
3247/*
3248 * The "evaluate" argument: When FALSE, the argument is only parsed but not
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003249 * executed. The function may return OK, but the rettv will be of type
Bram Moolenaar071d4272004-06-13 20:20:40 +00003250 * VAR_UNKNOWN. The function still returns FAIL for a syntax error.
3251 */
3252
3253/*
3254 * Handle zero level expression.
3255 * This calls eval1() and handles error message and nextcmd.
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003256 * Put the result in "rettv" when returning OK and "evaluate" is TRUE.
Bram Moolenaar071d4272004-06-13 20:20:40 +00003257 * Return OK or FAIL.
3258 */
3259 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003260eval0(arg, rettv, nextcmd, evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003261 char_u *arg;
Bram Moolenaar33570922005-01-25 22:26:29 +00003262 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003263 char_u **nextcmd;
3264 int evaluate;
3265{
3266 int ret;
3267 char_u *p;
3268
3269 p = skipwhite(arg);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003270 ret = eval1(&p, rettv, evaluate);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003271 if (ret == FAIL || !ends_excmd(*p))
3272 {
3273 if (ret != FAIL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003274 clear_tv(rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003275 /*
3276 * Report the invalid expression unless the expression evaluation has
3277 * been cancelled due to an aborting error, an interrupt, or an
3278 * exception.
3279 */
3280 if (!aborting())
3281 EMSG2(_(e_invexpr2), arg);
3282 ret = FAIL;
3283 }
3284 if (nextcmd != NULL)
3285 *nextcmd = check_nextcmd(p);
3286
3287 return ret;
3288}
3289
3290/*
3291 * Handle top level expression:
3292 * expr1 ? expr0 : expr0
3293 *
3294 * "arg" must point to the first non-white of the expression.
3295 * "arg" is advanced to the next non-white after the recognized expression.
3296 *
3297 * Return OK or FAIL.
3298 */
3299 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003300eval1(arg, rettv, evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003301 char_u **arg;
Bram Moolenaar33570922005-01-25 22:26:29 +00003302 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003303 int evaluate;
3304{
3305 int result;
Bram Moolenaar33570922005-01-25 22:26:29 +00003306 typval_T var2;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003307
3308 /*
3309 * Get the first variable.
3310 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003311 if (eval2(arg, rettv, evaluate) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003312 return FAIL;
3313
3314 if ((*arg)[0] == '?')
3315 {
3316 result = FALSE;
3317 if (evaluate)
3318 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003319 if (get_tv_number(rettv) != 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003320 result = TRUE;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003321 clear_tv(rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003322 }
3323
3324 /*
3325 * Get the second variable.
3326 */
3327 *arg = skipwhite(*arg + 1);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003328 if (eval1(arg, rettv, evaluate && result) == FAIL) /* recursive! */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003329 return FAIL;
3330
3331 /*
3332 * Check for the ":".
3333 */
3334 if ((*arg)[0] != ':')
3335 {
3336 EMSG(_("E109: Missing ':' after '?'"));
3337 if (evaluate && result)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003338 clear_tv(rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003339 return FAIL;
3340 }
3341
3342 /*
3343 * Get the third variable.
3344 */
3345 *arg = skipwhite(*arg + 1);
3346 if (eval1(arg, &var2, evaluate && !result) == FAIL) /* recursive! */
3347 {
3348 if (evaluate && result)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003349 clear_tv(rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003350 return FAIL;
3351 }
3352 if (evaluate && !result)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003353 *rettv = var2;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003354 }
3355
3356 return OK;
3357}
3358
3359/*
3360 * Handle first level expression:
3361 * expr2 || expr2 || expr2 logical OR
3362 *
3363 * "arg" must point to the first non-white of the expression.
3364 * "arg" is advanced to the next non-white after the recognized expression.
3365 *
3366 * Return OK or FAIL.
3367 */
3368 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003369eval2(arg, rettv, evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003370 char_u **arg;
Bram Moolenaar33570922005-01-25 22:26:29 +00003371 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003372 int evaluate;
3373{
Bram Moolenaar33570922005-01-25 22:26:29 +00003374 typval_T var2;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003375 long result;
3376 int first;
3377
3378 /*
3379 * Get the first variable.
3380 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003381 if (eval3(arg, rettv, evaluate) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003382 return FAIL;
3383
3384 /*
3385 * Repeat until there is no following "||".
3386 */
3387 first = TRUE;
3388 result = FALSE;
3389 while ((*arg)[0] == '|' && (*arg)[1] == '|')
3390 {
3391 if (evaluate && first)
3392 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003393 if (get_tv_number(rettv) != 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003394 result = TRUE;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003395 clear_tv(rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003396 first = FALSE;
3397 }
3398
3399 /*
3400 * Get the second variable.
3401 */
3402 *arg = skipwhite(*arg + 2);
3403 if (eval3(arg, &var2, evaluate && !result) == FAIL)
3404 return FAIL;
3405
3406 /*
3407 * Compute the result.
3408 */
3409 if (evaluate && !result)
3410 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003411 if (get_tv_number(&var2) != 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003412 result = TRUE;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003413 clear_tv(&var2);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003414 }
3415 if (evaluate)
3416 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003417 rettv->v_type = VAR_NUMBER;
3418 rettv->vval.v_number = result;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003419 }
3420 }
3421
3422 return OK;
3423}
3424
3425/*
3426 * Handle second level expression:
3427 * expr3 && expr3 && expr3 logical AND
3428 *
3429 * "arg" must point to the first non-white of the expression.
3430 * "arg" is advanced to the next non-white after the recognized expression.
3431 *
3432 * Return OK or FAIL.
3433 */
3434 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003435eval3(arg, rettv, evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003436 char_u **arg;
Bram Moolenaar33570922005-01-25 22:26:29 +00003437 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003438 int evaluate;
3439{
Bram Moolenaar33570922005-01-25 22:26:29 +00003440 typval_T var2;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003441 long result;
3442 int first;
3443
3444 /*
3445 * Get the first variable.
3446 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003447 if (eval4(arg, rettv, evaluate) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003448 return FAIL;
3449
3450 /*
3451 * Repeat until there is no following "&&".
3452 */
3453 first = TRUE;
3454 result = TRUE;
3455 while ((*arg)[0] == '&' && (*arg)[1] == '&')
3456 {
3457 if (evaluate && first)
3458 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003459 if (get_tv_number(rettv) == 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003460 result = FALSE;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003461 clear_tv(rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003462 first = FALSE;
3463 }
3464
3465 /*
3466 * Get the second variable.
3467 */
3468 *arg = skipwhite(*arg + 2);
3469 if (eval4(arg, &var2, evaluate && result) == FAIL)
3470 return FAIL;
3471
3472 /*
3473 * Compute the result.
3474 */
3475 if (evaluate && result)
3476 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003477 if (get_tv_number(&var2) == 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003478 result = FALSE;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003479 clear_tv(&var2);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003480 }
3481 if (evaluate)
3482 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003483 rettv->v_type = VAR_NUMBER;
3484 rettv->vval.v_number = result;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003485 }
3486 }
3487
3488 return OK;
3489}
3490
3491/*
3492 * Handle third level expression:
3493 * var1 == var2
3494 * var1 =~ var2
3495 * var1 != var2
3496 * var1 !~ var2
3497 * var1 > var2
3498 * var1 >= var2
3499 * var1 < var2
3500 * var1 <= var2
Bram Moolenaar8a283e52005-01-06 23:28:25 +00003501 * var1 is var2
3502 * var1 isnot var2
Bram Moolenaar071d4272004-06-13 20:20:40 +00003503 *
3504 * "arg" must point to the first non-white of the expression.
3505 * "arg" is advanced to the next non-white after the recognized expression.
3506 *
3507 * Return OK or FAIL.
3508 */
3509 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003510eval4(arg, rettv, evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003511 char_u **arg;
Bram Moolenaar33570922005-01-25 22:26:29 +00003512 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003513 int evaluate;
3514{
Bram Moolenaar33570922005-01-25 22:26:29 +00003515 typval_T var2;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003516 char_u *p;
3517 int i;
3518 exptype_T type = TYPE_UNKNOWN;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00003519 int type_is = FALSE; /* TRUE for "is" and "isnot" */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003520 int len = 2;
3521 long n1, n2;
3522 char_u *s1, *s2;
3523 char_u buf1[NUMBUFLEN], buf2[NUMBUFLEN];
3524 regmatch_T regmatch;
3525 int ic;
3526 char_u *save_cpo;
3527
3528 /*
3529 * Get the first variable.
3530 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003531 if (eval5(arg, rettv, evaluate) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003532 return FAIL;
3533
3534 p = *arg;
3535 switch (p[0])
3536 {
3537 case '=': if (p[1] == '=')
3538 type = TYPE_EQUAL;
3539 else if (p[1] == '~')
3540 type = TYPE_MATCH;
3541 break;
3542 case '!': if (p[1] == '=')
3543 type = TYPE_NEQUAL;
3544 else if (p[1] == '~')
3545 type = TYPE_NOMATCH;
3546 break;
3547 case '>': if (p[1] != '=')
3548 {
3549 type = TYPE_GREATER;
3550 len = 1;
3551 }
3552 else
3553 type = TYPE_GEQUAL;
3554 break;
3555 case '<': if (p[1] != '=')
3556 {
3557 type = TYPE_SMALLER;
3558 len = 1;
3559 }
3560 else
3561 type = TYPE_SEQUAL;
3562 break;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00003563 case 'i': if (p[1] == 's')
3564 {
3565 if (p[2] == 'n' && p[3] == 'o' && p[4] == 't')
3566 len = 5;
3567 if (!vim_isIDc(p[len]))
3568 {
3569 type = len == 2 ? TYPE_EQUAL : TYPE_NEQUAL;
3570 type_is = TRUE;
3571 }
3572 }
3573 break;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003574 }
3575
3576 /*
3577 * If there is a comparitive operator, use it.
3578 */
3579 if (type != TYPE_UNKNOWN)
3580 {
3581 /* extra question mark appended: ignore case */
3582 if (p[len] == '?')
3583 {
3584 ic = TRUE;
3585 ++len;
3586 }
3587 /* extra '#' appended: match case */
3588 else if (p[len] == '#')
3589 {
3590 ic = FALSE;
3591 ++len;
3592 }
3593 /* nothing appened: use 'ignorecase' */
3594 else
3595 ic = p_ic;
3596
3597 /*
3598 * Get the second variable.
3599 */
3600 *arg = skipwhite(p + len);
3601 if (eval5(arg, &var2, evaluate) == FAIL)
3602 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003603 clear_tv(rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003604 return FAIL;
3605 }
3606
3607 if (evaluate)
3608 {
Bram Moolenaar8a283e52005-01-06 23:28:25 +00003609 if (type_is && rettv->v_type != var2.v_type)
3610 {
3611 /* For "is" a different type always means FALSE, for "notis"
3612 * it means TRUE. */
3613 n1 = (type == TYPE_NEQUAL);
3614 }
3615 else if (rettv->v_type == VAR_LIST || var2.v_type == VAR_LIST)
3616 {
3617 if (type_is)
3618 {
3619 n1 = (rettv->v_type == var2.v_type
3620 && rettv->vval.v_list == var2.vval.v_list);
3621 if (type == TYPE_NEQUAL)
3622 n1 = !n1;
3623 }
3624 else if (rettv->v_type != var2.v_type
3625 || (type != TYPE_EQUAL && type != TYPE_NEQUAL))
3626 {
3627 if (rettv->v_type != var2.v_type)
Bram Moolenaare49b69a2005-01-08 16:11:57 +00003628 EMSG(_("E691: Can only compare List with List"));
Bram Moolenaar8a283e52005-01-06 23:28:25 +00003629 else
Bram Moolenaare49b69a2005-01-08 16:11:57 +00003630 EMSG(_("E692: Invalid operation for Lists"));
Bram Moolenaar8a283e52005-01-06 23:28:25 +00003631 clear_tv(rettv);
3632 clear_tv(&var2);
3633 return FAIL;
3634 }
3635 else
3636 {
3637 /* Compare two Lists for being equal or unequal. */
3638 n1 = list_equal(rettv->vval.v_list, var2.vval.v_list, ic);
3639 if (type == TYPE_NEQUAL)
3640 n1 = !n1;
3641 }
3642 }
3643
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00003644 else if (rettv->v_type == VAR_DICT || var2.v_type == VAR_DICT)
3645 {
3646 if (type_is)
3647 {
3648 n1 = (rettv->v_type == var2.v_type
3649 && rettv->vval.v_dict == var2.vval.v_dict);
3650 if (type == TYPE_NEQUAL)
3651 n1 = !n1;
3652 }
3653 else if (rettv->v_type != var2.v_type
3654 || (type != TYPE_EQUAL && type != TYPE_NEQUAL))
3655 {
3656 if (rettv->v_type != var2.v_type)
3657 EMSG(_("E735: Can only compare Dictionary with Dictionary"));
3658 else
3659 EMSG(_("E736: Invalid operation for Dictionary"));
3660 clear_tv(rettv);
3661 clear_tv(&var2);
3662 return FAIL;
3663 }
3664 else
3665 {
3666 /* Compare two Dictionaries for being equal or unequal. */
3667 n1 = dict_equal(rettv->vval.v_dict, var2.vval.v_dict, ic);
3668 if (type == TYPE_NEQUAL)
3669 n1 = !n1;
3670 }
3671 }
3672
Bram Moolenaar8a283e52005-01-06 23:28:25 +00003673 else if (rettv->v_type == VAR_FUNC || var2.v_type == VAR_FUNC)
3674 {
3675 if (rettv->v_type != var2.v_type
3676 || (type != TYPE_EQUAL && type != TYPE_NEQUAL))
3677 {
3678 if (rettv->v_type != var2.v_type)
Bram Moolenaare49b69a2005-01-08 16:11:57 +00003679 EMSG(_("E693: Can only compare Funcref with Funcref"));
Bram Moolenaar8a283e52005-01-06 23:28:25 +00003680 else
Bram Moolenaare49b69a2005-01-08 16:11:57 +00003681 EMSG(_("E694: Invalid operation for Funcrefs"));
Bram Moolenaar8a283e52005-01-06 23:28:25 +00003682 clear_tv(rettv);
3683 clear_tv(&var2);
3684 return FAIL;
3685 }
3686 else
3687 {
3688 /* Compare two Funcrefs for being equal or unequal. */
3689 if (rettv->vval.v_string == NULL
3690 || var2.vval.v_string == NULL)
3691 n1 = FALSE;
3692 else
3693 n1 = STRCMP(rettv->vval.v_string,
3694 var2.vval.v_string) == 0;
3695 if (type == TYPE_NEQUAL)
3696 n1 = !n1;
3697 }
3698 }
3699
Bram Moolenaar071d4272004-06-13 20:20:40 +00003700 /*
3701 * If one of the two variables is a number, compare as a number.
3702 * When using "=~" or "!~", always compare as string.
3703 */
Bram Moolenaar8a283e52005-01-06 23:28:25 +00003704 else if ((rettv->v_type == VAR_NUMBER || var2.v_type == VAR_NUMBER)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003705 && type != TYPE_MATCH && type != TYPE_NOMATCH)
3706 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003707 n1 = get_tv_number(rettv);
3708 n2 = get_tv_number(&var2);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003709 switch (type)
3710 {
3711 case TYPE_EQUAL: n1 = (n1 == n2); break;
3712 case TYPE_NEQUAL: n1 = (n1 != n2); break;
3713 case TYPE_GREATER: n1 = (n1 > n2); break;
3714 case TYPE_GEQUAL: n1 = (n1 >= n2); break;
3715 case TYPE_SMALLER: n1 = (n1 < n2); break;
3716 case TYPE_SEQUAL: n1 = (n1 <= n2); break;
3717 case TYPE_UNKNOWN:
3718 case TYPE_MATCH:
3719 case TYPE_NOMATCH: break; /* avoid gcc warning */
3720 }
3721 }
3722 else
3723 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003724 s1 = get_tv_string_buf(rettv, buf1);
3725 s2 = get_tv_string_buf(&var2, buf2);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003726 if (type != TYPE_MATCH && type != TYPE_NOMATCH)
3727 i = ic ? MB_STRICMP(s1, s2) : STRCMP(s1, s2);
3728 else
3729 i = 0;
3730 n1 = FALSE;
3731 switch (type)
3732 {
3733 case TYPE_EQUAL: n1 = (i == 0); break;
3734 case TYPE_NEQUAL: n1 = (i != 0); break;
3735 case TYPE_GREATER: n1 = (i > 0); break;
3736 case TYPE_GEQUAL: n1 = (i >= 0); break;
3737 case TYPE_SMALLER: n1 = (i < 0); break;
3738 case TYPE_SEQUAL: n1 = (i <= 0); break;
3739
3740 case TYPE_MATCH:
3741 case TYPE_NOMATCH:
3742 /* avoid 'l' flag in 'cpoptions' */
3743 save_cpo = p_cpo;
3744 p_cpo = (char_u *)"";
3745 regmatch.regprog = vim_regcomp(s2,
3746 RE_MAGIC + RE_STRING);
3747 regmatch.rm_ic = ic;
3748 if (regmatch.regprog != NULL)
3749 {
3750 n1 = vim_regexec_nl(&regmatch, s1, (colnr_T)0);
3751 vim_free(regmatch.regprog);
3752 if (type == TYPE_NOMATCH)
3753 n1 = !n1;
3754 }
3755 p_cpo = save_cpo;
3756 break;
3757
3758 case TYPE_UNKNOWN: break; /* avoid gcc warning */
3759 }
3760 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003761 clear_tv(rettv);
3762 clear_tv(&var2);
3763 rettv->v_type = VAR_NUMBER;
3764 rettv->vval.v_number = n1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003765 }
3766 }
3767
3768 return OK;
3769}
3770
3771/*
3772 * Handle fourth level expression:
3773 * + number addition
3774 * - number subtraction
3775 * . string concatenation
3776 *
3777 * "arg" must point to the first non-white of the expression.
3778 * "arg" is advanced to the next non-white after the recognized expression.
3779 *
3780 * Return OK or FAIL.
3781 */
3782 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003783eval5(arg, rettv, evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003784 char_u **arg;
Bram Moolenaar33570922005-01-25 22:26:29 +00003785 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003786 int evaluate;
3787{
Bram Moolenaar33570922005-01-25 22:26:29 +00003788 typval_T var2;
3789 typval_T var3;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003790 int op;
3791 long n1, n2;
3792 char_u *s1, *s2;
3793 char_u buf1[NUMBUFLEN], buf2[NUMBUFLEN];
3794 char_u *p;
3795
3796 /*
3797 * Get the first variable.
3798 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003799 if (eval6(arg, rettv, evaluate) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003800 return FAIL;
3801
3802 /*
3803 * Repeat computing, until no '+', '-' or '.' is following.
3804 */
3805 for (;;)
3806 {
3807 op = **arg;
3808 if (op != '+' && op != '-' && op != '.')
3809 break;
3810
3811 /*
3812 * Get the second variable.
3813 */
3814 *arg = skipwhite(*arg + 1);
3815 if (eval6(arg, &var2, evaluate) == FAIL)
3816 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003817 clear_tv(rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003818 return FAIL;
3819 }
3820
3821 if (evaluate)
3822 {
3823 /*
3824 * Compute the result.
3825 */
3826 if (op == '.')
3827 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003828 s1 = get_tv_string_buf(rettv, buf1);
3829 s2 = get_tv_string_buf(&var2, buf2);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00003830 p = concat_str(s1, s2);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003831 clear_tv(rettv);
3832 rettv->v_type = VAR_STRING;
3833 rettv->vval.v_string = p;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003834 }
Bram Moolenaare9a41262005-01-15 22:18:47 +00003835 else if (op == '+' && rettv->v_type == VAR_LIST
3836 && var2.v_type == VAR_LIST)
Bram Moolenaar8a283e52005-01-06 23:28:25 +00003837 {
3838 /* concatenate Lists */
3839 if (list_concat(rettv->vval.v_list, var2.vval.v_list,
3840 &var3) == FAIL)
3841 {
3842 clear_tv(rettv);
3843 clear_tv(&var2);
3844 return FAIL;
3845 }
3846 clear_tv(rettv);
3847 *rettv = var3;
3848 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00003849 else
3850 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003851 n1 = get_tv_number(rettv);
3852 n2 = get_tv_number(&var2);
3853 clear_tv(rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003854 if (op == '+')
3855 n1 = n1 + n2;
3856 else
3857 n1 = n1 - n2;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003858 rettv->v_type = VAR_NUMBER;
3859 rettv->vval.v_number = n1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003860 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003861 clear_tv(&var2);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003862 }
3863 }
3864 return OK;
3865}
3866
3867/*
3868 * Handle fifth level expression:
3869 * * number multiplication
3870 * / number division
3871 * % number modulo
3872 *
3873 * "arg" must point to the first non-white of the expression.
3874 * "arg" is advanced to the next non-white after the recognized expression.
3875 *
3876 * Return OK or FAIL.
3877 */
3878 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003879eval6(arg, rettv, evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003880 char_u **arg;
Bram Moolenaar33570922005-01-25 22:26:29 +00003881 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003882 int evaluate;
3883{
Bram Moolenaar33570922005-01-25 22:26:29 +00003884 typval_T var2;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003885 int op;
3886 long n1, n2;
3887
3888 /*
3889 * Get the first variable.
3890 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003891 if (eval7(arg, rettv, evaluate) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003892 return FAIL;
3893
3894 /*
3895 * Repeat computing, until no '*', '/' or '%' is following.
3896 */
3897 for (;;)
3898 {
3899 op = **arg;
3900 if (op != '*' && op != '/' && op != '%')
3901 break;
3902
3903 if (evaluate)
3904 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003905 n1 = get_tv_number(rettv);
3906 clear_tv(rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003907 }
3908 else
3909 n1 = 0;
3910
3911 /*
3912 * Get the second variable.
3913 */
3914 *arg = skipwhite(*arg + 1);
3915 if (eval7(arg, &var2, evaluate) == FAIL)
3916 return FAIL;
3917
3918 if (evaluate)
3919 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003920 n2 = get_tv_number(&var2);
3921 clear_tv(&var2);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003922
3923 /*
3924 * Compute the result.
3925 */
3926 if (op == '*')
3927 n1 = n1 * n2;
3928 else if (op == '/')
3929 {
3930 if (n2 == 0) /* give an error message? */
3931 n1 = 0x7fffffffL;
3932 else
3933 n1 = n1 / n2;
3934 }
3935 else
3936 {
3937 if (n2 == 0) /* give an error message? */
3938 n1 = 0;
3939 else
3940 n1 = n1 % n2;
3941 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003942 rettv->v_type = VAR_NUMBER;
3943 rettv->vval.v_number = n1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003944 }
3945 }
3946
3947 return OK;
3948}
3949
3950/*
3951 * Handle sixth level expression:
3952 * number number constant
3953 * "string" string contstant
3954 * 'string' literal string contstant
3955 * &option-name option value
3956 * @r register contents
3957 * identifier variable value
3958 * function() function call
3959 * $VAR environment variable
3960 * (expression) nested expression
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00003961 * [expr, expr] List
3962 * {key: val, key: val} Dictionary
Bram Moolenaar071d4272004-06-13 20:20:40 +00003963 *
3964 * Also handle:
3965 * ! in front logical NOT
3966 * - in front unary minus
3967 * + in front unary plus (ignored)
Bram Moolenaar8c711452005-01-14 21:53:12 +00003968 * trailing [] subscript in String or List
3969 * trailing .name entry in Dictionary
Bram Moolenaar071d4272004-06-13 20:20:40 +00003970 *
3971 * "arg" must point to the first non-white of the expression.
3972 * "arg" is advanced to the next non-white after the recognized expression.
3973 *
3974 * Return OK or FAIL.
3975 */
3976 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003977eval7(arg, rettv, evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003978 char_u **arg;
Bram Moolenaar33570922005-01-25 22:26:29 +00003979 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003980 int evaluate;
3981{
Bram Moolenaar071d4272004-06-13 20:20:40 +00003982 long n;
3983 int len;
3984 char_u *s;
3985 int val;
3986 char_u *start_leader, *end_leader;
3987 int ret = OK;
3988 char_u *alias;
3989
3990 /*
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003991 * Initialise variable so that clear_tv() can't mistake this for a
Bram Moolenaar49cd9572005-01-03 21:06:01 +00003992 * string and free a string that isn't there.
Bram Moolenaar071d4272004-06-13 20:20:40 +00003993 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003994 rettv->v_type = VAR_UNKNOWN;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003995
3996 /*
3997 * Skip '!' and '-' characters. They are handled later.
3998 */
3999 start_leader = *arg;
4000 while (**arg == '!' || **arg == '-' || **arg == '+')
4001 *arg = skipwhite(*arg + 1);
4002 end_leader = *arg;
4003
4004 switch (**arg)
4005 {
4006 /*
4007 * Number constant.
4008 */
4009 case '0':
4010 case '1':
4011 case '2':
4012 case '3':
4013 case '4':
4014 case '5':
4015 case '6':
4016 case '7':
4017 case '8':
4018 case '9':
4019 vim_str2nr(*arg, NULL, &len, TRUE, TRUE, &n, NULL);
4020 *arg += len;
4021 if (evaluate)
4022 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004023 rettv->v_type = VAR_NUMBER;
4024 rettv->vval.v_number = n;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004025 }
4026 break;
4027
4028 /*
4029 * String constant: "string".
4030 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004031 case '"': ret = get_string_tv(arg, rettv, evaluate);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004032 break;
4033
4034 /*
Bram Moolenaar8c711452005-01-14 21:53:12 +00004035 * Literal string constant: 'str''ing'.
Bram Moolenaar071d4272004-06-13 20:20:40 +00004036 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004037 case '\'': ret = get_lit_string_tv(arg, rettv, evaluate);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004038 break;
4039
4040 /*
4041 * List: [expr, expr]
4042 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004043 case '[': ret = get_list_tv(arg, rettv, evaluate);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004044 break;
4045
4046 /*
Bram Moolenaar8c711452005-01-14 21:53:12 +00004047 * Dictionary: {key: val, key: val}
4048 */
4049 case '{': ret = get_dict_tv(arg, rettv, evaluate);
4050 break;
4051
4052 /*
Bram Moolenaare9a41262005-01-15 22:18:47 +00004053 * Option value: &name
Bram Moolenaar071d4272004-06-13 20:20:40 +00004054 */
Bram Moolenaare9a41262005-01-15 22:18:47 +00004055 case '&': ret = get_option_tv(arg, rettv, evaluate);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004056 break;
4057
4058 /*
4059 * Environment variable: $VAR.
4060 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004061 case '$': ret = get_env_tv(arg, rettv, evaluate);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004062 break;
4063
4064 /*
4065 * Register contents: @r.
4066 */
4067 case '@': ++*arg;
4068 if (evaluate)
4069 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004070 rettv->v_type = VAR_STRING;
4071 rettv->vval.v_string = get_reg_contents(**arg, FALSE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004072 }
4073 if (**arg != NUL)
4074 ++*arg;
4075 break;
4076
4077 /*
4078 * nested expression: (expression).
4079 */
4080 case '(': *arg = skipwhite(*arg + 1);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004081 ret = eval1(arg, rettv, evaluate); /* recursive! */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004082 if (**arg == ')')
4083 ++*arg;
4084 else if (ret == OK)
4085 {
4086 EMSG(_("E110: Missing ')'"));
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004087 clear_tv(rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004088 ret = FAIL;
4089 }
4090 break;
4091
Bram Moolenaar8c711452005-01-14 21:53:12 +00004092 default: ret = NOTDONE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004093 break;
4094 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00004095
4096 if (ret == NOTDONE)
4097 {
4098 /*
4099 * Must be a variable or function name.
4100 * Can also be a curly-braces kind of name: {expr}.
4101 */
4102 s = *arg;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00004103 len = get_name_len(arg, &alias, evaluate, TRUE);
Bram Moolenaar8c711452005-01-14 21:53:12 +00004104 if (alias != NULL)
4105 s = alias;
4106
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00004107 if (len <= 0)
Bram Moolenaar8c711452005-01-14 21:53:12 +00004108 ret = FAIL;
4109 else
4110 {
4111 if (**arg == '(') /* recursive! */
4112 {
4113 /* If "s" is the name of a variable of type VAR_FUNC
4114 * use its contents. */
4115 s = deref_func_name(s, &len);
4116
4117 /* Invoke the function. */
4118 ret = get_func_tv(s, len, rettv, arg,
4119 curwin->w_cursor.lnum, curwin->w_cursor.lnum,
Bram Moolenaare9a41262005-01-15 22:18:47 +00004120 &len, evaluate, NULL);
Bram Moolenaar8c711452005-01-14 21:53:12 +00004121 /* Stop the expression evaluation when immediately
4122 * aborting on error, or when an interrupt occurred or
4123 * an exception was thrown but not caught. */
4124 if (aborting())
4125 {
4126 if (ret == OK)
4127 clear_tv(rettv);
4128 ret = FAIL;
4129 }
4130 }
4131 else if (evaluate)
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00004132 ret = get_var_tv(s, len, rettv, TRUE);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00004133 else
4134 ret = OK;
Bram Moolenaar8c711452005-01-14 21:53:12 +00004135 }
4136
4137 if (alias != NULL)
4138 vim_free(alias);
4139 }
4140
Bram Moolenaar071d4272004-06-13 20:20:40 +00004141 *arg = skipwhite(*arg);
4142
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00004143 /* Handle following '[', '(' and '.' for expr[expr], expr.name,
4144 * expr(expr). */
4145 if (ret == OK)
4146 ret = handle_subscript(arg, rettv, evaluate, TRUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004147
4148 /*
4149 * Apply logical NOT and unary '-', from right to left, ignore '+'.
4150 */
4151 if (ret == OK && evaluate && end_leader > start_leader)
4152 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004153 val = get_tv_number(rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004154 while (end_leader > start_leader)
4155 {
4156 --end_leader;
4157 if (*end_leader == '!')
4158 val = !val;
4159 else if (*end_leader == '-')
4160 val = -val;
4161 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004162 clear_tv(rettv);
4163 rettv->v_type = VAR_NUMBER;
4164 rettv->vval.v_number = val;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004165 }
4166
4167 return ret;
4168}
4169
4170/*
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004171 * Evaluate an "[expr]" or "[expr:expr]" index.
4172 * "*arg" points to the '['.
4173 * Returns FAIL or OK. "*arg" is advanced to after the ']'.
4174 */
4175 static int
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00004176eval_index(arg, rettv, evaluate, verbose)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004177 char_u **arg;
Bram Moolenaar33570922005-01-25 22:26:29 +00004178 typval_T *rettv;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004179 int evaluate;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00004180 int verbose; /* give error messages */
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004181{
4182 int empty1 = FALSE, empty2 = FALSE;
Bram Moolenaar33570922005-01-25 22:26:29 +00004183 typval_T var1, var2;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004184 long n1, n2 = 0;
Bram Moolenaar8c711452005-01-14 21:53:12 +00004185 long len = -1;
4186 int range = FALSE;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004187 char_u *s;
Bram Moolenaar8c711452005-01-14 21:53:12 +00004188 char_u *key = NULL;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004189
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004190 if (rettv->v_type == VAR_FUNC)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004191 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00004192 if (verbose)
4193 EMSG(_("E695: Cannot index a Funcref"));
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004194 return FAIL;
4195 }
4196
Bram Moolenaar8c711452005-01-14 21:53:12 +00004197 if (**arg == '.')
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004198 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00004199 /*
4200 * dict.name
4201 */
4202 key = *arg + 1;
4203 for (len = 0; ASCII_ISALNUM(key[len]) || key[len] == '_'; ++len)
4204 ;
4205 if (len == 0)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004206 return FAIL;
Bram Moolenaar8c711452005-01-14 21:53:12 +00004207 *arg = skipwhite(key + len);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004208 }
4209 else
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004210 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00004211 /*
4212 * something[idx]
4213 *
4214 * Get the (first) variable from inside the [].
4215 */
4216 *arg = skipwhite(*arg + 1);
4217 if (**arg == ':')
4218 empty1 = TRUE;
4219 else if (eval1(arg, &var1, evaluate) == FAIL) /* recursive! */
4220 return FAIL;
4221
4222 /*
4223 * Get the second variable from inside the [:].
4224 */
4225 if (**arg == ':')
4226 {
4227 range = TRUE;
4228 *arg = skipwhite(*arg + 1);
4229 if (**arg == ']')
4230 empty2 = TRUE;
4231 else if (eval1(arg, &var2, evaluate) == FAIL) /* recursive! */
4232 {
4233 clear_tv(&var1);
4234 return FAIL;
4235 }
4236 }
4237
4238 /* Check for the ']'. */
4239 if (**arg != ']')
4240 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00004241 if (verbose)
4242 EMSG(_(e_missbrac));
Bram Moolenaar8c711452005-01-14 21:53:12 +00004243 clear_tv(&var1);
4244 if (range)
4245 clear_tv(&var2);
4246 return FAIL;
4247 }
4248 *arg = skipwhite(*arg + 1); /* skip the ']' */
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004249 }
4250
4251 if (evaluate)
4252 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00004253 n1 = 0;
4254 if (!empty1 && rettv->v_type != VAR_DICT)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004255 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004256 n1 = get_tv_number(&var1);
4257 clear_tv(&var1);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004258 }
4259 if (range)
4260 {
4261 if (empty2)
4262 n2 = -1;
4263 else
4264 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004265 n2 = get_tv_number(&var2);
4266 clear_tv(&var2);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004267 }
4268 }
4269
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004270 switch (rettv->v_type)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004271 {
4272 case VAR_NUMBER:
4273 case VAR_STRING:
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004274 s = get_tv_string(rettv);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004275 len = (long)STRLEN(s);
4276 if (range)
4277 {
4278 /* The resulting variable is a substring. If the indexes
4279 * are out of range the result is empty. */
4280 if (n1 < 0)
4281 {
4282 n1 = len + n1;
4283 if (n1 < 0)
4284 n1 = 0;
4285 }
4286 if (n2 < 0)
4287 n2 = len + n2;
4288 else if (n2 >= len)
4289 n2 = len;
4290 if (n1 >= len || n2 < 0 || n1 > n2)
4291 s = NULL;
4292 else
4293 s = vim_strnsave(s + n1, (int)(n2 - n1 + 1));
4294 }
4295 else
4296 {
4297 /* The resulting variable is a string of a single
4298 * character. If the index is too big or negative the
4299 * result is empty. */
4300 if (n1 >= len || n1 < 0)
4301 s = NULL;
4302 else
4303 s = vim_strnsave(s + n1, 1);
4304 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004305 clear_tv(rettv);
4306 rettv->v_type = VAR_STRING;
4307 rettv->vval.v_string = s;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004308 break;
4309
4310 case VAR_LIST:
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004311 len = list_len(rettv->vval.v_list);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004312 if (n1 < 0)
4313 n1 = len + n1;
4314 if (!empty1 && (n1 < 0 || n1 >= len))
4315 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00004316 if (verbose)
4317 EMSGN(_(e_listidx), n1);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004318 return FAIL;
4319 }
4320 if (range)
4321 {
Bram Moolenaar33570922005-01-25 22:26:29 +00004322 list_T *l;
4323 listitem_T *item;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004324
4325 if (n2 < 0)
4326 n2 = len + n2;
Bram Moolenaar8c711452005-01-14 21:53:12 +00004327 if (!empty2 && (n2 < 0 || n2 >= len || n2 + 1 < n1))
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004328 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00004329 if (verbose)
4330 EMSGN(_(e_listidx), n2);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004331 return FAIL;
4332 }
4333 l = list_alloc();
4334 if (l == NULL)
4335 return FAIL;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004336 for (item = list_find(rettv->vval.v_list, n1);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004337 n1 <= n2; ++n1)
4338 {
4339 if (list_append_tv(l, &item->li_tv) == FAIL)
4340 {
4341 list_free(l);
4342 return FAIL;
4343 }
4344 item = item->li_next;
4345 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004346 clear_tv(rettv);
4347 rettv->v_type = VAR_LIST;
4348 rettv->vval.v_list = l;
Bram Moolenaar0d660222005-01-07 21:51:51 +00004349 ++l->lv_refcount;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004350 }
4351 else
4352 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004353 copy_tv(&list_find(rettv->vval.v_list, n1)->li_tv,
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004354 &var1);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004355 clear_tv(rettv);
4356 *rettv = var1;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004357 }
4358 break;
Bram Moolenaar8c711452005-01-14 21:53:12 +00004359
4360 case VAR_DICT:
4361 if (range)
4362 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00004363 if (verbose)
4364 EMSG(_(e_dictrange));
Bram Moolenaar8c711452005-01-14 21:53:12 +00004365 if (len == -1)
4366 clear_tv(&var1);
4367 return FAIL;
4368 }
4369 {
Bram Moolenaar33570922005-01-25 22:26:29 +00004370 dictitem_T *item;
Bram Moolenaar8c711452005-01-14 21:53:12 +00004371
4372 if (len == -1)
4373 {
4374 key = get_tv_string(&var1);
4375 if (*key == NUL)
4376 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00004377 if (verbose)
4378 EMSG(_(e_emptykey));
Bram Moolenaar8c711452005-01-14 21:53:12 +00004379 clear_tv(&var1);
4380 return FAIL;
4381 }
4382 }
4383
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00004384 item = dict_find(rettv->vval.v_dict, key, (int)len);
Bram Moolenaar8c711452005-01-14 21:53:12 +00004385
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00004386 if (item == NULL && verbose)
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00004387 EMSG2(_(e_dictkey), key);
Bram Moolenaar8c711452005-01-14 21:53:12 +00004388 if (len == -1)
4389 clear_tv(&var1);
4390 if (item == NULL)
4391 return FAIL;
4392
4393 copy_tv(&item->di_tv, &var1);
4394 clear_tv(rettv);
4395 *rettv = var1;
4396 }
4397 break;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004398 }
4399 }
4400
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004401 return OK;
4402}
4403
4404/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00004405 * Get an option value.
4406 * "arg" points to the '&' or '+' before the option name.
4407 * "arg" is advanced to character after the option name.
4408 * Return OK or FAIL.
4409 */
4410 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004411get_option_tv(arg, rettv, evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004412 char_u **arg;
Bram Moolenaar33570922005-01-25 22:26:29 +00004413 typval_T *rettv; /* when NULL, only check if option exists */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004414 int evaluate;
4415{
4416 char_u *option_end;
4417 long numval;
4418 char_u *stringval;
4419 int opt_type;
4420 int c;
4421 int working = (**arg == '+'); /* has("+option") */
4422 int ret = OK;
4423 int opt_flags;
4424
4425 /*
4426 * Isolate the option name and find its value.
4427 */
4428 option_end = find_option_end(arg, &opt_flags);
4429 if (option_end == NULL)
4430 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004431 if (rettv != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004432 EMSG2(_("E112: Option name missing: %s"), *arg);
4433 return FAIL;
4434 }
4435
4436 if (!evaluate)
4437 {
4438 *arg = option_end;
4439 return OK;
4440 }
4441
4442 c = *option_end;
4443 *option_end = NUL;
4444 opt_type = get_option_value(*arg, &numval,
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004445 rettv == NULL ? NULL : &stringval, opt_flags);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004446
4447 if (opt_type == -3) /* invalid name */
4448 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004449 if (rettv != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004450 EMSG2(_("E113: Unknown option: %s"), *arg);
4451 ret = FAIL;
4452 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004453 else if (rettv != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004454 {
4455 if (opt_type == -2) /* hidden string option */
4456 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004457 rettv->v_type = VAR_STRING;
4458 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004459 }
4460 else if (opt_type == -1) /* hidden number option */
4461 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004462 rettv->v_type = VAR_NUMBER;
4463 rettv->vval.v_number = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004464 }
4465 else if (opt_type == 1) /* number option */
4466 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004467 rettv->v_type = VAR_NUMBER;
4468 rettv->vval.v_number = numval;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004469 }
4470 else /* string option */
4471 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004472 rettv->v_type = VAR_STRING;
4473 rettv->vval.v_string = stringval;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004474 }
4475 }
4476 else if (working && (opt_type == -2 || opt_type == -1))
4477 ret = FAIL;
4478
4479 *option_end = c; /* put back for error messages */
4480 *arg = option_end;
4481
4482 return ret;
4483}
4484
4485/*
4486 * Allocate a variable for a string constant.
4487 * Return OK or FAIL.
4488 */
4489 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004490get_string_tv(arg, rettv, evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004491 char_u **arg;
Bram Moolenaar33570922005-01-25 22:26:29 +00004492 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004493 int evaluate;
4494{
4495 char_u *p;
4496 char_u *name;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004497 int extra = 0;
4498
4499 /*
4500 * Find the end of the string, skipping backslashed characters.
4501 */
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00004502 for (p = *arg + 1; *p != NUL && *p != '"'; mb_ptr_adv(p))
Bram Moolenaar071d4272004-06-13 20:20:40 +00004503 {
4504 if (*p == '\\' && p[1] != NUL)
4505 {
4506 ++p;
4507 /* A "\<x>" form occupies at least 4 characters, and produces up
4508 * to 6 characters: reserve space for 2 extra */
4509 if (*p == '<')
4510 extra += 2;
4511 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004512 }
4513
4514 if (*p != '"')
4515 {
4516 EMSG2(_("E114: Missing quote: %s"), *arg);
4517 return FAIL;
4518 }
4519
4520 /* If only parsing, set *arg and return here */
4521 if (!evaluate)
4522 {
4523 *arg = p + 1;
4524 return OK;
4525 }
4526
4527 /*
4528 * Copy the string into allocated memory, handling backslashed
4529 * characters.
4530 */
4531 name = alloc((unsigned)(p - *arg + extra));
4532 if (name == NULL)
4533 return FAIL;
Bram Moolenaar8c711452005-01-14 21:53:12 +00004534 rettv->v_type = VAR_STRING;
4535 rettv->vval.v_string = name;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004536
Bram Moolenaar8c711452005-01-14 21:53:12 +00004537 for (p = *arg + 1; *p != NUL && *p != '"'; )
Bram Moolenaar071d4272004-06-13 20:20:40 +00004538 {
4539 if (*p == '\\')
4540 {
4541 switch (*++p)
4542 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00004543 case 'b': *name++ = BS; ++p; break;
4544 case 'e': *name++ = ESC; ++p; break;
4545 case 'f': *name++ = FF; ++p; break;
4546 case 'n': *name++ = NL; ++p; break;
4547 case 'r': *name++ = CAR; ++p; break;
4548 case 't': *name++ = TAB; ++p; break;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004549
4550 case 'X': /* hex: "\x1", "\x12" */
4551 case 'x':
4552 case 'u': /* Unicode: "\u0023" */
4553 case 'U':
4554 if (vim_isxdigit(p[1]))
4555 {
4556 int n, nr;
4557 int c = toupper(*p);
4558
4559 if (c == 'X')
4560 n = 2;
4561 else
4562 n = 4;
4563 nr = 0;
4564 while (--n >= 0 && vim_isxdigit(p[1]))
4565 {
4566 ++p;
4567 nr = (nr << 4) + hex2nr(*p);
4568 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00004569 ++p;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004570#ifdef FEAT_MBYTE
4571 /* For "\u" store the number according to
4572 * 'encoding'. */
4573 if (c != 'X')
Bram Moolenaar8c711452005-01-14 21:53:12 +00004574 name += (*mb_char2bytes)(nr, name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004575 else
4576#endif
Bram Moolenaar8c711452005-01-14 21:53:12 +00004577 *name++ = nr;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004578 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004579 break;
4580
4581 /* octal: "\1", "\12", "\123" */
4582 case '0':
4583 case '1':
4584 case '2':
4585 case '3':
4586 case '4':
4587 case '5':
4588 case '6':
Bram Moolenaar8c711452005-01-14 21:53:12 +00004589 case '7': *name = *p++ - '0';
4590 if (*p >= '0' && *p <= '7')
Bram Moolenaar071d4272004-06-13 20:20:40 +00004591 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00004592 *name = (*name << 3) + *p++ - '0';
4593 if (*p >= '0' && *p <= '7')
4594 *name = (*name << 3) + *p++ - '0';
Bram Moolenaar071d4272004-06-13 20:20:40 +00004595 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00004596 ++name;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004597 break;
4598
4599 /* Special key, e.g.: "\<C-W>" */
Bram Moolenaar8c711452005-01-14 21:53:12 +00004600 case '<': extra = trans_special(&p, name, TRUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004601 if (extra != 0)
4602 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00004603 name += extra;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004604 break;
4605 }
4606 /* FALLTHROUGH */
4607
Bram Moolenaar8c711452005-01-14 21:53:12 +00004608 default: MB_COPY_CHAR(p, name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004609 break;
4610 }
4611 }
4612 else
Bram Moolenaar8c711452005-01-14 21:53:12 +00004613 MB_COPY_CHAR(p, name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004614
Bram Moolenaar071d4272004-06-13 20:20:40 +00004615 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00004616 *name = NUL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004617 *arg = p + 1;
4618
Bram Moolenaar071d4272004-06-13 20:20:40 +00004619 return OK;
4620}
4621
4622/*
Bram Moolenaar8c711452005-01-14 21:53:12 +00004623 * Allocate a variable for a 'str''ing' constant.
Bram Moolenaar071d4272004-06-13 20:20:40 +00004624 * Return OK or FAIL.
4625 */
4626 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004627get_lit_string_tv(arg, rettv, evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004628 char_u **arg;
Bram Moolenaar33570922005-01-25 22:26:29 +00004629 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004630 int evaluate;
4631{
4632 char_u *p;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00004633 char_u *str;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00004634 int reduce = 0;
4635
4636 /*
Bram Moolenaar8c711452005-01-14 21:53:12 +00004637 * Find the end of the string, skipping ''.
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00004638 */
4639 for (p = *arg + 1; *p != NUL; mb_ptr_adv(p))
4640 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00004641 if (*p == '\'')
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00004642 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00004643 if (p[1] != '\'')
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00004644 break;
4645 ++reduce;
4646 ++p;
4647 }
4648 }
4649
Bram Moolenaar8c711452005-01-14 21:53:12 +00004650 if (*p != '\'')
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00004651 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00004652 EMSG2(_("E115: Missing quote: %s"), *arg);
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00004653 return FAIL;
4654 }
4655
Bram Moolenaar8c711452005-01-14 21:53:12 +00004656 /* If only parsing return after setting "*arg" */
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00004657 if (!evaluate)
4658 {
4659 *arg = p + 1;
4660 return OK;
4661 }
4662
4663 /*
Bram Moolenaar8c711452005-01-14 21:53:12 +00004664 * Copy the string into allocated memory, handling '' to ' reduction.
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00004665 */
4666 str = alloc((unsigned)((p - *arg) - reduce));
4667 if (str == NULL)
4668 return FAIL;
Bram Moolenaar8c711452005-01-14 21:53:12 +00004669 rettv->v_type = VAR_STRING;
4670 rettv->vval.v_string = str;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00004671
Bram Moolenaar8c711452005-01-14 21:53:12 +00004672 for (p = *arg + 1; *p != NUL; )
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00004673 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00004674 if (*p == '\'')
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00004675 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00004676 if (p[1] != '\'')
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00004677 break;
4678 ++p;
4679 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00004680 MB_COPY_CHAR(p, str);
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00004681 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00004682 *str = NUL;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00004683 *arg = p + 1;
4684
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00004685 return OK;
4686}
4687
4688/*
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004689 * Allocate a variable for a List and fill it from "*arg".
4690 * Return OK or FAIL.
4691 */
4692 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004693get_list_tv(arg, rettv, evaluate)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004694 char_u **arg;
Bram Moolenaar33570922005-01-25 22:26:29 +00004695 typval_T *rettv;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004696 int evaluate;
4697{
Bram Moolenaar33570922005-01-25 22:26:29 +00004698 list_T *l = NULL;
4699 typval_T tv;
4700 listitem_T *item;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004701
4702 if (evaluate)
4703 {
4704 l = list_alloc();
4705 if (l == NULL)
4706 return FAIL;
4707 }
4708
4709 *arg = skipwhite(*arg + 1);
4710 while (**arg != ']' && **arg != NUL)
4711 {
4712 if (eval1(arg, &tv, evaluate) == FAIL) /* recursive! */
4713 goto failret;
4714 if (evaluate)
4715 {
4716 item = listitem_alloc();
4717 if (item != NULL)
4718 {
4719 item->li_tv = tv;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00004720 item->li_tv.v_lock = 0;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004721 list_append(l, item);
4722 }
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00004723 else
4724 clear_tv(&tv);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004725 }
4726
4727 if (**arg == ']')
4728 break;
4729 if (**arg != ',')
4730 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00004731 EMSG2(_("E696: Missing comma in List: %s"), *arg);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004732 goto failret;
4733 }
4734 *arg = skipwhite(*arg + 1);
4735 }
4736
4737 if (**arg != ']')
4738 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00004739 EMSG2(_("E697: Missing end of List ']': %s"), *arg);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004740failret:
4741 if (evaluate)
4742 list_free(l);
4743 return FAIL;
4744 }
4745
4746 *arg = skipwhite(*arg + 1);
4747 if (evaluate)
4748 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004749 rettv->v_type = VAR_LIST;
4750 rettv->vval.v_list = l;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004751 ++l->lv_refcount;
4752 }
4753
4754 return OK;
4755}
4756
4757/*
4758 * Allocate an empty header for a list.
4759 */
Bram Moolenaar33570922005-01-25 22:26:29 +00004760 static list_T *
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004761list_alloc()
4762{
Bram Moolenaar33570922005-01-25 22:26:29 +00004763 return (list_T *)alloc_clear(sizeof(list_T));
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004764}
4765
4766/*
4767 * Unreference a list: decrement the reference count and free it when it
4768 * becomes zero.
4769 */
4770 static void
4771list_unref(l)
Bram Moolenaar33570922005-01-25 22:26:29 +00004772 list_T *l;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004773{
4774 if (l != NULL && --l->lv_refcount <= 0)
4775 list_free(l);
4776}
4777
4778/*
4779 * Free a list, including all items it points to.
4780 * Ignores the reference count.
4781 */
4782 static void
4783list_free(l)
Bram Moolenaar33570922005-01-25 22:26:29 +00004784 list_T *l;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004785{
Bram Moolenaar33570922005-01-25 22:26:29 +00004786 listitem_T *item;
4787 listitem_T *next;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004788
4789 for (item = l->lv_first; item != NULL; item = next)
4790 {
4791 next = item->li_next;
4792 listitem_free(item);
4793 }
4794 vim_free(l);
4795}
4796
4797/*
4798 * Allocate a list item.
4799 */
Bram Moolenaar33570922005-01-25 22:26:29 +00004800 static listitem_T *
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004801listitem_alloc()
4802{
Bram Moolenaar33570922005-01-25 22:26:29 +00004803 return (listitem_T *)alloc(sizeof(listitem_T));
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004804}
4805
4806/*
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00004807 * Free a list item. Also clears the value. Does not notify watchers.
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004808 */
4809 static void
4810listitem_free(item)
Bram Moolenaar33570922005-01-25 22:26:29 +00004811 listitem_T *item;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004812{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004813 clear_tv(&item->li_tv);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004814 vim_free(item);
4815}
4816
4817/*
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00004818 * Remove a list item from a List and free it. Also clears the value.
4819 */
4820 static void
4821listitem_remove(l, item)
Bram Moolenaar33570922005-01-25 22:26:29 +00004822 list_T *l;
4823 listitem_T *item;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00004824{
4825 list_remove(l, item, item);
4826 listitem_free(item);
4827}
4828
4829/*
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004830 * Get the number of items in a list.
4831 */
4832 static long
4833list_len(l)
Bram Moolenaar33570922005-01-25 22:26:29 +00004834 list_T *l;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004835{
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004836 if (l == NULL)
4837 return 0L;
Bram Moolenaar758711c2005-02-02 23:11:38 +00004838 return l->lv_len;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004839}
4840
4841/*
Bram Moolenaar8a283e52005-01-06 23:28:25 +00004842 * Return TRUE when two lists have exactly the same values.
4843 */
4844 static int
4845list_equal(l1, l2, ic)
Bram Moolenaar33570922005-01-25 22:26:29 +00004846 list_T *l1;
4847 list_T *l2;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00004848 int ic; /* ignore case for strings */
4849{
Bram Moolenaar33570922005-01-25 22:26:29 +00004850 listitem_T *item1, *item2;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00004851
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00004852 if (list_len(l1) != list_len(l2))
4853 return FALSE;
4854
Bram Moolenaar8a283e52005-01-06 23:28:25 +00004855 for (item1 = l1->lv_first, item2 = l2->lv_first;
4856 item1 != NULL && item2 != NULL;
4857 item1 = item1->li_next, item2 = item2->li_next)
4858 if (!tv_equal(&item1->li_tv, &item2->li_tv, ic))
4859 return FALSE;
4860 return item1 == NULL && item2 == NULL;
4861}
4862
4863/*
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00004864 * Return TRUE when two dictionaries have exactly the same key/values.
4865 */
4866 static int
4867dict_equal(d1, d2, ic)
Bram Moolenaar33570922005-01-25 22:26:29 +00004868 dict_T *d1;
4869 dict_T *d2;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00004870 int ic; /* ignore case for strings */
4871{
Bram Moolenaar33570922005-01-25 22:26:29 +00004872 hashitem_T *hi;
4873 dictitem_T *item2;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00004874 int todo;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00004875
4876 if (dict_len(d1) != dict_len(d2))
4877 return FALSE;
4878
Bram Moolenaar33570922005-01-25 22:26:29 +00004879 todo = d1->dv_hashtab.ht_used;
4880 for (hi = d1->dv_hashtab.ht_array; todo > 0; ++hi)
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00004881 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00004882 if (!HASHITEM_EMPTY(hi))
4883 {
4884 item2 = dict_find(d2, hi->hi_key, -1);
4885 if (item2 == NULL)
4886 return FALSE;
4887 if (!tv_equal(&HI2DI(hi)->di_tv, &item2->di_tv, ic))
4888 return FALSE;
4889 --todo;
4890 }
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00004891 }
4892 return TRUE;
4893}
4894
4895/*
Bram Moolenaar8a283e52005-01-06 23:28:25 +00004896 * Return TRUE if "tv1" and "tv2" have the same value.
4897 * Compares the items just like "==" would compare them.
4898 */
4899 static int
4900tv_equal(tv1, tv2, ic)
Bram Moolenaar33570922005-01-25 22:26:29 +00004901 typval_T *tv1;
4902 typval_T *tv2;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00004903 int ic; /* ignore case */
4904{
4905 char_u buf1[NUMBUFLEN], buf2[NUMBUFLEN];
4906
4907 if (tv1->v_type == VAR_LIST || tv2->v_type == VAR_LIST)
4908 {
4909 /* recursive! */
4910 if (tv1->v_type != tv2->v_type
4911 || !list_equal(tv1->vval.v_list, tv2->vval.v_list, ic))
4912 return FALSE;
4913 }
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00004914 else if (tv1->v_type == VAR_DICT || tv2->v_type == VAR_DICT)
4915 {
4916 /* recursive! */
4917 if (tv1->v_type != tv2->v_type
4918 || !dict_equal(tv1->vval.v_dict, tv2->vval.v_dict, ic))
4919 return FALSE;
4920 }
Bram Moolenaar8a283e52005-01-06 23:28:25 +00004921 else if (tv1->v_type == VAR_FUNC || tv2->v_type == VAR_FUNC)
4922 {
4923 if (tv1->v_type != tv2->v_type
4924 || tv1->vval.v_string == NULL
4925 || tv2->vval.v_string == NULL
4926 || STRCMP(tv1->vval.v_string, tv2->vval.v_string) != 0)
4927 return FALSE;
4928 }
4929 else if (tv1->v_type == VAR_NUMBER || tv2->v_type == VAR_NUMBER)
4930 {
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00004931 /* "4" is equal to 4. But don't consider 'a' and zero to be equal.
4932 * Don't consider "4x" to be equal to 4. */
4933 if ((tv1->v_type == VAR_STRING
4934 && !string_isa_number(tv1->vval.v_string))
4935 || (tv2->v_type == VAR_STRING
4936 && !string_isa_number(tv2->vval.v_string)))
4937 return FALSE;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00004938 if (get_tv_number(tv1) != get_tv_number(tv2))
4939 return FALSE;
4940 }
4941 else if (!ic && STRCMP(get_tv_string_buf(tv1, buf1),
4942 get_tv_string_buf(tv2, buf2)) != 0)
4943 return FALSE;
4944 else if (ic && STRICMP(get_tv_string_buf(tv1, buf1),
4945 get_tv_string_buf(tv2, buf2)) != 0)
4946 return FALSE;
4947 return TRUE;
4948}
4949
4950/*
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00004951 * Return TRUE if "tv" is a number without other non-white characters.
4952 */
4953 static int
4954string_isa_number(s)
4955 char_u *s;
4956{
4957 int len;
4958
4959 vim_str2nr(s, NULL, &len, TRUE, TRUE, NULL, NULL);
4960 return len > 0 && *skipwhite(s + len) == NUL;
4961}
4962
4963/*
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004964 * Locate item with index "n" in list "l" and return it.
4965 * A negative index is counted from the end; -1 is the last item.
4966 * Returns NULL when "n" is out of range.
4967 */
Bram Moolenaar33570922005-01-25 22:26:29 +00004968 static listitem_T *
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004969list_find(l, n)
Bram Moolenaar33570922005-01-25 22:26:29 +00004970 list_T *l;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004971 long n;
4972{
Bram Moolenaar33570922005-01-25 22:26:29 +00004973 listitem_T *item;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004974 long idx;
4975
4976 if (l == NULL)
4977 return NULL;
Bram Moolenaar758711c2005-02-02 23:11:38 +00004978
4979 /* Negative index is relative to the end. */
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004980 if (n < 0)
Bram Moolenaar758711c2005-02-02 23:11:38 +00004981 n = l->lv_len + n;
4982
4983 /* Check for index out of range. */
4984 if (n < 0 || n >= l->lv_len)
4985 return NULL;
4986
4987 /* When there is a cached index may start search from there. */
4988 if (l->lv_idx_item != NULL)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004989 {
Bram Moolenaar758711c2005-02-02 23:11:38 +00004990 if (n < l->lv_idx / 2)
4991 {
4992 /* closest to the start of the list */
4993 item = l->lv_first;
4994 idx = 0;
4995 }
4996 else if (n > (l->lv_idx + l->lv_len) / 2)
4997 {
4998 /* closest to the end of the list */
4999 item = l->lv_last;
5000 idx = l->lv_len - 1;
5001 }
5002 else
5003 {
5004 /* closest to the cached index */
5005 item = l->lv_idx_item;
5006 idx = l->lv_idx;
5007 }
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005008 }
5009 else
5010 {
Bram Moolenaar758711c2005-02-02 23:11:38 +00005011 if (n < l->lv_len / 2)
5012 {
5013 /* closest to the start of the list */
5014 item = l->lv_first;
5015 idx = 0;
5016 }
5017 else
5018 {
5019 /* closest to the end of the list */
5020 item = l->lv_last;
5021 idx = l->lv_len - 1;
5022 }
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005023 }
Bram Moolenaar758711c2005-02-02 23:11:38 +00005024
5025 while (n > idx)
5026 {
5027 /* search forward */
5028 item = item->li_next;
5029 ++idx;
5030 }
5031 while (n < idx)
5032 {
5033 /* search backward */
5034 item = item->li_prev;
5035 --idx;
5036 }
5037
5038 /* cache the used index */
5039 l->lv_idx = idx;
5040 l->lv_idx_item = item;
5041
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005042 return item;
5043}
5044
5045/*
Bram Moolenaar6cc16192005-01-08 21:49:45 +00005046 * Locate "item" list "l" and return its index.
5047 * Returns -1 when "item" is not in the list.
5048 */
5049 static long
5050list_idx_of_item(l, item)
Bram Moolenaar33570922005-01-25 22:26:29 +00005051 list_T *l;
5052 listitem_T *item;
Bram Moolenaar6cc16192005-01-08 21:49:45 +00005053{
5054 long idx = 0;
Bram Moolenaar33570922005-01-25 22:26:29 +00005055 listitem_T *li;
Bram Moolenaar6cc16192005-01-08 21:49:45 +00005056
5057 if (l == NULL)
5058 return -1;
5059 idx = 0;
5060 for (li = l->lv_first; li != NULL && li != item; li = li->li_next)
5061 ++idx;
5062 if (li == NULL)
5063 return -1;
5064 return idx;;
5065}
5066
5067/*
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005068 * Append item "item" to the end of list "l".
5069 */
5070 static void
5071list_append(l, item)
Bram Moolenaar33570922005-01-25 22:26:29 +00005072 list_T *l;
5073 listitem_T *item;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005074{
5075 if (l->lv_last == NULL)
5076 {
5077 /* empty list */
5078 l->lv_first = item;
5079 l->lv_last = item;
5080 item->li_prev = NULL;
5081 }
5082 else
5083 {
5084 l->lv_last->li_next = item;
5085 item->li_prev = l->lv_last;
5086 l->lv_last = item;
5087 }
Bram Moolenaar758711c2005-02-02 23:11:38 +00005088 ++l->lv_len;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005089 item->li_next = NULL;
5090}
5091
5092/*
Bram Moolenaar33570922005-01-25 22:26:29 +00005093 * Append typval_T "tv" to the end of list "l".
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005094 * Return FAIL when out of memory.
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005095 */
5096 static int
5097list_append_tv(l, tv)
Bram Moolenaar33570922005-01-25 22:26:29 +00005098 list_T *l;
5099 typval_T *tv;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005100{
Bram Moolenaar05159a02005-02-26 23:04:13 +00005101 listitem_T *li = listitem_alloc();
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005102
Bram Moolenaar05159a02005-02-26 23:04:13 +00005103 if (li == NULL)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005104 return FAIL;
Bram Moolenaar05159a02005-02-26 23:04:13 +00005105 copy_tv(tv, &li->li_tv);
5106 list_append(l, li);
5107 return OK;
5108}
5109
5110/*
5111 * Add a dictionary to a list. Used by errorlist().
5112 * Return FAIL when out of memory.
5113 */
5114 int
5115list_append_dict(list, dict)
5116 list_T *list;
5117 dict_T *dict;
5118{
5119 listitem_T *li = listitem_alloc();
5120
5121 if (li == NULL)
5122 return FAIL;
5123 li->li_tv.v_type = VAR_DICT;
5124 li->li_tv.v_lock = 0;
5125 li->li_tv.vval.v_dict = dict;
5126 list_append(list, li);
5127 ++dict->dv_refcount;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005128 return OK;
5129}
5130
5131/*
Bram Moolenaar33570922005-01-25 22:26:29 +00005132 * Insert typval_T "tv" in list "l" before "item".
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005133 * If "item" is NULL append at the end.
5134 * Return FAIL when out of memory.
5135 */
5136 static int
5137list_insert_tv(l, tv, item)
Bram Moolenaar33570922005-01-25 22:26:29 +00005138 list_T *l;
5139 typval_T *tv;
5140 listitem_T *item;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005141{
Bram Moolenaar33570922005-01-25 22:26:29 +00005142 listitem_T *ni = listitem_alloc();
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005143
5144 if (ni == NULL)
5145 return FAIL;
5146 copy_tv(tv, &ni->li_tv);
5147 if (item == NULL)
5148 /* Append new item at end of list. */
5149 list_append(l, ni);
5150 else
5151 {
5152 /* Insert new item before existing item. */
5153 ni->li_prev = item->li_prev;
5154 ni->li_next = item;
5155 if (item->li_prev == NULL)
Bram Moolenaar758711c2005-02-02 23:11:38 +00005156 {
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005157 l->lv_first = ni;
Bram Moolenaar758711c2005-02-02 23:11:38 +00005158 ++l->lv_idx;
5159 }
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005160 else
Bram Moolenaar758711c2005-02-02 23:11:38 +00005161 {
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005162 item->li_prev->li_next = ni;
Bram Moolenaar758711c2005-02-02 23:11:38 +00005163 l->lv_idx_item = NULL;
5164 }
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005165 item->li_prev = ni;
Bram Moolenaar758711c2005-02-02 23:11:38 +00005166 ++l->lv_len;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005167 }
5168 return OK;
5169}
5170
5171/*
5172 * Extend "l1" with "l2".
5173 * If "bef" is NULL append at the end, otherwise insert before this item.
5174 * Returns FAIL when out of memory.
5175 */
5176 static int
5177list_extend(l1, l2, bef)
Bram Moolenaar33570922005-01-25 22:26:29 +00005178 list_T *l1;
5179 list_T *l2;
5180 listitem_T *bef;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005181{
Bram Moolenaar33570922005-01-25 22:26:29 +00005182 listitem_T *item;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005183
5184 for (item = l2->lv_first; item != NULL; item = item->li_next)
5185 if (list_insert_tv(l1, &item->li_tv, bef) == FAIL)
5186 return FAIL;
5187 return OK;
5188}
5189
5190/*
5191 * Concatenate lists "l1" and "l2" into a new list, stored in "tv".
5192 * Return FAIL when out of memory.
5193 */
5194 static int
5195list_concat(l1, l2, tv)
Bram Moolenaar33570922005-01-25 22:26:29 +00005196 list_T *l1;
5197 list_T *l2;
5198 typval_T *tv;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005199{
Bram Moolenaar33570922005-01-25 22:26:29 +00005200 list_T *l;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005201
5202 /* make a copy of the first list. */
Bram Moolenaar81bf7082005-02-12 14:31:42 +00005203 l = list_copy(l1, FALSE, 0);
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005204 if (l == NULL)
5205 return FAIL;
5206 tv->v_type = VAR_LIST;
5207 tv->vval.v_list = l;
5208
5209 /* append all items from the second list */
5210 return list_extend(l, l2, NULL);
5211}
5212
5213/*
Bram Moolenaare9a41262005-01-15 22:18:47 +00005214 * Make a copy of list "orig". Shallow if "deep" is FALSE.
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005215 * The refcount of the new list is set to 1.
Bram Moolenaar81bf7082005-02-12 14:31:42 +00005216 * See item_copy() for "copyID".
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005217 * Returns NULL when out of memory.
5218 */
Bram Moolenaar33570922005-01-25 22:26:29 +00005219 static list_T *
Bram Moolenaar81bf7082005-02-12 14:31:42 +00005220list_copy(orig, deep, copyID)
Bram Moolenaar33570922005-01-25 22:26:29 +00005221 list_T *orig;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005222 int deep;
Bram Moolenaar81bf7082005-02-12 14:31:42 +00005223 int copyID;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005224{
Bram Moolenaar33570922005-01-25 22:26:29 +00005225 list_T *copy;
5226 listitem_T *item;
5227 listitem_T *ni;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005228
5229 if (orig == NULL)
5230 return NULL;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005231
5232 copy = list_alloc();
5233 if (copy != NULL)
5234 {
Bram Moolenaar81bf7082005-02-12 14:31:42 +00005235 if (copyID != 0)
5236 {
5237 /* Do this before adding the items, because one of the items may
5238 * refer back to this list. */
5239 orig->lv_copyID = copyID;
5240 orig->lv_copylist = copy;
5241 }
5242 for (item = orig->lv_first; item != NULL && !got_int;
5243 item = item->li_next)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005244 {
5245 ni = listitem_alloc();
5246 if (ni == NULL)
5247 break;
Bram Moolenaare9a41262005-01-15 22:18:47 +00005248 if (deep)
Bram Moolenaar81bf7082005-02-12 14:31:42 +00005249 {
5250 if (item_copy(&item->li_tv, &ni->li_tv, deep, copyID) == FAIL)
5251 {
5252 vim_free(ni);
5253 break;
5254 }
5255 }
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005256 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005257 copy_tv(&item->li_tv, &ni->li_tv);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005258 list_append(copy, ni);
5259 }
5260 ++copy->lv_refcount;
Bram Moolenaar81bf7082005-02-12 14:31:42 +00005261 if (item != NULL)
5262 {
5263 list_unref(copy);
5264 copy = NULL;
5265 }
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005266 }
5267
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005268 return copy;
5269}
5270
5271/*
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005272 * Remove items "item" to "item2" from list "l".
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00005273 * Does not free the listitem or the value!
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005274 */
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005275 static void
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00005276list_remove(l, item, item2)
Bram Moolenaar33570922005-01-25 22:26:29 +00005277 list_T *l;
5278 listitem_T *item;
5279 listitem_T *item2;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005280{
Bram Moolenaar33570922005-01-25 22:26:29 +00005281 listitem_T *ip;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005282
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005283 /* notify watchers */
5284 for (ip = item; ip != NULL; ip = ip->li_next)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005285 {
Bram Moolenaar758711c2005-02-02 23:11:38 +00005286 --l->lv_len;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005287 list_fix_watch(l, ip);
5288 if (ip == item2)
5289 break;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005290 }
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005291
5292 if (item2->li_next == NULL)
5293 l->lv_last = item->li_prev;
5294 else
5295 item2->li_next->li_prev = item->li_prev;
5296 if (item->li_prev == NULL)
5297 l->lv_first = item2->li_next;
5298 else
5299 item->li_prev->li_next = item2->li_next;
Bram Moolenaar758711c2005-02-02 23:11:38 +00005300 l->lv_idx_item = NULL;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005301}
5302
5303/*
5304 * Return an allocated string with the string representation of a list.
5305 * May return NULL.
5306 */
5307 static char_u *
5308list2string(tv)
Bram Moolenaar33570922005-01-25 22:26:29 +00005309 typval_T *tv;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005310{
5311 garray_T ga;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005312
5313 if (tv->vval.v_list == NULL)
5314 return NULL;
5315 ga_init2(&ga, (int)sizeof(char), 80);
5316 ga_append(&ga, '[');
Bram Moolenaar81bf7082005-02-12 14:31:42 +00005317 if (list_join(&ga, tv->vval.v_list, (char_u *)", ", FALSE) == FAIL)
5318 {
5319 vim_free(ga.ga_data);
5320 return NULL;
5321 }
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005322 ga_append(&ga, ']');
5323 ga_append(&ga, NUL);
5324 return (char_u *)ga.ga_data;
5325}
5326
5327/*
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005328 * Join list "l" into a string in "*gap", using separator "sep".
5329 * When "echo" is TRUE use String as echoed, otherwise as inside a List.
Bram Moolenaar81bf7082005-02-12 14:31:42 +00005330 * Return FAIL or OK.
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005331 */
Bram Moolenaar81bf7082005-02-12 14:31:42 +00005332 static int
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005333list_join(gap, l, sep, echo)
5334 garray_T *gap;
Bram Moolenaar33570922005-01-25 22:26:29 +00005335 list_T *l;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005336 char_u *sep;
5337 int echo;
5338{
5339 int first = TRUE;
5340 char_u *tofree;
5341 char_u numbuf[NUMBUFLEN];
Bram Moolenaar33570922005-01-25 22:26:29 +00005342 listitem_T *item;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005343 char_u *s;
5344
Bram Moolenaar81bf7082005-02-12 14:31:42 +00005345 for (item = l->lv_first; item != NULL && !got_int; item = item->li_next)
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005346 {
5347 if (first)
5348 first = FALSE;
5349 else
5350 ga_concat(gap, sep);
5351
5352 if (echo)
5353 s = echo_string(&item->li_tv, &tofree, numbuf);
5354 else
5355 s = tv2string(&item->li_tv, &tofree, numbuf);
5356 if (s != NULL)
5357 ga_concat(gap, s);
5358 vim_free(tofree);
Bram Moolenaar81bf7082005-02-12 14:31:42 +00005359 if (s == NULL)
5360 return FAIL;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005361 }
Bram Moolenaar81bf7082005-02-12 14:31:42 +00005362 return OK;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005363}
5364
5365/*
Bram Moolenaar8c711452005-01-14 21:53:12 +00005366 * Allocate an empty header for a dictionary.
5367 */
Bram Moolenaar05159a02005-02-26 23:04:13 +00005368 dict_T *
Bram Moolenaar8c711452005-01-14 21:53:12 +00005369dict_alloc()
5370{
Bram Moolenaar33570922005-01-25 22:26:29 +00005371 dict_T *d;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005372
Bram Moolenaar33570922005-01-25 22:26:29 +00005373 d = (dict_T *)alloc(sizeof(dict_T));
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005374 if (d != NULL)
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00005375 {
Bram Moolenaar33570922005-01-25 22:26:29 +00005376 hash_init(&d->dv_hashtab);
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00005377 d->dv_lock = 0;
5378 d->dv_refcount = 0;
Bram Moolenaar81bf7082005-02-12 14:31:42 +00005379 d->dv_copyID = 0;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00005380 }
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005381 return d;
Bram Moolenaar8c711452005-01-14 21:53:12 +00005382}
5383
5384/*
5385 * Unreference a Dictionary: decrement the reference count and free it when it
5386 * becomes zero.
5387 */
5388 static void
5389dict_unref(d)
Bram Moolenaar33570922005-01-25 22:26:29 +00005390 dict_T *d;
Bram Moolenaar8c711452005-01-14 21:53:12 +00005391{
5392 if (d != NULL && --d->dv_refcount <= 0)
5393 dict_free(d);
5394}
5395
5396/*
5397 * Free a Dictionary, including all items it contains.
5398 * Ignores the reference count.
5399 */
5400 static void
5401dict_free(d)
Bram Moolenaar33570922005-01-25 22:26:29 +00005402 dict_T *d;
Bram Moolenaar8c711452005-01-14 21:53:12 +00005403{
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005404 int todo;
Bram Moolenaar33570922005-01-25 22:26:29 +00005405 hashitem_T *hi;
Bram Moolenaar8c711452005-01-14 21:53:12 +00005406
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005407 /* Careful: we free the dictitems while they still appear in the
Bram Moolenaar33570922005-01-25 22:26:29 +00005408 * hashtab. Must not try to resize the hashtab! */
5409 todo = d->dv_hashtab.ht_used;
5410 for (hi = d->dv_hashtab.ht_array; todo > 0; ++hi)
Bram Moolenaar8c711452005-01-14 21:53:12 +00005411 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005412 if (!HASHITEM_EMPTY(hi))
5413 {
5414 dictitem_free(HI2DI(hi));
5415 --todo;
5416 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00005417 }
Bram Moolenaar33570922005-01-25 22:26:29 +00005418 hash_clear(&d->dv_hashtab);
Bram Moolenaar8c711452005-01-14 21:53:12 +00005419 vim_free(d);
5420}
5421
5422/*
5423 * Allocate a Dictionary item.
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005424 * The "key" is copied to the new item.
5425 * Note that the value of the item "di_tv" still needs to be initialized!
5426 * Returns NULL when out of memory.
Bram Moolenaar8c711452005-01-14 21:53:12 +00005427 */
Bram Moolenaar33570922005-01-25 22:26:29 +00005428 static dictitem_T *
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005429dictitem_alloc(key)
5430 char_u *key;
Bram Moolenaar8c711452005-01-14 21:53:12 +00005431{
Bram Moolenaar33570922005-01-25 22:26:29 +00005432 dictitem_T *di;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005433
Bram Moolenaar33570922005-01-25 22:26:29 +00005434 di = (dictitem_T *)alloc(sizeof(dictitem_T) + STRLEN(key));
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005435 if (di != NULL)
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00005436 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005437 STRCPY(di->di_key, key);
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00005438 di->di_flags = 0;
5439 }
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005440 return di;
Bram Moolenaar8c711452005-01-14 21:53:12 +00005441}
5442
5443/*
Bram Moolenaare9a41262005-01-15 22:18:47 +00005444 * Make a copy of a Dictionary item.
5445 */
Bram Moolenaar33570922005-01-25 22:26:29 +00005446 static dictitem_T *
Bram Moolenaare9a41262005-01-15 22:18:47 +00005447dictitem_copy(org)
Bram Moolenaar33570922005-01-25 22:26:29 +00005448 dictitem_T *org;
Bram Moolenaare9a41262005-01-15 22:18:47 +00005449{
Bram Moolenaar33570922005-01-25 22:26:29 +00005450 dictitem_T *di;
Bram Moolenaare9a41262005-01-15 22:18:47 +00005451
Bram Moolenaar33570922005-01-25 22:26:29 +00005452 di = (dictitem_T *)alloc(sizeof(dictitem_T) + STRLEN(org->di_key));
Bram Moolenaare9a41262005-01-15 22:18:47 +00005453 if (di != NULL)
5454 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005455 STRCPY(di->di_key, org->di_key);
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00005456 di->di_flags = 0;
Bram Moolenaare9a41262005-01-15 22:18:47 +00005457 copy_tv(&org->di_tv, &di->di_tv);
5458 }
5459 return di;
5460}
5461
5462/*
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005463 * Remove item "item" from Dictionary "dict" and free it.
5464 */
5465 static void
5466dictitem_remove(dict, item)
Bram Moolenaar33570922005-01-25 22:26:29 +00005467 dict_T *dict;
5468 dictitem_T *item;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005469{
Bram Moolenaar33570922005-01-25 22:26:29 +00005470 hashitem_T *hi;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005471
Bram Moolenaar33570922005-01-25 22:26:29 +00005472 hi = hash_find(&dict->dv_hashtab, item->di_key);
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005473 if (HASHITEM_EMPTY(hi))
5474 EMSG2(_(e_intern2), "dictitem_remove()");
5475 else
Bram Moolenaar33570922005-01-25 22:26:29 +00005476 hash_remove(&dict->dv_hashtab, hi);
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005477 dictitem_free(item);
5478}
5479
5480/*
Bram Moolenaar8c711452005-01-14 21:53:12 +00005481 * Free a dict item. Also clears the value.
5482 */
5483 static void
5484dictitem_free(item)
Bram Moolenaar33570922005-01-25 22:26:29 +00005485 dictitem_T *item;
Bram Moolenaar8c711452005-01-14 21:53:12 +00005486{
Bram Moolenaar8c711452005-01-14 21:53:12 +00005487 clear_tv(&item->di_tv);
5488 vim_free(item);
5489}
5490
5491/*
Bram Moolenaare9a41262005-01-15 22:18:47 +00005492 * Make a copy of dict "d". Shallow if "deep" is FALSE.
5493 * The refcount of the new dict is set to 1.
Bram Moolenaar81bf7082005-02-12 14:31:42 +00005494 * See item_copy() for "copyID".
Bram Moolenaare9a41262005-01-15 22:18:47 +00005495 * Returns NULL when out of memory.
5496 */
Bram Moolenaar33570922005-01-25 22:26:29 +00005497 static dict_T *
Bram Moolenaar81bf7082005-02-12 14:31:42 +00005498dict_copy(orig, deep, copyID)
Bram Moolenaar33570922005-01-25 22:26:29 +00005499 dict_T *orig;
Bram Moolenaare9a41262005-01-15 22:18:47 +00005500 int deep;
Bram Moolenaar81bf7082005-02-12 14:31:42 +00005501 int copyID;
Bram Moolenaare9a41262005-01-15 22:18:47 +00005502{
Bram Moolenaar33570922005-01-25 22:26:29 +00005503 dict_T *copy;
5504 dictitem_T *di;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005505 int todo;
Bram Moolenaar33570922005-01-25 22:26:29 +00005506 hashitem_T *hi;
Bram Moolenaare9a41262005-01-15 22:18:47 +00005507
5508 if (orig == NULL)
5509 return NULL;
5510
5511 copy = dict_alloc();
5512 if (copy != NULL)
5513 {
Bram Moolenaar81bf7082005-02-12 14:31:42 +00005514 if (copyID != 0)
5515 {
5516 orig->dv_copyID = copyID;
5517 orig->dv_copydict = copy;
5518 }
Bram Moolenaar33570922005-01-25 22:26:29 +00005519 todo = orig->dv_hashtab.ht_used;
Bram Moolenaar81bf7082005-02-12 14:31:42 +00005520 for (hi = orig->dv_hashtab.ht_array; todo > 0 && !got_int; ++hi)
Bram Moolenaare9a41262005-01-15 22:18:47 +00005521 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005522 if (!HASHITEM_EMPTY(hi))
Bram Moolenaare9a41262005-01-15 22:18:47 +00005523 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005524 --todo;
5525
5526 di = dictitem_alloc(hi->hi_key);
5527 if (di == NULL)
5528 break;
5529 if (deep)
Bram Moolenaar81bf7082005-02-12 14:31:42 +00005530 {
5531 if (item_copy(&HI2DI(hi)->di_tv, &di->di_tv, deep,
5532 copyID) == FAIL)
5533 {
5534 vim_free(di);
5535 break;
5536 }
5537 }
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005538 else
5539 copy_tv(&HI2DI(hi)->di_tv, &di->di_tv);
5540 if (dict_add(copy, di) == FAIL)
5541 {
5542 dictitem_free(di);
5543 break;
5544 }
Bram Moolenaare9a41262005-01-15 22:18:47 +00005545 }
Bram Moolenaare9a41262005-01-15 22:18:47 +00005546 }
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005547
Bram Moolenaare9a41262005-01-15 22:18:47 +00005548 ++copy->dv_refcount;
Bram Moolenaar81bf7082005-02-12 14:31:42 +00005549 if (todo > 0)
5550 {
5551 dict_unref(copy);
5552 copy = NULL;
5553 }
Bram Moolenaare9a41262005-01-15 22:18:47 +00005554 }
5555
5556 return copy;
5557}
5558
5559/*
Bram Moolenaar8c711452005-01-14 21:53:12 +00005560 * Add item "item" to Dictionary "d".
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005561 * Returns FAIL when out of memory and when key already existed.
Bram Moolenaar8c711452005-01-14 21:53:12 +00005562 */
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005563 static int
Bram Moolenaar8c711452005-01-14 21:53:12 +00005564dict_add(d, item)
Bram Moolenaar33570922005-01-25 22:26:29 +00005565 dict_T *d;
5566 dictitem_T *item;
Bram Moolenaar8c711452005-01-14 21:53:12 +00005567{
Bram Moolenaar33570922005-01-25 22:26:29 +00005568 return hash_add(&d->dv_hashtab, item->di_key);
Bram Moolenaar8c711452005-01-14 21:53:12 +00005569}
5570
Bram Moolenaar8c711452005-01-14 21:53:12 +00005571/*
Bram Moolenaar05159a02005-02-26 23:04:13 +00005572 * Add a number or string entry to dictionary "d".
5573 * When "str" is NULL use number "nr", otherwise use "str".
5574 * Returns FAIL when out of memory and when key already exists.
5575 */
5576 int
5577dict_add_nr_str(d, key, nr, str)
5578 dict_T *d;
5579 char *key;
5580 long nr;
5581 char_u *str;
5582{
5583 dictitem_T *item;
5584
5585 item = dictitem_alloc((char_u *)key);
5586 if (item == NULL)
5587 return FAIL;
5588 item->di_tv.v_lock = 0;
5589 if (str == NULL)
5590 {
5591 item->di_tv.v_type = VAR_NUMBER;
5592 item->di_tv.vval.v_number = nr;
5593 }
5594 else
5595 {
5596 item->di_tv.v_type = VAR_STRING;
5597 item->di_tv.vval.v_string = vim_strsave(str);
5598 }
5599 if (dict_add(d, item) == FAIL)
5600 {
5601 dictitem_free(item);
5602 return FAIL;
5603 }
5604 return OK;
5605}
5606
5607/*
Bram Moolenaare9a41262005-01-15 22:18:47 +00005608 * Get the number of items in a Dictionary.
5609 */
5610 static long
5611dict_len(d)
Bram Moolenaar33570922005-01-25 22:26:29 +00005612 dict_T *d;
Bram Moolenaare9a41262005-01-15 22:18:47 +00005613{
Bram Moolenaare9a41262005-01-15 22:18:47 +00005614 if (d == NULL)
5615 return 0L;
Bram Moolenaar33570922005-01-25 22:26:29 +00005616 return d->dv_hashtab.ht_used;
Bram Moolenaare9a41262005-01-15 22:18:47 +00005617}
5618
5619/*
Bram Moolenaar8c711452005-01-14 21:53:12 +00005620 * Find item "key[len]" in Dictionary "d".
5621 * If "len" is negative use strlen(key).
5622 * Returns NULL when not found.
5623 */
Bram Moolenaar33570922005-01-25 22:26:29 +00005624 static dictitem_T *
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005625dict_find(d, key, len)
Bram Moolenaar33570922005-01-25 22:26:29 +00005626 dict_T *d;
Bram Moolenaar8c711452005-01-14 21:53:12 +00005627 char_u *key;
5628 int len;
5629{
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005630#define AKEYLEN 200
5631 char_u buf[AKEYLEN];
5632 char_u *akey;
5633 char_u *tofree = NULL;
Bram Moolenaar33570922005-01-25 22:26:29 +00005634 hashitem_T *hi;
Bram Moolenaar8c711452005-01-14 21:53:12 +00005635
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005636 if (len < 0)
5637 akey = key;
5638 else if (len >= AKEYLEN)
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00005639 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005640 tofree = akey = vim_strnsave(key, len);
5641 if (akey == NULL)
5642 return NULL;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00005643 }
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005644 else
5645 {
5646 /* Avoid a malloc/free by using buf[]. */
5647 STRNCPY(buf, key, len);
5648 buf[len] = NUL;
5649 akey = buf;
5650 }
5651
Bram Moolenaar33570922005-01-25 22:26:29 +00005652 hi = hash_find(&d->dv_hashtab, akey);
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005653 vim_free(tofree);
5654 if (HASHITEM_EMPTY(hi))
5655 return NULL;
5656 return HI2DI(hi);
Bram Moolenaar8c711452005-01-14 21:53:12 +00005657}
5658
5659/*
5660 * Return an allocated string with the string representation of a Dictionary.
5661 * May return NULL.
5662 */
5663 static char_u *
5664dict2string(tv)
Bram Moolenaar33570922005-01-25 22:26:29 +00005665 typval_T *tv;
Bram Moolenaar8c711452005-01-14 21:53:12 +00005666{
5667 garray_T ga;
5668 int first = TRUE;
5669 char_u *tofree;
5670 char_u numbuf[NUMBUFLEN];
Bram Moolenaar33570922005-01-25 22:26:29 +00005671 hashitem_T *hi;
Bram Moolenaar8c711452005-01-14 21:53:12 +00005672 char_u *s;
Bram Moolenaar33570922005-01-25 22:26:29 +00005673 dict_T *d;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005674 int todo;
Bram Moolenaar8c711452005-01-14 21:53:12 +00005675
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005676 if ((d = tv->vval.v_dict) == NULL)
Bram Moolenaar8c711452005-01-14 21:53:12 +00005677 return NULL;
5678 ga_init2(&ga, (int)sizeof(char), 80);
5679 ga_append(&ga, '{');
5680
Bram Moolenaar33570922005-01-25 22:26:29 +00005681 todo = d->dv_hashtab.ht_used;
Bram Moolenaar81bf7082005-02-12 14:31:42 +00005682 for (hi = d->dv_hashtab.ht_array; todo > 0 && !got_int; ++hi)
Bram Moolenaar8c711452005-01-14 21:53:12 +00005683 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005684 if (!HASHITEM_EMPTY(hi))
Bram Moolenaar8c711452005-01-14 21:53:12 +00005685 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005686 --todo;
5687
5688 if (first)
5689 first = FALSE;
5690 else
5691 ga_concat(&ga, (char_u *)", ");
5692
5693 tofree = string_quote(hi->hi_key, FALSE);
5694 if (tofree != NULL)
5695 {
5696 ga_concat(&ga, tofree);
5697 vim_free(tofree);
5698 }
5699 ga_concat(&ga, (char_u *)": ");
5700 s = tv2string(&HI2DI(hi)->di_tv, &tofree, numbuf);
5701 if (s != NULL)
5702 ga_concat(&ga, s);
Bram Moolenaar8c711452005-01-14 21:53:12 +00005703 vim_free(tofree);
Bram Moolenaar81bf7082005-02-12 14:31:42 +00005704 if (s == NULL)
5705 break;
Bram Moolenaar8c711452005-01-14 21:53:12 +00005706 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00005707 }
Bram Moolenaar81bf7082005-02-12 14:31:42 +00005708 if (todo > 0)
5709 {
5710 vim_free(ga.ga_data);
5711 return NULL;
5712 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00005713
5714 ga_append(&ga, '}');
5715 ga_append(&ga, NUL);
5716 return (char_u *)ga.ga_data;
5717}
5718
5719/*
5720 * Allocate a variable for a Dictionary and fill it from "*arg".
5721 * Return OK or FAIL. Returns NOTDONE for {expr}.
5722 */
5723 static int
5724get_dict_tv(arg, rettv, evaluate)
5725 char_u **arg;
Bram Moolenaar33570922005-01-25 22:26:29 +00005726 typval_T *rettv;
Bram Moolenaar8c711452005-01-14 21:53:12 +00005727 int evaluate;
5728{
Bram Moolenaar33570922005-01-25 22:26:29 +00005729 dict_T *d = NULL;
5730 typval_T tvkey;
5731 typval_T tv;
Bram Moolenaar8c711452005-01-14 21:53:12 +00005732 char_u *key;
Bram Moolenaar33570922005-01-25 22:26:29 +00005733 dictitem_T *item;
Bram Moolenaar8c711452005-01-14 21:53:12 +00005734 char_u *start = skipwhite(*arg + 1);
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005735 char_u buf[NUMBUFLEN];
Bram Moolenaar8c711452005-01-14 21:53:12 +00005736
5737 /*
5738 * First check if it's not a curly-braces thing: {expr}.
5739 * Must do this without evaluating, otherwise a function may be called
5740 * twice. Unfortunately this means we need to call eval1() twice for the
5741 * first item.
Bram Moolenaare9a41262005-01-15 22:18:47 +00005742 * But {} is an empty Dictionary.
Bram Moolenaar8c711452005-01-14 21:53:12 +00005743 */
Bram Moolenaare9a41262005-01-15 22:18:47 +00005744 if (*start != '}')
5745 {
5746 if (eval1(&start, &tv, FALSE) == FAIL) /* recursive! */
5747 return FAIL;
5748 if (*start == '}')
5749 return NOTDONE;
5750 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00005751
5752 if (evaluate)
5753 {
5754 d = dict_alloc();
5755 if (d == NULL)
5756 return FAIL;
5757 }
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005758 tvkey.v_type = VAR_UNKNOWN;
5759 tv.v_type = VAR_UNKNOWN;
Bram Moolenaar8c711452005-01-14 21:53:12 +00005760
5761 *arg = skipwhite(*arg + 1);
5762 while (**arg != '}' && **arg != NUL)
5763 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005764 if (eval1(arg, &tvkey, evaluate) == FAIL) /* recursive! */
Bram Moolenaar8c711452005-01-14 21:53:12 +00005765 goto failret;
5766 if (**arg != ':')
5767 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00005768 EMSG2(_("E720: Missing colon in Dictionary: %s"), *arg);
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005769 clear_tv(&tvkey);
Bram Moolenaar8c711452005-01-14 21:53:12 +00005770 goto failret;
5771 }
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005772 key = get_tv_string_buf(&tvkey, buf);
Bram Moolenaar8c711452005-01-14 21:53:12 +00005773 if (*key == NUL)
5774 {
5775 EMSG(_(e_emptykey));
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005776 clear_tv(&tvkey);
Bram Moolenaar8c711452005-01-14 21:53:12 +00005777 goto failret;
5778 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00005779
5780 *arg = skipwhite(*arg + 1);
5781 if (eval1(arg, &tv, evaluate) == FAIL) /* recursive! */
5782 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005783 clear_tv(&tvkey);
Bram Moolenaar8c711452005-01-14 21:53:12 +00005784 goto failret;
5785 }
5786 if (evaluate)
5787 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005788 item = dict_find(d, key, -1);
Bram Moolenaar8c711452005-01-14 21:53:12 +00005789 if (item != NULL)
5790 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00005791 EMSG(_("E721: Duplicate key in Dictionary"));
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005792 clear_tv(&tvkey);
Bram Moolenaar8c711452005-01-14 21:53:12 +00005793 clear_tv(&tv);
5794 goto failret;
5795 }
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005796 item = dictitem_alloc(key);
5797 clear_tv(&tvkey);
5798 if (item != NULL)
Bram Moolenaar8c711452005-01-14 21:53:12 +00005799 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00005800 item->di_tv = tv;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00005801 item->di_tv.v_lock = 0;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005802 if (dict_add(d, item) == FAIL)
5803 dictitem_free(item);
Bram Moolenaar8c711452005-01-14 21:53:12 +00005804 }
5805 }
5806
5807 if (**arg == '}')
5808 break;
5809 if (**arg != ',')
5810 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00005811 EMSG2(_("E722: Missing comma in Dictionary: %s"), *arg);
Bram Moolenaar8c711452005-01-14 21:53:12 +00005812 goto failret;
5813 }
5814 *arg = skipwhite(*arg + 1);
5815 }
5816
5817 if (**arg != '}')
5818 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00005819 EMSG2(_("E723: Missing end of Dictionary '}': %s"), *arg);
Bram Moolenaar8c711452005-01-14 21:53:12 +00005820failret:
5821 if (evaluate)
5822 dict_free(d);
5823 return FAIL;
5824 }
5825
5826 *arg = skipwhite(*arg + 1);
5827 if (evaluate)
5828 {
5829 rettv->v_type = VAR_DICT;
5830 rettv->vval.v_dict = d;
5831 ++d->dv_refcount;
5832 }
5833
5834 return OK;
5835}
5836
Bram Moolenaar8c711452005-01-14 21:53:12 +00005837/*
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005838 * Return a string with the string representation of a variable.
5839 * If the memory is allocated "tofree" is set to it, otherwise NULL.
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005840 * "numbuf" is used for a number.
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005841 * Does not put quotes around strings, as ":echo" displays values.
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005842 * May return NULL;
5843 */
5844 static char_u *
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005845echo_string(tv, tofree, numbuf)
Bram Moolenaar33570922005-01-25 22:26:29 +00005846 typval_T *tv;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005847 char_u **tofree;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005848 char_u *numbuf;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005849{
Bram Moolenaare9a41262005-01-15 22:18:47 +00005850 static int recurse = 0;
5851 char_u *r = NULL;
5852
Bram Moolenaar33570922005-01-25 22:26:29 +00005853 if (recurse >= DICT_MAXNEST)
Bram Moolenaare9a41262005-01-15 22:18:47 +00005854 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00005855 EMSG(_("E724: variable nested too deep for displaying"));
Bram Moolenaare9a41262005-01-15 22:18:47 +00005856 *tofree = NULL;
5857 return NULL;
5858 }
5859 ++recurse;
5860
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005861 switch (tv->v_type)
5862 {
5863 case VAR_FUNC:
5864 *tofree = NULL;
Bram Moolenaare9a41262005-01-15 22:18:47 +00005865 r = tv->vval.v_string;
5866 break;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005867 case VAR_LIST:
5868 *tofree = list2string(tv);
Bram Moolenaare9a41262005-01-15 22:18:47 +00005869 r = *tofree;
5870 break;
Bram Moolenaar8c711452005-01-14 21:53:12 +00005871 case VAR_DICT:
5872 *tofree = dict2string(tv);
Bram Moolenaare9a41262005-01-15 22:18:47 +00005873 r = *tofree;
5874 break;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005875 case VAR_STRING:
5876 case VAR_NUMBER:
Bram Moolenaare9a41262005-01-15 22:18:47 +00005877 *tofree = NULL;
5878 r = get_tv_string_buf(tv, numbuf);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005879 break;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005880 default:
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005881 EMSG2(_(e_intern2), "echo_string()");
Bram Moolenaare9a41262005-01-15 22:18:47 +00005882 *tofree = NULL;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005883 }
Bram Moolenaare9a41262005-01-15 22:18:47 +00005884
5885 --recurse;
5886 return r;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005887}
5888
5889/*
5890 * Return a string with the string representation of a variable.
5891 * If the memory is allocated "tofree" is set to it, otherwise NULL.
5892 * "numbuf" is used for a number.
5893 * Puts quotes around strings, so that they can be parsed back by eval().
5894 * May return NULL;
5895 */
5896 static char_u *
5897tv2string(tv, tofree, numbuf)
Bram Moolenaar33570922005-01-25 22:26:29 +00005898 typval_T *tv;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005899 char_u **tofree;
5900 char_u *numbuf;
5901{
5902 switch (tv->v_type)
5903 {
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005904 case VAR_FUNC:
5905 *tofree = string_quote(tv->vval.v_string, TRUE);
5906 return *tofree;
5907 case VAR_STRING:
5908 *tofree = string_quote(tv->vval.v_string, FALSE);
5909 return *tofree;
Bram Moolenaare9a41262005-01-15 22:18:47 +00005910 case VAR_NUMBER:
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005911 case VAR_LIST:
Bram Moolenaar8c711452005-01-14 21:53:12 +00005912 case VAR_DICT:
Bram Moolenaare9a41262005-01-15 22:18:47 +00005913 break;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005914 default:
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005915 EMSG2(_(e_intern2), "tv2string()");
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005916 }
Bram Moolenaare9a41262005-01-15 22:18:47 +00005917 return echo_string(tv, tofree, numbuf);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005918}
5919
5920/*
Bram Moolenaar33570922005-01-25 22:26:29 +00005921 * Return string "str" in ' quotes, doubling ' characters.
5922 * If "str" is NULL an empty string is assumed.
Bram Moolenaar8c711452005-01-14 21:53:12 +00005923 * If "function" is TRUE make it function('string').
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005924 */
5925 static char_u *
5926string_quote(str, function)
5927 char_u *str;
5928 int function;
5929{
Bram Moolenaar33570922005-01-25 22:26:29 +00005930 unsigned len;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005931 char_u *p, *r, *s;
5932
Bram Moolenaar33570922005-01-25 22:26:29 +00005933 len = (function ? 13 : 3);
5934 if (str != NULL)
5935 {
5936 len += STRLEN(str);
5937 for (p = str; *p != NUL; mb_ptr_adv(p))
5938 if (*p == '\'')
5939 ++len;
5940 }
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005941 s = r = alloc(len);
5942 if (r != NULL)
5943 {
5944 if (function)
5945 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00005946 STRCPY(r, "function('");
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005947 r += 10;
5948 }
5949 else
Bram Moolenaar8c711452005-01-14 21:53:12 +00005950 *r++ = '\'';
Bram Moolenaar33570922005-01-25 22:26:29 +00005951 if (str != NULL)
5952 for (p = str; *p != NUL; )
5953 {
5954 if (*p == '\'')
5955 *r++ = '\'';
5956 MB_COPY_CHAR(p, r);
5957 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00005958 *r++ = '\'';
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005959 if (function)
5960 *r++ = ')';
5961 *r++ = NUL;
5962 }
5963 return s;
5964}
5965
5966/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00005967 * Get the value of an environment variable.
5968 * "arg" is pointing to the '$'. It is advanced to after the name.
5969 * If the environment variable was not set, silently assume it is empty.
5970 * Always return OK.
5971 */
5972 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005973get_env_tv(arg, rettv, evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005974 char_u **arg;
Bram Moolenaar33570922005-01-25 22:26:29 +00005975 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005976 int evaluate;
5977{
5978 char_u *string = NULL;
5979 int len;
5980 int cc;
5981 char_u *name;
Bram Moolenaar05159a02005-02-26 23:04:13 +00005982 int mustfree = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005983
5984 ++*arg;
5985 name = *arg;
5986 len = get_env_len(arg);
5987 if (evaluate)
5988 {
5989 if (len != 0)
5990 {
5991 cc = name[len];
5992 name[len] = NUL;
Bram Moolenaar05159a02005-02-26 23:04:13 +00005993 /* first try vim_getenv(), fast for normal environment vars */
5994 string = vim_getenv(name, &mustfree);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005995 if (string != NULL && *string != NUL)
Bram Moolenaar05159a02005-02-26 23:04:13 +00005996 {
5997 if (!mustfree)
5998 string = vim_strsave(string);
5999 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00006000 else
6001 {
Bram Moolenaar05159a02005-02-26 23:04:13 +00006002 if (mustfree)
6003 vim_free(string);
6004
Bram Moolenaar071d4272004-06-13 20:20:40 +00006005 /* next try expanding things like $VIM and ${HOME} */
6006 string = expand_env_save(name - 1);
6007 if (string != NULL && *string == '$')
6008 {
6009 vim_free(string);
6010 string = NULL;
6011 }
6012 }
6013 name[len] = cc;
6014 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006015 rettv->v_type = VAR_STRING;
6016 rettv->vval.v_string = string;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006017 }
6018
6019 return OK;
6020}
6021
6022/*
6023 * Array with names and number of arguments of all internal functions
6024 * MUST BE KEPT SORTED IN strcmp() ORDER FOR BINARY SEARCH!
6025 */
6026static struct fst
6027{
6028 char *f_name; /* function name */
6029 char f_min_argc; /* minimal number of arguments */
6030 char f_max_argc; /* maximal number of arguments */
Bram Moolenaar33570922005-01-25 22:26:29 +00006031 void (*f_func) __ARGS((typval_T *args, typval_T *rvar));
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006032 /* implemenation of function */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006033} functions[] =
6034{
Bram Moolenaar0d660222005-01-07 21:51:51 +00006035 {"add", 2, 2, f_add},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006036 {"append", 2, 2, f_append},
6037 {"argc", 0, 0, f_argc},
6038 {"argidx", 0, 0, f_argidx},
6039 {"argv", 1, 1, f_argv},
6040 {"browse", 4, 4, f_browse},
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00006041 {"browsedir", 2, 2, f_browsedir},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006042 {"bufexists", 1, 1, f_bufexists},
6043 {"buffer_exists", 1, 1, f_bufexists}, /* obsolete */
6044 {"buffer_name", 1, 1, f_bufname}, /* obsolete */
6045 {"buffer_number", 1, 1, f_bufnr}, /* obsolete */
6046 {"buflisted", 1, 1, f_buflisted},
6047 {"bufloaded", 1, 1, f_bufloaded},
6048 {"bufname", 1, 1, f_bufname},
6049 {"bufnr", 1, 1, f_bufnr},
6050 {"bufwinnr", 1, 1, f_bufwinnr},
6051 {"byte2line", 1, 1, f_byte2line},
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00006052 {"byteidx", 2, 2, f_byteidx},
Bram Moolenaare9a41262005-01-15 22:18:47 +00006053 {"call", 2, 3, f_call},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006054 {"char2nr", 1, 1, f_char2nr},
6055 {"cindent", 1, 1, f_cindent},
6056 {"col", 1, 1, f_col},
6057 {"confirm", 1, 4, f_confirm},
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006058 {"copy", 1, 1, f_copy},
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00006059 {"count", 2, 4, f_count},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006060 {"cscope_connection",0,3, f_cscope_connection},
6061 {"cursor", 2, 2, f_cursor},
Bram Moolenaar81bf7082005-02-12 14:31:42 +00006062 {"deepcopy", 1, 2, f_deepcopy},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006063 {"delete", 1, 1, f_delete},
6064 {"did_filetype", 0, 0, f_did_filetype},
Bram Moolenaar47136d72004-10-12 20:02:24 +00006065 {"diff_filler", 1, 1, f_diff_filler},
6066 {"diff_hlID", 2, 2, f_diff_hlID},
Bram Moolenaare49b69a2005-01-08 16:11:57 +00006067 {"empty", 1, 1, f_empty},
Bram Moolenaar05159a02005-02-26 23:04:13 +00006068 {"errorlist", 0, 0, f_errorlist},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006069 {"escape", 2, 2, f_escape},
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00006070 {"eval", 1, 1, f_eval},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006071 {"eventhandler", 0, 0, f_eventhandler},
6072 {"executable", 1, 1, f_executable},
6073 {"exists", 1, 1, f_exists},
6074 {"expand", 1, 2, f_expand},
Bram Moolenaar8a283e52005-01-06 23:28:25 +00006075 {"extend", 2, 3, f_extend},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006076 {"file_readable", 1, 1, f_filereadable}, /* obsolete */
6077 {"filereadable", 1, 1, f_filereadable},
6078 {"filewritable", 1, 1, f_filewritable},
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00006079 {"filter", 2, 2, f_filter},
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00006080 {"finddir", 1, 3, f_finddir},
6081 {"findfile", 1, 3, f_findfile},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006082 {"fnamemodify", 2, 2, f_fnamemodify},
6083 {"foldclosed", 1, 1, f_foldclosed},
6084 {"foldclosedend", 1, 1, f_foldclosedend},
6085 {"foldlevel", 1, 1, f_foldlevel},
6086 {"foldtext", 0, 0, f_foldtext},
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00006087 {"foldtextresult", 1, 1, f_foldtextresult},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006088 {"foreground", 0, 0, f_foreground},
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006089 {"function", 1, 1, f_function},
Bram Moolenaar0d660222005-01-07 21:51:51 +00006090 {"get", 2, 3, f_get},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006091 {"getbufvar", 2, 2, f_getbufvar},
6092 {"getchar", 0, 1, f_getchar},
6093 {"getcharmod", 0, 0, f_getcharmod},
6094 {"getcmdline", 0, 0, f_getcmdline},
6095 {"getcmdpos", 0, 0, f_getcmdpos},
6096 {"getcwd", 0, 0, f_getcwd},
Bram Moolenaar46c9c732004-12-12 11:37:09 +00006097 {"getfontname", 0, 1, f_getfontname},
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00006098 {"getfperm", 1, 1, f_getfperm},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006099 {"getfsize", 1, 1, f_getfsize},
6100 {"getftime", 1, 1, f_getftime},
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00006101 {"getftype", 1, 1, f_getftype},
Bram Moolenaar0d660222005-01-07 21:51:51 +00006102 {"getline", 1, 2, f_getline},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006103 {"getreg", 0, 1, f_getreg},
6104 {"getregtype", 0, 1, f_getregtype},
6105 {"getwinposx", 0, 0, f_getwinposx},
6106 {"getwinposy", 0, 0, f_getwinposy},
6107 {"getwinvar", 2, 2, f_getwinvar},
6108 {"glob", 1, 1, f_glob},
6109 {"globpath", 2, 2, f_globpath},
6110 {"has", 1, 1, f_has},
Bram Moolenaare9a41262005-01-15 22:18:47 +00006111 {"has_key", 2, 2, f_has_key},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006112 {"hasmapto", 1, 2, f_hasmapto},
6113 {"highlightID", 1, 1, f_hlID}, /* obsolete */
6114 {"highlight_exists",1, 1, f_hlexists}, /* obsolete */
6115 {"histadd", 2, 2, f_histadd},
6116 {"histdel", 1, 2, f_histdel},
6117 {"histget", 1, 2, f_histget},
6118 {"histnr", 1, 1, f_histnr},
6119 {"hlID", 1, 1, f_hlID},
6120 {"hlexists", 1, 1, f_hlexists},
6121 {"hostname", 0, 0, f_hostname},
6122 {"iconv", 3, 3, f_iconv},
6123 {"indent", 1, 1, f_indent},
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00006124 {"index", 2, 4, f_index},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006125 {"input", 1, 2, f_input},
6126 {"inputdialog", 1, 3, f_inputdialog},
6127 {"inputrestore", 0, 0, f_inputrestore},
6128 {"inputsave", 0, 0, f_inputsave},
6129 {"inputsecret", 1, 2, f_inputsecret},
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006130 {"insert", 2, 3, f_insert},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006131 {"isdirectory", 1, 1, f_isdirectory},
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00006132 {"islocked", 1, 1, f_islocked},
Bram Moolenaar8c711452005-01-14 21:53:12 +00006133 {"items", 1, 1, f_items},
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00006134 {"join", 1, 2, f_join},
Bram Moolenaar8c711452005-01-14 21:53:12 +00006135 {"keys", 1, 1, f_keys},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006136 {"last_buffer_nr", 0, 0, f_last_buffer_nr},/* obsolete */
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006137 {"len", 1, 1, f_len},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006138 {"libcall", 3, 3, f_libcall},
6139 {"libcallnr", 3, 3, f_libcallnr},
6140 {"line", 1, 1, f_line},
6141 {"line2byte", 1, 1, f_line2byte},
6142 {"lispindent", 1, 1, f_lispindent},
6143 {"localtime", 0, 0, f_localtime},
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00006144 {"map", 2, 2, f_map},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006145 {"maparg", 1, 2, f_maparg},
6146 {"mapcheck", 1, 2, f_mapcheck},
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00006147 {"match", 2, 4, f_match},
6148 {"matchend", 2, 4, f_matchend},
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00006149 {"matchlist", 2, 4, f_matchlist},
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00006150 {"matchstr", 2, 4, f_matchstr},
Bram Moolenaar6cc16192005-01-08 21:49:45 +00006151 {"max", 1, 1, f_max},
6152 {"min", 1, 1, f_min},
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00006153#ifdef vim_mkdir
6154 {"mkdir", 1, 3, f_mkdir},
6155#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00006156 {"mode", 0, 0, f_mode},
6157 {"nextnonblank", 1, 1, f_nextnonblank},
6158 {"nr2char", 1, 1, f_nr2char},
6159 {"prevnonblank", 1, 1, f_prevnonblank},
Bram Moolenaar8c711452005-01-14 21:53:12 +00006160 {"range", 1, 3, f_range},
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00006161 {"readfile", 1, 3, f_readfile},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006162 {"remote_expr", 2, 3, f_remote_expr},
6163 {"remote_foreground", 1, 1, f_remote_foreground},
6164 {"remote_peek", 1, 2, f_remote_peek},
6165 {"remote_read", 1, 1, f_remote_read},
6166 {"remote_send", 2, 3, f_remote_send},
Bram Moolenaar8a283e52005-01-06 23:28:25 +00006167 {"remove", 2, 3, f_remove},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006168 {"rename", 2, 2, f_rename},
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00006169 {"repeat", 2, 2, f_repeat},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006170 {"resolve", 1, 1, f_resolve},
Bram Moolenaar0d660222005-01-07 21:51:51 +00006171 {"reverse", 1, 1, f_reverse},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006172 {"search", 1, 2, f_search},
6173 {"searchpair", 3, 5, f_searchpair},
6174 {"server2client", 2, 2, f_server2client},
6175 {"serverlist", 0, 0, f_serverlist},
6176 {"setbufvar", 3, 3, f_setbufvar},
6177 {"setcmdpos", 1, 1, f_setcmdpos},
6178 {"setline", 2, 2, f_setline},
6179 {"setreg", 2, 3, f_setreg},
6180 {"setwinvar", 3, 3, f_setwinvar},
6181 {"simplify", 1, 1, f_simplify},
Bram Moolenaar0d660222005-01-07 21:51:51 +00006182 {"sort", 1, 2, f_sort},
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00006183 {"split", 1, 2, f_split},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006184#ifdef HAVE_STRFTIME
6185 {"strftime", 1, 2, f_strftime},
6186#endif
Bram Moolenaar33570922005-01-25 22:26:29 +00006187 {"stridx", 2, 3, f_stridx},
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006188 {"string", 1, 1, f_string},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006189 {"strlen", 1, 1, f_strlen},
6190 {"strpart", 2, 3, f_strpart},
Bram Moolenaar532c7802005-01-27 14:44:31 +00006191 {"strridx", 2, 3, f_strridx},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006192 {"strtrans", 1, 1, f_strtrans},
6193 {"submatch", 1, 1, f_submatch},
6194 {"substitute", 4, 4, f_substitute},
6195 {"synID", 3, 3, f_synID},
6196 {"synIDattr", 2, 3, f_synIDattr},
6197 {"synIDtrans", 1, 1, f_synIDtrans},
Bram Moolenaarc0197e22004-09-13 20:26:32 +00006198 {"system", 1, 2, f_system},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006199 {"tempname", 0, 0, f_tempname},
6200 {"tolower", 1, 1, f_tolower},
6201 {"toupper", 1, 1, f_toupper},
Bram Moolenaar8299df92004-07-10 09:47:34 +00006202 {"tr", 3, 3, f_tr},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006203 {"type", 1, 1, f_type},
Bram Moolenaar8c711452005-01-14 21:53:12 +00006204 {"values", 1, 1, f_values},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006205 {"virtcol", 1, 1, f_virtcol},
6206 {"visualmode", 0, 1, f_visualmode},
6207 {"winbufnr", 1, 1, f_winbufnr},
6208 {"wincol", 0, 0, f_wincol},
6209 {"winheight", 1, 1, f_winheight},
6210 {"winline", 0, 0, f_winline},
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00006211 {"winnr", 0, 1, f_winnr},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006212 {"winrestcmd", 0, 0, f_winrestcmd},
6213 {"winwidth", 1, 1, f_winwidth},
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00006214 {"writefile", 2, 3, f_writefile},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006215};
6216
6217#if defined(FEAT_CMDL_COMPL) || defined(PROTO)
6218
6219/*
6220 * Function given to ExpandGeneric() to obtain the list of internal
6221 * or user defined function names.
6222 */
6223 char_u *
6224get_function_name(xp, idx)
6225 expand_T *xp;
6226 int idx;
6227{
6228 static int intidx = -1;
6229 char_u *name;
6230
6231 if (idx == 0)
6232 intidx = -1;
6233 if (intidx < 0)
6234 {
6235 name = get_user_func_name(xp, idx);
6236 if (name != NULL)
6237 return name;
6238 }
6239 if (++intidx < (int)(sizeof(functions) / sizeof(struct fst)))
6240 {
6241 STRCPY(IObuff, functions[intidx].f_name);
6242 STRCAT(IObuff, "(");
6243 if (functions[intidx].f_max_argc == 0)
6244 STRCAT(IObuff, ")");
6245 return IObuff;
6246 }
6247
6248 return NULL;
6249}
6250
6251/*
6252 * Function given to ExpandGeneric() to obtain the list of internal or
6253 * user defined variable or function names.
6254 */
6255/*ARGSUSED*/
6256 char_u *
6257get_expr_name(xp, idx)
6258 expand_T *xp;
6259 int idx;
6260{
6261 static int intidx = -1;
6262 char_u *name;
6263
6264 if (idx == 0)
6265 intidx = -1;
6266 if (intidx < 0)
6267 {
6268 name = get_function_name(xp, idx);
6269 if (name != NULL)
6270 return name;
6271 }
6272 return get_user_var_name(xp, ++intidx);
6273}
6274
6275#endif /* FEAT_CMDL_COMPL */
6276
6277/*
6278 * Find internal function in table above.
6279 * Return index, or -1 if not found
6280 */
6281 static int
6282find_internal_func(name)
6283 char_u *name; /* name of the function */
6284{
6285 int first = 0;
6286 int last = (int)(sizeof(functions) / sizeof(struct fst)) - 1;
6287 int cmp;
6288 int x;
6289
6290 /*
6291 * Find the function name in the table. Binary search.
6292 */
6293 while (first <= last)
6294 {
6295 x = first + ((unsigned)(last - first) >> 1);
6296 cmp = STRCMP(name, functions[x].f_name);
6297 if (cmp < 0)
6298 last = x - 1;
6299 else if (cmp > 0)
6300 first = x + 1;
6301 else
6302 return x;
6303 }
6304 return -1;
6305}
6306
6307/*
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006308 * Check if "name" is a variable of type VAR_FUNC. If so, return the function
6309 * name it contains, otherwise return "name".
6310 */
6311 static char_u *
6312deref_func_name(name, lenp)
6313 char_u *name;
6314 int *lenp;
6315{
Bram Moolenaar33570922005-01-25 22:26:29 +00006316 dictitem_T *v;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006317 int cc;
6318
6319 cc = name[*lenp];
6320 name[*lenp] = NUL;
Bram Moolenaara7043832005-01-21 11:56:39 +00006321 v = find_var(name, NULL);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006322 name[*lenp] = cc;
Bram Moolenaar33570922005-01-25 22:26:29 +00006323 if (v != NULL && v->di_tv.v_type == VAR_FUNC)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006324 {
Bram Moolenaar33570922005-01-25 22:26:29 +00006325 if (v->di_tv.vval.v_string == NULL)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006326 {
6327 *lenp = 0;
6328 return (char_u *)""; /* just in case */
6329 }
Bram Moolenaar33570922005-01-25 22:26:29 +00006330 *lenp = STRLEN(v->di_tv.vval.v_string);
6331 return v->di_tv.vval.v_string;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006332 }
6333
6334 return name;
6335}
6336
6337/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00006338 * Allocate a variable for the result of a function.
6339 * Return OK or FAIL.
6340 */
6341 static int
Bram Moolenaare9a41262005-01-15 22:18:47 +00006342get_func_tv(name, len, rettv, arg, firstline, lastline, doesrange,
6343 evaluate, selfdict)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006344 char_u *name; /* name of the function */
6345 int len; /* length of "name" */
Bram Moolenaar33570922005-01-25 22:26:29 +00006346 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006347 char_u **arg; /* argument, pointing to the '(' */
6348 linenr_T firstline; /* first line of range */
6349 linenr_T lastline; /* last line of range */
6350 int *doesrange; /* return: function handled range */
6351 int evaluate;
Bram Moolenaar33570922005-01-25 22:26:29 +00006352 dict_T *selfdict; /* Dictionary for "self" */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006353{
6354 char_u *argp;
6355 int ret = OK;
Bram Moolenaar33570922005-01-25 22:26:29 +00006356 typval_T argvars[MAX_FUNC_ARGS]; /* vars for arguments */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006357 int argcount = 0; /* number of arguments found */
6358
6359 /*
6360 * Get the arguments.
6361 */
6362 argp = *arg;
6363 while (argcount < MAX_FUNC_ARGS)
6364 {
6365 argp = skipwhite(argp + 1); /* skip the '(' or ',' */
6366 if (*argp == ')' || *argp == ',' || *argp == NUL)
6367 break;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006368 if (eval1(&argp, &argvars[argcount], evaluate) == FAIL)
6369 {
6370 ret = FAIL;
6371 break;
6372 }
6373 ++argcount;
6374 if (*argp != ',')
6375 break;
6376 }
6377 if (*argp == ')')
6378 ++argp;
6379 else
6380 ret = FAIL;
6381
6382 if (ret == OK)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006383 ret = call_func(name, len, rettv, argcount, argvars,
Bram Moolenaare9a41262005-01-15 22:18:47 +00006384 firstline, lastline, doesrange, evaluate, selfdict);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006385 else if (!aborting())
Bram Moolenaar33570922005-01-25 22:26:29 +00006386 {
6387 if (argcount == MAX_FUNC_ARGS)
Bram Moolenaar81bf7082005-02-12 14:31:42 +00006388 emsg_funcname("E740: Too many arguments for function %s", name);
Bram Moolenaar33570922005-01-25 22:26:29 +00006389 else
Bram Moolenaar81bf7082005-02-12 14:31:42 +00006390 emsg_funcname("E116: Invalid arguments for function %s", name);
Bram Moolenaar33570922005-01-25 22:26:29 +00006391 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00006392
6393 while (--argcount >= 0)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006394 clear_tv(&argvars[argcount]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006395
6396 *arg = skipwhite(argp);
6397 return ret;
6398}
6399
6400
6401/*
6402 * Call a function with its resolved parameters
6403 * Return OK or FAIL.
6404 */
6405 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006406call_func(name, len, rettv, argcount, argvars, firstline, lastline,
Bram Moolenaare9a41262005-01-15 22:18:47 +00006407 doesrange, evaluate, selfdict)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006408 char_u *name; /* name of the function */
6409 int len; /* length of "name" */
Bram Moolenaar33570922005-01-25 22:26:29 +00006410 typval_T *rettv; /* return value goes here */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006411 int argcount; /* number of "argvars" */
Bram Moolenaar33570922005-01-25 22:26:29 +00006412 typval_T *argvars; /* vars for arguments */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006413 linenr_T firstline; /* first line of range */
6414 linenr_T lastline; /* last line of range */
6415 int *doesrange; /* return: function handled range */
6416 int evaluate;
Bram Moolenaar33570922005-01-25 22:26:29 +00006417 dict_T *selfdict; /* Dictionary for "self" */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006418{
6419 int ret = FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006420#define ERROR_UNKNOWN 0
6421#define ERROR_TOOMANY 1
6422#define ERROR_TOOFEW 2
6423#define ERROR_SCRIPT 3
Bram Moolenaare9a41262005-01-15 22:18:47 +00006424#define ERROR_DICT 4
6425#define ERROR_NONE 5
6426#define ERROR_OTHER 6
Bram Moolenaar071d4272004-06-13 20:20:40 +00006427 int error = ERROR_NONE;
6428 int i;
6429 int llen;
6430 ufunc_T *fp;
6431 int cc;
6432#define FLEN_FIXED 40
6433 char_u fname_buf[FLEN_FIXED + 1];
6434 char_u *fname;
6435
6436 /*
6437 * In a script change <SID>name() and s:name() to K_SNR 123_name().
6438 * Change <SNR>123_name() to K_SNR 123_name().
6439 * Use fname_buf[] when it fits, otherwise allocate memory (slow).
6440 */
6441 cc = name[len];
6442 name[len] = NUL;
6443 llen = eval_fname_script(name);
6444 if (llen > 0)
6445 {
6446 fname_buf[0] = K_SPECIAL;
6447 fname_buf[1] = KS_EXTRA;
6448 fname_buf[2] = (int)KE_SNR;
6449 i = 3;
6450 if (eval_fname_sid(name)) /* "<SID>" or "s:" */
6451 {
6452 if (current_SID <= 0)
6453 error = ERROR_SCRIPT;
6454 else
6455 {
6456 sprintf((char *)fname_buf + 3, "%ld_", (long)current_SID);
6457 i = (int)STRLEN(fname_buf);
6458 }
6459 }
6460 if (i + STRLEN(name + llen) < FLEN_FIXED)
6461 {
6462 STRCPY(fname_buf + i, name + llen);
6463 fname = fname_buf;
6464 }
6465 else
6466 {
6467 fname = alloc((unsigned)(i + STRLEN(name + llen) + 1));
6468 if (fname == NULL)
6469 error = ERROR_OTHER;
6470 else
6471 {
6472 mch_memmove(fname, fname_buf, (size_t)i);
6473 STRCPY(fname + i, name + llen);
6474 }
6475 }
6476 }
6477 else
6478 fname = name;
6479
6480 *doesrange = FALSE;
6481
6482
6483 /* execute the function if no errors detected and executing */
6484 if (evaluate && error == ERROR_NONE)
6485 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006486 rettv->v_type = VAR_NUMBER; /* default is number rettv */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006487 error = ERROR_UNKNOWN;
6488
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +00006489 if (!builtin_function(fname))
Bram Moolenaar071d4272004-06-13 20:20:40 +00006490 {
6491 /*
6492 * User defined function.
6493 */
6494 fp = find_func(fname);
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +00006495
Bram Moolenaar071d4272004-06-13 20:20:40 +00006496#ifdef FEAT_AUTOCMD
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +00006497 /* Trigger FuncUndefined event, may load the function. */
6498 if (fp == NULL
6499 && apply_autocmds(EVENT_FUNCUNDEFINED,
6500 fname, fname, TRUE, NULL)
6501 && !aborting())
Bram Moolenaar071d4272004-06-13 20:20:40 +00006502 {
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +00006503 /* executed an autocommand, search for the function again */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006504 fp = find_func(fname);
6505 }
6506#endif
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +00006507 /* Try loading a package. */
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00006508 if (fp == NULL && script_autoload(fname) && !aborting())
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +00006509 {
6510 /* loaded a package, search for the function again */
6511 fp = find_func(fname);
6512 }
6513
Bram Moolenaar071d4272004-06-13 20:20:40 +00006514 if (fp != NULL)
6515 {
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00006516 if (fp->uf_flags & FC_RANGE)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006517 *doesrange = TRUE;
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00006518 if (argcount < fp->uf_args.ga_len)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006519 error = ERROR_TOOFEW;
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00006520 else if (!fp->uf_varargs && argcount > fp->uf_args.ga_len)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006521 error = ERROR_TOOMANY;
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00006522 else if ((fp->uf_flags & FC_DICT) && selfdict == NULL)
Bram Moolenaare9a41262005-01-15 22:18:47 +00006523 error = ERROR_DICT;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006524 else
6525 {
6526 /*
6527 * Call the user function.
6528 * Save and restore search patterns, script variables and
6529 * redo buffer.
6530 */
6531 save_search_patterns();
6532 saveRedobuff();
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00006533 ++fp->uf_calls;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006534 call_user_func(fp, argcount, argvars, rettv,
Bram Moolenaare9a41262005-01-15 22:18:47 +00006535 firstline, lastline,
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00006536 (fp->uf_flags & FC_DICT) ? selfdict : NULL);
6537 if (--fp->uf_calls <= 0 && isdigit(*fp->uf_name)
6538 && fp->uf_refcount <= 0)
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00006539 /* Function was unreferenced while being used, free it
6540 * now. */
6541 func_free(fp);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006542 restoreRedobuff();
6543 restore_search_patterns();
6544 error = ERROR_NONE;
6545 }
6546 }
6547 }
6548 else
6549 {
6550 /*
6551 * Find the function name in the table, call its implementation.
6552 */
6553 i = find_internal_func(fname);
6554 if (i >= 0)
6555 {
6556 if (argcount < functions[i].f_min_argc)
6557 error = ERROR_TOOFEW;
6558 else if (argcount > functions[i].f_max_argc)
6559 error = ERROR_TOOMANY;
6560 else
6561 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006562 argvars[argcount].v_type = VAR_UNKNOWN;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006563 functions[i].f_func(argvars, rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006564 error = ERROR_NONE;
6565 }
6566 }
6567 }
6568 /*
6569 * The function call (or "FuncUndefined" autocommand sequence) might
6570 * have been aborted by an error, an interrupt, or an explicitly thrown
6571 * exception that has not been caught so far. This situation can be
6572 * tested for by calling aborting(). For an error in an internal
6573 * function or for the "E132" error in call_user_func(), however, the
6574 * throw point at which the "force_abort" flag (temporarily reset by
6575 * emsg()) is normally updated has not been reached yet. We need to
6576 * update that flag first to make aborting() reliable.
6577 */
6578 update_force_abort();
6579 }
6580 if (error == ERROR_NONE)
6581 ret = OK;
6582
6583 /*
6584 * Report an error unless the argument evaluation or function call has been
6585 * cancelled due to an aborting error, an interrupt, or an exception.
6586 */
Bram Moolenaar8c711452005-01-14 21:53:12 +00006587 if (!aborting())
6588 {
6589 switch (error)
6590 {
6591 case ERROR_UNKNOWN:
Bram Moolenaar81bf7082005-02-12 14:31:42 +00006592 emsg_funcname("E117: Unknown function: %s", name);
Bram Moolenaar8c711452005-01-14 21:53:12 +00006593 break;
6594 case ERROR_TOOMANY:
Bram Moolenaar81bf7082005-02-12 14:31:42 +00006595 emsg_funcname(e_toomanyarg, name);
Bram Moolenaar8c711452005-01-14 21:53:12 +00006596 break;
6597 case ERROR_TOOFEW:
Bram Moolenaar81bf7082005-02-12 14:31:42 +00006598 emsg_funcname("E119: Not enough arguments for function: %s",
Bram Moolenaar8c711452005-01-14 21:53:12 +00006599 name);
6600 break;
6601 case ERROR_SCRIPT:
Bram Moolenaar81bf7082005-02-12 14:31:42 +00006602 emsg_funcname("E120: Using <SID> not in a script context: %s",
Bram Moolenaar8c711452005-01-14 21:53:12 +00006603 name);
6604 break;
Bram Moolenaare9a41262005-01-15 22:18:47 +00006605 case ERROR_DICT:
Bram Moolenaar81bf7082005-02-12 14:31:42 +00006606 emsg_funcname("E725: Calling dict function without Dictionary: %s",
Bram Moolenaare9a41262005-01-15 22:18:47 +00006607 name);
6608 break;
Bram Moolenaar8c711452005-01-14 21:53:12 +00006609 }
6610 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00006611
6612 name[len] = cc;
6613 if (fname != name && fname != fname_buf)
6614 vim_free(fname);
6615
6616 return ret;
6617}
6618
Bram Moolenaar81bf7082005-02-12 14:31:42 +00006619/*
6620 * Give an error message with a function name. Handle <SNR> things.
6621 */
6622 static void
6623emsg_funcname(msg, name)
6624 char *msg;
6625 char_u *name;
6626{
6627 char_u *p;
6628
6629 if (*name == K_SPECIAL)
6630 p = concat_str((char_u *)"<SNR>", name + 3);
6631 else
6632 p = name;
6633 EMSG2(_(msg), p);
6634 if (p != name)
6635 vim_free(p);
6636}
6637
Bram Moolenaar071d4272004-06-13 20:20:40 +00006638/*********************************************
6639 * Implementation of the built-in functions
6640 */
6641
6642/*
Bram Moolenaar0d660222005-01-07 21:51:51 +00006643 * "add(list, item)" function
Bram Moolenaar071d4272004-06-13 20:20:40 +00006644 */
6645 static void
Bram Moolenaar0d660222005-01-07 21:51:51 +00006646f_add(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00006647 typval_T *argvars;
6648 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006649{
Bram Moolenaar33570922005-01-25 22:26:29 +00006650 list_T *l;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006651
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006652 rettv->vval.v_number = 1; /* Default: Failed */
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006653 if (argvars[0].v_type == VAR_LIST)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006654 {
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00006655 if ((l = argvars[0].vval.v_list) != NULL
6656 && !tv_check_lock(l->lv_lock, (char_u *)"add()")
6657 && list_append_tv(l, &argvars[1]) == OK)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006658 copy_tv(&argvars[0], rettv);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006659 }
6660 else
Bram Moolenaar0d660222005-01-07 21:51:51 +00006661 EMSG(_(e_listreq));
6662}
6663
6664/*
6665 * "append(lnum, string/list)" function
6666 */
6667 static void
6668f_append(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00006669 typval_T *argvars;
6670 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +00006671{
6672 long lnum;
Bram Moolenaar33570922005-01-25 22:26:29 +00006673 list_T *l = NULL;
6674 listitem_T *li = NULL;
6675 typval_T *tv;
Bram Moolenaar0d660222005-01-07 21:51:51 +00006676 long added = 0;
6677
6678 rettv->vval.v_number = 1; /* Default: Failed */
6679 lnum = get_tv_lnum(argvars);
6680 if (lnum >= 0
6681 && lnum <= curbuf->b_ml.ml_line_count
6682 && u_save(lnum, lnum + 1) == OK)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006683 {
Bram Moolenaar0d660222005-01-07 21:51:51 +00006684 if (argvars[1].v_type == VAR_LIST)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006685 {
Bram Moolenaar0d660222005-01-07 21:51:51 +00006686 l = argvars[1].vval.v_list;
6687 if (l == NULL)
6688 return;
6689 li = l->lv_first;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006690 }
Bram Moolenaar0d660222005-01-07 21:51:51 +00006691 for (;;)
6692 {
6693 if (l == NULL)
6694 tv = &argvars[1]; /* append a string */
6695 else if (li == NULL)
6696 break; /* end of list */
6697 else
6698 tv = &li->li_tv; /* append item from list */
6699 ml_append(lnum + added, get_tv_string(tv), (colnr_T)0, FALSE);
6700 ++added;
6701 if (l == NULL)
6702 break;
6703 li = li->li_next;
6704 }
6705
6706 appended_lines_mark(lnum, added);
6707 if (curwin->w_cursor.lnum > lnum)
6708 curwin->w_cursor.lnum += added;
6709 rettv->vval.v_number = 0; /* Success */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006710 }
6711}
6712
6713/*
6714 * "argc()" function
6715 */
6716/* ARGSUSED */
6717 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006718f_argc(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00006719 typval_T *argvars;
6720 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006721{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006722 rettv->vval.v_number = ARGCOUNT;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006723}
6724
6725/*
6726 * "argidx()" function
6727 */
6728/* ARGSUSED */
6729 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006730f_argidx(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00006731 typval_T *argvars;
6732 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006733{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006734 rettv->vval.v_number = curwin->w_arg_idx;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006735}
6736
6737/*
6738 * "argv(nr)" function
6739 */
6740 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006741f_argv(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00006742 typval_T *argvars;
6743 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006744{
6745 int idx;
6746
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006747 idx = get_tv_number(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006748 if (idx >= 0 && idx < ARGCOUNT)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006749 rettv->vval.v_string = vim_strsave(alist_name(&ARGLIST[idx]));
Bram Moolenaar071d4272004-06-13 20:20:40 +00006750 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006751 rettv->vval.v_string = NULL;
6752 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006753}
6754
6755/*
6756 * "browse(save, title, initdir, default)" function
6757 */
6758/* ARGSUSED */
6759 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006760f_browse(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00006761 typval_T *argvars;
6762 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006763{
6764#ifdef FEAT_BROWSE
6765 int save;
6766 char_u *title;
6767 char_u *initdir;
6768 char_u *defname;
6769 char_u buf[NUMBUFLEN];
6770 char_u buf2[NUMBUFLEN];
6771
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006772 save = get_tv_number(&argvars[0]);
6773 title = get_tv_string(&argvars[1]);
6774 initdir = get_tv_string_buf(&argvars[2], buf);
6775 defname = get_tv_string_buf(&argvars[3], buf2);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006776
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006777 rettv->vval.v_string =
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00006778 do_browse(save ? BROWSE_SAVE : 0,
6779 title, defname, NULL, initdir, NULL, curbuf);
6780#else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006781 rettv->vval.v_string = NULL;
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00006782#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006783 rettv->v_type = VAR_STRING;
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00006784}
6785
6786/*
6787 * "browsedir(title, initdir)" function
6788 */
6789/* ARGSUSED */
6790 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006791f_browsedir(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00006792 typval_T *argvars;
6793 typval_T *rettv;
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00006794{
6795#ifdef FEAT_BROWSE
6796 char_u *title;
6797 char_u *initdir;
6798 char_u buf[NUMBUFLEN];
6799
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006800 title = get_tv_string(&argvars[0]);
6801 initdir = get_tv_string_buf(&argvars[1], buf);
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00006802
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006803 rettv->vval.v_string = do_browse(BROWSE_DIR,
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00006804 title, NULL, NULL, initdir, NULL, curbuf);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006805#else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006806 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006807#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006808 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006809}
6810
Bram Moolenaar33570922005-01-25 22:26:29 +00006811static buf_T *find_buffer __ARGS((typval_T *avar));
Bram Moolenaar0d660222005-01-07 21:51:51 +00006812
Bram Moolenaar071d4272004-06-13 20:20:40 +00006813/*
6814 * Find a buffer by number or exact name.
6815 */
6816 static buf_T *
6817find_buffer(avar)
Bram Moolenaar33570922005-01-25 22:26:29 +00006818 typval_T *avar;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006819{
6820 buf_T *buf = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006821
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006822 if (avar->v_type == VAR_NUMBER)
6823 buf = buflist_findnr((int)avar->vval.v_number);
Bram Moolenaar758711c2005-02-02 23:11:38 +00006824 else if (avar->v_type == VAR_STRING && avar->vval.v_string != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006825 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006826 buf = buflist_findname_exp(avar->vval.v_string);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006827 if (buf == NULL)
6828 {
6829 /* No full path name match, try a match with a URL or a "nofile"
6830 * buffer, these don't use the full path. */
6831 for (buf = firstbuf; buf != NULL; buf = buf->b_next)
6832 if (buf->b_fname != NULL
6833 && (path_with_url(buf->b_fname)
6834#ifdef FEAT_QUICKFIX
6835 || bt_nofile(buf)
6836#endif
6837 )
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006838 && STRCMP(buf->b_fname, avar->vval.v_string) == 0)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006839 break;
6840 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00006841 }
6842 return buf;
6843}
6844
6845/*
6846 * "bufexists(expr)" function
6847 */
6848 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006849f_bufexists(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00006850 typval_T *argvars;
6851 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006852{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006853 rettv->vval.v_number = (find_buffer(&argvars[0]) != NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006854}
6855
6856/*
6857 * "buflisted(expr)" function
6858 */
6859 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006860f_buflisted(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00006861 typval_T *argvars;
6862 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006863{
6864 buf_T *buf;
6865
6866 buf = find_buffer(&argvars[0]);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006867 rettv->vval.v_number = (buf != NULL && buf->b_p_bl);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006868}
6869
6870/*
6871 * "bufloaded(expr)" function
6872 */
6873 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006874f_bufloaded(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00006875 typval_T *argvars;
6876 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006877{
6878 buf_T *buf;
6879
6880 buf = find_buffer(&argvars[0]);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006881 rettv->vval.v_number = (buf != NULL && buf->b_ml.ml_mfp != NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006882}
6883
Bram Moolenaar33570922005-01-25 22:26:29 +00006884static buf_T *get_buf_tv __ARGS((typval_T *tv));
Bram Moolenaar0d660222005-01-07 21:51:51 +00006885
Bram Moolenaar071d4272004-06-13 20:20:40 +00006886/*
6887 * Get buffer by number or pattern.
6888 */
6889 static buf_T *
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006890get_buf_tv(tv)
Bram Moolenaar33570922005-01-25 22:26:29 +00006891 typval_T *tv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006892{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006893 char_u *name = tv->vval.v_string;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006894 int save_magic;
6895 char_u *save_cpo;
6896 buf_T *buf;
6897
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006898 if (tv->v_type == VAR_NUMBER)
6899 return buflist_findnr((int)tv->vval.v_number);
Bram Moolenaar758711c2005-02-02 23:11:38 +00006900 if (tv->v_type != VAR_STRING)
6901 return NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006902 if (name == NULL || *name == NUL)
6903 return curbuf;
6904 if (name[0] == '$' && name[1] == NUL)
6905 return lastbuf;
6906
6907 /* Ignore 'magic' and 'cpoptions' here to make scripts portable */
6908 save_magic = p_magic;
6909 p_magic = TRUE;
6910 save_cpo = p_cpo;
6911 p_cpo = (char_u *)"";
6912
6913 buf = buflist_findnr(buflist_findpat(name, name + STRLEN(name),
6914 TRUE, FALSE));
6915
6916 p_magic = save_magic;
6917 p_cpo = save_cpo;
6918
6919 /* If not found, try expanding the name, like done for bufexists(). */
6920 if (buf == NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006921 buf = find_buffer(tv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006922
6923 return buf;
6924}
6925
6926/*
6927 * "bufname(expr)" function
6928 */
6929 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006930f_bufname(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00006931 typval_T *argvars;
6932 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006933{
6934 buf_T *buf;
6935
6936 ++emsg_off;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006937 buf = get_buf_tv(&argvars[0]);
6938 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006939 if (buf != NULL && buf->b_fname != NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006940 rettv->vval.v_string = vim_strsave(buf->b_fname);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006941 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006942 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006943 --emsg_off;
6944}
6945
6946/*
6947 * "bufnr(expr)" function
6948 */
6949 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006950f_bufnr(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00006951 typval_T *argvars;
6952 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006953{
6954 buf_T *buf;
6955
6956 ++emsg_off;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006957 buf = get_buf_tv(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006958 if (buf != NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006959 rettv->vval.v_number = buf->b_fnum;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006960 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006961 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006962 --emsg_off;
6963}
6964
6965/*
6966 * "bufwinnr(nr)" function
6967 */
6968 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006969f_bufwinnr(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00006970 typval_T *argvars;
6971 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006972{
6973#ifdef FEAT_WINDOWS
6974 win_T *wp;
6975 int winnr = 0;
6976#endif
6977 buf_T *buf;
6978
6979 ++emsg_off;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006980 buf = get_buf_tv(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006981#ifdef FEAT_WINDOWS
6982 for (wp = firstwin; wp; wp = wp->w_next)
6983 {
6984 ++winnr;
6985 if (wp->w_buffer == buf)
6986 break;
6987 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006988 rettv->vval.v_number = (wp != NULL ? winnr : -1);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006989#else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006990 rettv->vval.v_number = (curwin->w_buffer == buf ? 1 : -1);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006991#endif
6992 --emsg_off;
6993}
6994
6995/*
6996 * "byte2line(byte)" function
6997 */
6998/*ARGSUSED*/
6999 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007000f_byte2line(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007001 typval_T *argvars;
7002 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007003{
7004#ifndef FEAT_BYTEOFF
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007005 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007006#else
7007 long boff = 0;
7008
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007009 boff = get_tv_number(&argvars[0]) - 1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007010 if (boff < 0)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007011 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007012 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007013 rettv->vval.v_number = ml_find_line_or_offset(curbuf,
Bram Moolenaar071d4272004-06-13 20:20:40 +00007014 (linenr_T)0, &boff);
7015#endif
7016}
7017
7018/*
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00007019 * "byteidx()" function
7020 */
7021/*ARGSUSED*/
7022 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007023f_byteidx(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007024 typval_T *argvars;
7025 typval_T *rettv;
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00007026{
7027#ifdef FEAT_MBYTE
7028 char_u *t;
7029#endif
7030 char_u *str;
7031 long idx;
7032
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007033 str = get_tv_string(&argvars[0]);
7034 idx = get_tv_number(&argvars[1]);
7035 rettv->vval.v_number = -1;
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00007036 if (idx < 0)
7037 return;
7038
7039#ifdef FEAT_MBYTE
7040 t = str;
7041 for ( ; idx > 0; idx--)
7042 {
7043 if (*t == NUL) /* EOL reached */
7044 return;
7045 t += mb_ptr2len_check(t);
7046 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007047 rettv->vval.v_number = t - str;
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00007048#else
7049 if (idx <= STRLEN(str))
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007050 rettv->vval.v_number = idx;
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00007051#endif
7052}
7053
7054/*
Bram Moolenaar8a283e52005-01-06 23:28:25 +00007055 * "call(func, arglist)" function
7056 */
7057 static void
7058f_call(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007059 typval_T *argvars;
7060 typval_T *rettv;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00007061{
7062 char_u *func;
Bram Moolenaar33570922005-01-25 22:26:29 +00007063 typval_T argv[MAX_FUNC_ARGS];
Bram Moolenaar8a283e52005-01-06 23:28:25 +00007064 int argc = 0;
Bram Moolenaar33570922005-01-25 22:26:29 +00007065 listitem_T *item;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00007066 int dummy;
Bram Moolenaar33570922005-01-25 22:26:29 +00007067 dict_T *selfdict = NULL;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00007068
7069 rettv->vval.v_number = 0;
7070 if (argvars[1].v_type != VAR_LIST)
7071 {
7072 EMSG(_(e_listreq));
7073 return;
7074 }
7075 if (argvars[1].vval.v_list == NULL)
7076 return;
7077
7078 if (argvars[0].v_type == VAR_FUNC)
7079 func = argvars[0].vval.v_string;
7080 else
7081 func = get_tv_string(&argvars[0]);
7082
Bram Moolenaare9a41262005-01-15 22:18:47 +00007083 if (argvars[2].v_type != VAR_UNKNOWN)
7084 {
7085 if (argvars[2].v_type != VAR_DICT)
7086 {
7087 EMSG(_(e_dictreq));
7088 return;
7089 }
7090 selfdict = argvars[2].vval.v_dict;
7091 }
7092
Bram Moolenaar8a283e52005-01-06 23:28:25 +00007093 for (item = argvars[1].vval.v_list->lv_first; item != NULL;
7094 item = item->li_next)
7095 {
7096 if (argc == MAX_FUNC_ARGS)
7097 {
Bram Moolenaare49b69a2005-01-08 16:11:57 +00007098 EMSG(_("E699: Too many arguments"));
Bram Moolenaar8a283e52005-01-06 23:28:25 +00007099 break;
7100 }
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00007101 /* Make a copy of each argument. This is needed to be able to set
7102 * v_lock to VAR_FIXED in the copy without changing the original list.
7103 */
Bram Moolenaar8a283e52005-01-06 23:28:25 +00007104 copy_tv(&item->li_tv, &argv[argc++]);
7105 }
7106
7107 if (item == NULL)
7108 (void)call_func(func, STRLEN(func), rettv, argc, argv,
Bram Moolenaare9a41262005-01-15 22:18:47 +00007109 curwin->w_cursor.lnum, curwin->w_cursor.lnum,
7110 &dummy, TRUE, selfdict);
Bram Moolenaar8a283e52005-01-06 23:28:25 +00007111
7112 /* Free the arguments. */
7113 while (argc > 0)
7114 clear_tv(&argv[--argc]);
7115}
7116
7117/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00007118 * "char2nr(string)" function
7119 */
7120 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007121f_char2nr(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#ifdef FEAT_MBYTE
7126 if (has_mbyte)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007127 rettv->vval.v_number =
7128 (*mb_ptr2char)(get_tv_string(&argvars[0]));
Bram Moolenaar071d4272004-06-13 20:20:40 +00007129 else
7130#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007131 rettv->vval.v_number = get_tv_string(&argvars[0])[0];
Bram Moolenaar071d4272004-06-13 20:20:40 +00007132}
7133
7134/*
7135 * "cindent(lnum)" function
7136 */
7137 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007138f_cindent(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007139 typval_T *argvars;
7140 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007141{
7142#ifdef FEAT_CINDENT
7143 pos_T pos;
7144 linenr_T lnum;
7145
7146 pos = curwin->w_cursor;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007147 lnum = get_tv_lnum(argvars);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007148 if (lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count)
7149 {
7150 curwin->w_cursor.lnum = lnum;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007151 rettv->vval.v_number = get_c_indent();
Bram Moolenaar071d4272004-06-13 20:20:40 +00007152 curwin->w_cursor = pos;
7153 }
7154 else
7155#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007156 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007157}
7158
7159/*
7160 * "col(string)" function
7161 */
7162 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007163f_col(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007164 typval_T *argvars;
7165 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007166{
7167 colnr_T col = 0;
7168 pos_T *fp;
7169
7170 fp = var2fpos(&argvars[0], FALSE);
7171 if (fp != NULL)
7172 {
7173 if (fp->col == MAXCOL)
7174 {
7175 /* '> can be MAXCOL, get the length of the line then */
7176 if (fp->lnum <= curbuf->b_ml.ml_line_count)
7177 col = STRLEN(ml_get(fp->lnum)) + 1;
7178 else
7179 col = MAXCOL;
7180 }
7181 else
7182 {
7183 col = fp->col + 1;
7184#ifdef FEAT_VIRTUALEDIT
7185 /* col(".") when the cursor is on the NUL at the end of the line
7186 * because of "coladd" can be seen as an extra column. */
7187 if (virtual_active() && fp == &curwin->w_cursor)
7188 {
7189 char_u *p = ml_get_cursor();
7190
7191 if (curwin->w_cursor.coladd >= (colnr_T)chartabsize(p,
7192 curwin->w_virtcol - curwin->w_cursor.coladd))
7193 {
7194# ifdef FEAT_MBYTE
7195 int l;
7196
7197 if (*p != NUL && p[(l = (*mb_ptr2len_check)(p))] == NUL)
7198 col += l;
7199# else
7200 if (*p != NUL && p[1] == NUL)
7201 ++col;
7202# endif
7203 }
7204 }
7205#endif
7206 }
7207 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007208 rettv->vval.v_number = col;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007209}
7210
7211/*
7212 * "confirm(message, buttons[, default [, type]])" function
7213 */
7214/*ARGSUSED*/
7215 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007216f_confirm(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007217 typval_T *argvars;
7218 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007219{
7220#if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
7221 char_u *message;
7222 char_u *buttons = NULL;
7223 char_u buf[NUMBUFLEN];
7224 char_u buf2[NUMBUFLEN];
7225 int def = 1;
7226 int type = VIM_GENERIC;
7227 int c;
7228
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007229 message = get_tv_string(&argvars[0]);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007230 if (argvars[1].v_type != VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007231 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007232 buttons = get_tv_string_buf(&argvars[1], buf);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007233 if (argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007234 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007235 def = get_tv_number(&argvars[2]);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007236 if (argvars[3].v_type != VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007237 {
Bram Moolenaara7043832005-01-21 11:56:39 +00007238 /* avoid that TOUPPER_ASC calls get_tv_string_buf() twice */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007239 c = *get_tv_string_buf(&argvars[3], buf2);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007240 switch (TOUPPER_ASC(c))
7241 {
7242 case 'E': type = VIM_ERROR; break;
7243 case 'Q': type = VIM_QUESTION; break;
7244 case 'I': type = VIM_INFO; break;
7245 case 'W': type = VIM_WARNING; break;
7246 case 'G': type = VIM_GENERIC; break;
7247 }
7248 }
7249 }
7250 }
7251
7252 if (buttons == NULL || *buttons == NUL)
7253 buttons = (char_u *)_("&Ok");
7254
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007255 rettv->vval.v_number = do_dialog(type, NULL, message, buttons,
Bram Moolenaar071d4272004-06-13 20:20:40 +00007256 def, NULL);
7257#else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007258 rettv->vval.v_number = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007259#endif
7260}
7261
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007262/*
7263 * "copy()" function
7264 */
7265 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007266f_copy(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007267 typval_T *argvars;
7268 typval_T *rettv;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007269{
Bram Moolenaar81bf7082005-02-12 14:31:42 +00007270 item_copy(&argvars[0], rettv, FALSE, 0);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007271}
Bram Moolenaar071d4272004-06-13 20:20:40 +00007272
7273/*
Bram Moolenaar8a283e52005-01-06 23:28:25 +00007274 * "count()" function
7275 */
7276 static void
7277f_count(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007278 typval_T *argvars;
7279 typval_T *rettv;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00007280{
Bram Moolenaar8a283e52005-01-06 23:28:25 +00007281 long n = 0;
7282 int ic = FALSE;
7283
Bram Moolenaare9a41262005-01-15 22:18:47 +00007284 if (argvars[0].v_type == VAR_LIST)
Bram Moolenaar8a283e52005-01-06 23:28:25 +00007285 {
Bram Moolenaar33570922005-01-25 22:26:29 +00007286 listitem_T *li;
7287 list_T *l;
Bram Moolenaare9a41262005-01-15 22:18:47 +00007288 long idx;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00007289
Bram Moolenaare9a41262005-01-15 22:18:47 +00007290 if ((l = argvars[0].vval.v_list) != NULL)
7291 {
7292 li = l->lv_first;
7293 if (argvars[2].v_type != VAR_UNKNOWN)
7294 {
7295 ic = get_tv_number(&argvars[2]);
7296 if (argvars[3].v_type != VAR_UNKNOWN)
7297 {
7298 idx = get_tv_number(&argvars[3]);
7299 li = list_find(l, idx);
7300 if (li == NULL)
7301 EMSGN(_(e_listidx), idx);
7302 }
7303 }
7304
7305 for ( ; li != NULL; li = li->li_next)
7306 if (tv_equal(&li->li_tv, &argvars[1], ic))
7307 ++n;
7308 }
Bram Moolenaar8a283e52005-01-06 23:28:25 +00007309 }
Bram Moolenaare9a41262005-01-15 22:18:47 +00007310 else if (argvars[0].v_type == VAR_DICT)
7311 {
Bram Moolenaar33570922005-01-25 22:26:29 +00007312 int todo;
7313 dict_T *d;
7314 hashitem_T *hi;
Bram Moolenaare9a41262005-01-15 22:18:47 +00007315
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00007316 if ((d = argvars[0].vval.v_dict) != NULL)
7317 {
Bram Moolenaare9a41262005-01-15 22:18:47 +00007318 if (argvars[2].v_type != VAR_UNKNOWN)
7319 {
7320 ic = get_tv_number(&argvars[2]);
7321 if (argvars[3].v_type != VAR_UNKNOWN)
7322 EMSG(_(e_invarg));
7323 }
7324
Bram Moolenaar33570922005-01-25 22:26:29 +00007325 todo = d->dv_hashtab.ht_used;
7326 for (hi = d->dv_hashtab.ht_array; todo > 0; ++hi)
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00007327 {
7328 if (!HASHITEM_EMPTY(hi))
7329 {
7330 --todo;
7331 if (tv_equal(&HI2DI(hi)->di_tv, &argvars[1], ic))
7332 ++n;
7333 }
7334 }
Bram Moolenaare9a41262005-01-15 22:18:47 +00007335 }
7336 }
7337 else
7338 EMSG2(_(e_listdictarg), "count()");
Bram Moolenaar8a283e52005-01-06 23:28:25 +00007339 rettv->vval.v_number = n;
7340}
7341
7342/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00007343 * "cscope_connection([{num} , {dbpath} [, {prepend}]])" function
7344 *
7345 * Checks the existence of a cscope connection.
7346 */
7347/*ARGSUSED*/
7348 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007349f_cscope_connection(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007350 typval_T *argvars;
7351 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007352{
7353#ifdef FEAT_CSCOPE
7354 int num = 0;
7355 char_u *dbpath = NULL;
7356 char_u *prepend = NULL;
7357 char_u buf[NUMBUFLEN];
7358
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007359 if (argvars[0].v_type != VAR_UNKNOWN
7360 && argvars[1].v_type != VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007361 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007362 num = (int)get_tv_number(&argvars[0]);
7363 dbpath = get_tv_string(&argvars[1]);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007364 if (argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007365 prepend = get_tv_string_buf(&argvars[2], buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007366 }
7367
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007368 rettv->vval.v_number = cs_connection(num, dbpath, prepend);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007369#else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007370 rettv->vval.v_number = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007371#endif
7372}
7373
7374/*
7375 * "cursor(lnum, col)" function
7376 *
7377 * Moves the cursor to the specified line and column
7378 */
7379/*ARGSUSED*/
7380 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007381f_cursor(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007382 typval_T *argvars;
7383 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007384{
7385 long line, col;
7386
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007387 line = get_tv_lnum(argvars);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007388 if (line > 0)
7389 curwin->w_cursor.lnum = line;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007390 col = get_tv_number(&argvars[1]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007391 if (col > 0)
7392 curwin->w_cursor.col = col - 1;
7393#ifdef FEAT_VIRTUALEDIT
7394 curwin->w_cursor.coladd = 0;
7395#endif
7396
7397 /* Make sure the cursor is in a valid position. */
7398 check_cursor();
7399#ifdef FEAT_MBYTE
7400 /* Correct cursor for multi-byte character. */
7401 if (has_mbyte)
7402 mb_adjust_cursor();
7403#endif
Bram Moolenaarf4b8e572004-06-24 15:53:16 +00007404
7405 curwin->w_set_curswant = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007406}
7407
7408/*
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007409 * "deepcopy()" function
Bram Moolenaar071d4272004-06-13 20:20:40 +00007410 */
7411 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007412f_deepcopy(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007413 typval_T *argvars;
7414 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007415{
Bram Moolenaar81bf7082005-02-12 14:31:42 +00007416 static int copyID = 0;
7417 int noref = 0;
7418
7419 if (argvars[1].v_type != VAR_UNKNOWN)
7420 noref = get_tv_number(&argvars[1]);
7421 if (noref < 0 || noref > 1)
7422 EMSG(_(e_invarg));
7423 else
7424 item_copy(&argvars[0], rettv, TRUE, noref == 0 ? ++copyID : 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007425}
7426
7427/*
7428 * "delete()" function
7429 */
7430 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007431f_delete(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007432 typval_T *argvars;
7433 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007434{
7435 if (check_restricted() || check_secure())
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007436 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007437 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007438 rettv->vval.v_number = mch_remove(get_tv_string(&argvars[0]));
Bram Moolenaar071d4272004-06-13 20:20:40 +00007439}
7440
7441/*
7442 * "did_filetype()" function
7443 */
7444/*ARGSUSED*/
7445 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007446f_did_filetype(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007447 typval_T *argvars;
7448 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007449{
7450#ifdef FEAT_AUTOCMD
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007451 rettv->vval.v_number = did_filetype;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007452#else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007453 rettv->vval.v_number = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007454#endif
7455}
7456
7457/*
Bram Moolenaar47136d72004-10-12 20:02:24 +00007458 * "diff_filler()" function
7459 */
7460/*ARGSUSED*/
7461 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007462f_diff_filler(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007463 typval_T *argvars;
7464 typval_T *rettv;
Bram Moolenaar47136d72004-10-12 20:02:24 +00007465{
7466#ifdef FEAT_DIFF
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007467 rettv->vval.v_number = diff_check_fill(curwin, get_tv_lnum(argvars));
Bram Moolenaar47136d72004-10-12 20:02:24 +00007468#endif
7469}
7470
7471/*
7472 * "diff_hlID()" function
7473 */
7474/*ARGSUSED*/
7475 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007476f_diff_hlID(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007477 typval_T *argvars;
7478 typval_T *rettv;
Bram Moolenaar47136d72004-10-12 20:02:24 +00007479{
7480#ifdef FEAT_DIFF
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007481 linenr_T lnum = get_tv_lnum(argvars);
Bram Moolenaar47136d72004-10-12 20:02:24 +00007482 static linenr_T prev_lnum = 0;
7483 static int changedtick = 0;
7484 static int fnum = 0;
7485 static int change_start = 0;
7486 static int change_end = 0;
7487 static enum hlf_value hlID = 0;
7488 int filler_lines;
7489 int col;
7490
7491 if (lnum != prev_lnum
7492 || changedtick != curbuf->b_changedtick
7493 || fnum != curbuf->b_fnum)
7494 {
7495 /* New line, buffer, change: need to get the values. */
7496 filler_lines = diff_check(curwin, lnum);
7497 if (filler_lines < 0)
7498 {
7499 if (filler_lines == -1)
7500 {
7501 change_start = MAXCOL;
7502 change_end = -1;
7503 if (diff_find_change(curwin, lnum, &change_start, &change_end))
7504 hlID = HLF_ADD; /* added line */
7505 else
7506 hlID = HLF_CHD; /* changed line */
7507 }
7508 else
7509 hlID = HLF_ADD; /* added line */
7510 }
7511 else
7512 hlID = (enum hlf_value)0;
7513 prev_lnum = lnum;
7514 changedtick = curbuf->b_changedtick;
7515 fnum = curbuf->b_fnum;
7516 }
7517
7518 if (hlID == HLF_CHD || hlID == HLF_TXD)
7519 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007520 col = get_tv_number(&argvars[1]) - 1;
Bram Moolenaar47136d72004-10-12 20:02:24 +00007521 if (col >= change_start && col <= change_end)
7522 hlID = HLF_TXD; /* changed text */
7523 else
7524 hlID = HLF_CHD; /* changed line */
7525 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007526 rettv->vval.v_number = hlID == (enum hlf_value)0 ? 0 : (int)hlID;
Bram Moolenaar47136d72004-10-12 20:02:24 +00007527#endif
7528}
7529
7530/*
Bram Moolenaare49b69a2005-01-08 16:11:57 +00007531 * "empty({expr})" function
7532 */
7533 static void
7534f_empty(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007535 typval_T *argvars;
7536 typval_T *rettv;
Bram Moolenaare49b69a2005-01-08 16:11:57 +00007537{
7538 int n;
7539
7540 switch (argvars[0].v_type)
7541 {
7542 case VAR_STRING:
7543 case VAR_FUNC:
7544 n = argvars[0].vval.v_string == NULL
7545 || *argvars[0].vval.v_string == NUL;
7546 break;
7547 case VAR_NUMBER:
7548 n = argvars[0].vval.v_number == 0;
7549 break;
7550 case VAR_LIST:
7551 n = argvars[0].vval.v_list == NULL
7552 || argvars[0].vval.v_list->lv_first == NULL;
7553 break;
Bram Moolenaare9a41262005-01-15 22:18:47 +00007554 case VAR_DICT:
7555 n = argvars[0].vval.v_dict == NULL
Bram Moolenaar33570922005-01-25 22:26:29 +00007556 || argvars[0].vval.v_dict->dv_hashtab.ht_used == 0;
Bram Moolenaare9a41262005-01-15 22:18:47 +00007557 break;
Bram Moolenaare49b69a2005-01-08 16:11:57 +00007558 default:
7559 EMSG2(_(e_intern2), "f_empty()");
7560 n = 0;
7561 }
7562
7563 rettv->vval.v_number = n;
7564}
7565
7566/*
Bram Moolenaar05159a02005-02-26 23:04:13 +00007567 * "errorlist()" function
7568 */
7569/*ARGSUSED*/
7570 static void
7571f_errorlist(argvars, rettv)
7572 typval_T *argvars;
7573 typval_T *rettv;
7574{
7575#ifdef FEAT_QUICKFIX
7576 list_T *l;
7577#endif
7578
7579 rettv->vval.v_number = FALSE;
7580#ifdef FEAT_QUICKFIX
7581 l = list_alloc();
7582 if (l != NULL)
7583 {
7584 if (get_errorlist(l) != FAIL)
7585 {
7586 rettv->vval.v_list = l;
7587 rettv->v_type = VAR_LIST;
7588 ++l->lv_refcount;
7589 }
7590 else
7591 list_free(l);
7592 }
7593#endif
7594}
7595
7596/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00007597 * "escape({string}, {chars})" function
7598 */
7599 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007600f_escape(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007601 typval_T *argvars;
7602 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007603{
7604 char_u buf[NUMBUFLEN];
7605
Bram Moolenaar758711c2005-02-02 23:11:38 +00007606 rettv->vval.v_string = vim_strsave_escaped(get_tv_string(&argvars[0]),
7607 get_tv_string_buf(&argvars[1], buf));
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007608 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007609}
7610
7611/*
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00007612 * "eval()" function
7613 */
7614/*ARGSUSED*/
7615 static void
7616f_eval(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007617 typval_T *argvars;
7618 typval_T *rettv;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00007619{
7620 char_u *s;
7621
7622 s = get_tv_string(&argvars[0]);
7623 s = skipwhite(s);
7624
7625 if (eval1(&s, rettv, TRUE) == FAIL)
7626 rettv->vval.v_number = 0;
7627 else if (*s != NUL)
7628 EMSG(_(e_trailing));
7629}
7630
7631/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00007632 * "eventhandler()" function
7633 */
7634/*ARGSUSED*/
7635 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007636f_eventhandler(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007637 typval_T *argvars;
7638 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007639{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007640 rettv->vval.v_number = vgetc_busy;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007641}
7642
7643/*
7644 * "executable()" function
7645 */
7646 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007647f_executable(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007648 typval_T *argvars;
7649 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007650{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007651 rettv->vval.v_number = mch_can_exe(get_tv_string(&argvars[0]));
Bram Moolenaar071d4272004-06-13 20:20:40 +00007652}
7653
7654/*
7655 * "exists()" function
7656 */
7657 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007658f_exists(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007659 typval_T *argvars;
7660 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007661{
7662 char_u *p;
7663 char_u *name;
7664 int n = FALSE;
7665 int len = 0;
7666
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007667 p = get_tv_string(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007668 if (*p == '$') /* environment variable */
7669 {
7670 /* first try "normal" environment variables (fast) */
7671 if (mch_getenv(p + 1) != NULL)
7672 n = TRUE;
7673 else
7674 {
7675 /* try expanding things like $VIM and ${HOME} */
7676 p = expand_env_save(p);
7677 if (p != NULL && *p != '$')
7678 n = TRUE;
7679 vim_free(p);
7680 }
7681 }
7682 else if (*p == '&' || *p == '+') /* option */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007683 n = (get_option_tv(&p, NULL, TRUE) == OK);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007684 else if (*p == '*') /* internal or user defined function */
7685 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007686 n = function_exists(p + 1);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007687 }
7688 else if (*p == ':')
7689 {
7690 n = cmd_exists(p + 1);
7691 }
7692 else if (*p == '#')
7693 {
7694#ifdef FEAT_AUTOCMD
7695 name = p + 1;
7696 p = vim_strchr(name, '#');
7697 if (p != NULL)
7698 n = au_exists(name, p, p + 1);
7699 else
7700 n = au_exists(name, name + STRLEN(name), NULL);
7701#endif
7702 }
7703 else /* internal variable */
7704 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00007705 char_u *tofree;
7706 typval_T tv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007707
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00007708 /* get_name_len() takes care of expanding curly braces */
7709 name = p;
7710 len = get_name_len(&p, &tofree, TRUE, FALSE);
7711 if (len > 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007712 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00007713 if (tofree != NULL)
7714 name = tofree;
7715 n = (get_var_tv(name, len, &tv, FALSE) == OK);
7716 if (n)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007717 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00007718 /* handle d.key, l[idx], f(expr) */
7719 n = (handle_subscript(&p, &tv, TRUE, FALSE) == OK);
7720 if (n)
7721 clear_tv(&tv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007722 }
7723 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00007724
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00007725 vim_free(tofree);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007726 }
7727
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007728 rettv->vval.v_number = n;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007729}
7730
7731/*
7732 * "expand()" function
7733 */
7734 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007735f_expand(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007736 typval_T *argvars;
7737 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007738{
7739 char_u *s;
7740 int len;
7741 char_u *errormsg;
7742 int flags = WILD_SILENT|WILD_USE_NL|WILD_LIST_NOTFOUND;
7743 expand_T xpc;
7744
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007745 rettv->v_type = VAR_STRING;
7746 s = get_tv_string(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007747 if (*s == '%' || *s == '#' || *s == '<')
7748 {
7749 ++emsg_off;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007750 rettv->vval.v_string = eval_vars(s, &len, NULL, &errormsg, s);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007751 --emsg_off;
7752 }
7753 else
7754 {
7755 /* When the optional second argument is non-zero, don't remove matches
7756 * for 'suffixes' and 'wildignore' */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007757 if (argvars[1].v_type != VAR_UNKNOWN && get_tv_number(&argvars[1]))
Bram Moolenaar071d4272004-06-13 20:20:40 +00007758 flags |= WILD_KEEP_ALL;
7759 ExpandInit(&xpc);
7760 xpc.xp_context = EXPAND_FILES;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007761 rettv->vval.v_string = ExpandOne(&xpc, s, NULL, flags, WILD_ALL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007762 ExpandCleanup(&xpc);
7763 }
7764}
7765
7766/*
Bram Moolenaar8a283e52005-01-06 23:28:25 +00007767 * "extend(list, list [, idx])" function
Bram Moolenaare9a41262005-01-15 22:18:47 +00007768 * "extend(dict, dict [, action])" function
Bram Moolenaar8a283e52005-01-06 23:28:25 +00007769 */
7770 static void
7771f_extend(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007772 typval_T *argvars;
7773 typval_T *rettv;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00007774{
Bram Moolenaar8a283e52005-01-06 23:28:25 +00007775 rettv->vval.v_number = 0;
Bram Moolenaare9a41262005-01-15 22:18:47 +00007776 if (argvars[0].v_type == VAR_LIST && argvars[1].v_type == VAR_LIST)
Bram Moolenaar8a283e52005-01-06 23:28:25 +00007777 {
Bram Moolenaar33570922005-01-25 22:26:29 +00007778 list_T *l1, *l2;
7779 listitem_T *item;
Bram Moolenaare9a41262005-01-15 22:18:47 +00007780 long before;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00007781
Bram Moolenaare9a41262005-01-15 22:18:47 +00007782 l1 = argvars[0].vval.v_list;
7783 l2 = argvars[1].vval.v_list;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00007784 if (l1 != NULL && !tv_check_lock(l1->lv_lock, (char_u *)"extend()")
7785 && l2 != NULL)
Bram Moolenaare9a41262005-01-15 22:18:47 +00007786 {
7787 if (argvars[2].v_type != VAR_UNKNOWN)
7788 {
Bram Moolenaar758711c2005-02-02 23:11:38 +00007789 before = get_tv_number(&argvars[2]);
7790 if (before == l1->lv_len)
7791 item = NULL;
7792 else
Bram Moolenaare9a41262005-01-15 22:18:47 +00007793 {
Bram Moolenaar758711c2005-02-02 23:11:38 +00007794 item = list_find(l1, before);
7795 if (item == NULL)
7796 {
7797 EMSGN(_(e_listidx), before);
7798 return;
7799 }
Bram Moolenaare9a41262005-01-15 22:18:47 +00007800 }
7801 }
7802 else
7803 item = NULL;
7804 list_extend(l1, l2, item);
7805
7806 ++l1->lv_refcount;
7807 copy_tv(&argvars[0], rettv);
7808 }
Bram Moolenaar8a283e52005-01-06 23:28:25 +00007809 }
Bram Moolenaare9a41262005-01-15 22:18:47 +00007810 else if (argvars[0].v_type == VAR_DICT && argvars[1].v_type == VAR_DICT)
7811 {
Bram Moolenaar33570922005-01-25 22:26:29 +00007812 dict_T *d1, *d2;
7813 dictitem_T *di1;
Bram Moolenaare9a41262005-01-15 22:18:47 +00007814 char_u *action;
7815 int i;
Bram Moolenaar33570922005-01-25 22:26:29 +00007816 hashitem_T *hi2;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00007817 int todo;
Bram Moolenaare9a41262005-01-15 22:18:47 +00007818
7819 d1 = argvars[0].vval.v_dict;
7820 d2 = argvars[1].vval.v_dict;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00007821 if (d1 != NULL && !tv_check_lock(d1->dv_lock, (char_u *)"extend()")
7822 && d2 != NULL)
Bram Moolenaare9a41262005-01-15 22:18:47 +00007823 {
7824 /* Check the third argument. */
7825 if (argvars[2].v_type != VAR_UNKNOWN)
7826 {
7827 static char *(av[]) = {"keep", "force", "error"};
7828
7829 action = get_tv_string(&argvars[2]);
7830 for (i = 0; i < 3; ++i)
7831 if (STRCMP(action, av[i]) == 0)
7832 break;
7833 if (i == 3)
7834 {
7835 EMSGN(_(e_invarg2), action);
7836 return;
7837 }
7838 }
7839 else
7840 action = (char_u *)"force";
7841
7842 /* Go over all entries in the second dict and add them to the
7843 * first dict. */
Bram Moolenaar33570922005-01-25 22:26:29 +00007844 todo = d2->dv_hashtab.ht_used;
7845 for (hi2 = d2->dv_hashtab.ht_array; todo > 0; ++hi2)
Bram Moolenaare9a41262005-01-15 22:18:47 +00007846 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00007847 if (!HASHITEM_EMPTY(hi2))
Bram Moolenaare9a41262005-01-15 22:18:47 +00007848 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00007849 --todo;
7850 di1 = dict_find(d1, hi2->hi_key, -1);
7851 if (di1 == NULL)
7852 {
7853 di1 = dictitem_copy(HI2DI(hi2));
7854 if (di1 != NULL && dict_add(d1, di1) == FAIL)
7855 dictitem_free(di1);
7856 }
7857 else if (*action == 'e')
7858 {
7859 EMSG2(_("E737: Key already exists: %s"), hi2->hi_key);
7860 break;
7861 }
7862 else if (*action == 'f')
7863 {
7864 clear_tv(&di1->di_tv);
7865 copy_tv(&HI2DI(hi2)->di_tv, &di1->di_tv);
7866 }
Bram Moolenaare9a41262005-01-15 22:18:47 +00007867 }
7868 }
7869
7870 ++d1->dv_refcount;
7871 copy_tv(&argvars[0], rettv);
7872 }
7873 }
7874 else
7875 EMSG2(_(e_listdictarg), "extend()");
Bram Moolenaar8a283e52005-01-06 23:28:25 +00007876}
7877
7878/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00007879 * "filereadable()" function
7880 */
7881 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007882f_filereadable(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007883 typval_T *argvars;
7884 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007885{
7886 FILE *fd;
7887 char_u *p;
7888 int n;
7889
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007890 p = get_tv_string(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007891 if (*p && !mch_isdir(p) && (fd = mch_fopen((char *)p, "r")) != NULL)
7892 {
7893 n = TRUE;
7894 fclose(fd);
7895 }
7896 else
7897 n = FALSE;
7898
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007899 rettv->vval.v_number = n;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007900}
7901
7902/*
7903 * return 0 for not writable, 1 for writable file, 2 for a dir which we have
7904 * rights to write into.
7905 */
7906 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007907f_filewritable(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007908 typval_T *argvars;
7909 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007910{
7911 char_u *p;
7912 int retval = 0;
7913#if defined(UNIX) || defined(VMS)
7914 int perm = 0;
7915#endif
7916
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007917 p = get_tv_string(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007918#if defined(UNIX) || defined(VMS)
7919 perm = mch_getperm(p);
7920#endif
7921#ifndef MACOS_CLASSIC /* TODO: get either mch_writable or mch_access */
7922 if (
7923# ifdef WIN3264
7924 mch_writable(p) &&
7925# else
7926# if defined(UNIX) || defined(VMS)
7927 (perm & 0222) &&
7928# endif
7929# endif
7930 mch_access((char *)p, W_OK) == 0
7931 )
7932#endif
7933 {
7934 ++retval;
7935 if (mch_isdir(p))
7936 ++retval;
7937 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007938 rettv->vval.v_number = retval;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007939}
7940
Bram Moolenaar33570922005-01-25 22:26:29 +00007941static void findfilendir __ARGS((typval_T *argvars, typval_T *rettv, int dir));
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00007942
7943 static void
Bram Moolenaar0d660222005-01-07 21:51:51 +00007944findfilendir(argvars, rettv, dir)
Bram Moolenaar33570922005-01-25 22:26:29 +00007945 typval_T *argvars;
7946 typval_T *rettv;
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00007947 int dir;
7948{
7949#ifdef FEAT_SEARCHPATH
7950 char_u *fname;
7951 char_u *fresult = NULL;
7952 char_u *path = *curbuf->b_p_path == NUL ? p_path : curbuf->b_p_path;
7953 char_u *p;
7954 char_u pathbuf[NUMBUFLEN];
7955 int count = 1;
7956 int first = TRUE;
7957
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007958 fname = get_tv_string(&argvars[0]);
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00007959
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007960 if (argvars[1].v_type != VAR_UNKNOWN)
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00007961 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007962 p = get_tv_string_buf(&argvars[1], pathbuf);
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00007963 if (*p != NUL)
7964 path = p;
7965
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007966 if (argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007967 count = get_tv_number(&argvars[2]);
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00007968 }
7969
7970 do
7971 {
7972 vim_free(fresult);
7973 fresult = find_file_in_path_option(first ? fname : NULL,
7974 first ? (int)STRLEN(fname) : 0,
7975 0, first, path, dir, NULL);
7976 first = FALSE;
7977 } while (--count > 0 && fresult != NULL);
7978
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007979 rettv->vval.v_string = fresult;
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00007980#else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007981 rettv->vval.v_string = NULL;
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00007982#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007983 rettv->v_type = VAR_STRING;
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00007984}
7985
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00007986static void prepare_vimvar __ARGS((int idx, typval_T *save_tv));
7987static void restore_vimvar __ARGS((int idx, typval_T *save_tv));
Bram Moolenaar33570922005-01-25 22:26:29 +00007988static void filter_map __ARGS((typval_T *argvars, typval_T *rettv, int map));
7989static int filter_map_one __ARGS((typval_T *tv, char_u *expr, int map, int *remp));
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00007990
7991/*
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00007992 * Prepare v: variable "idx" to be used.
7993 * Save the current typeval in "save_tv".
7994 * When not used yet add the variable to the v: hashtable.
7995 */
7996 static void
7997prepare_vimvar(idx, save_tv)
7998 int idx;
7999 typval_T *save_tv;
8000{
8001 *save_tv = vimvars[idx].vv_tv;
8002 if (vimvars[idx].vv_type == VAR_UNKNOWN)
8003 hash_add(&vimvarht, vimvars[idx].vv_di.di_key);
8004}
8005
8006/*
8007 * Restore v: variable "idx" to typeval "save_tv".
8008 * When no longer defined, remove the variable from the v: hashtable.
8009 */
8010 static void
8011restore_vimvar(idx, save_tv)
8012 int idx;
8013 typval_T *save_tv;
8014{
8015 hashitem_T *hi;
8016
8017 clear_tv(&vimvars[idx].vv_tv);
8018 vimvars[idx].vv_tv = *save_tv;
8019 if (vimvars[idx].vv_type == VAR_UNKNOWN)
8020 {
8021 hi = hash_find(&vimvarht, vimvars[idx].vv_di.di_key);
8022 if (HASHITEM_EMPTY(hi))
8023 EMSG2(_(e_intern2), "restore_vimvar()");
8024 else
8025 hash_remove(&vimvarht, hi);
8026 }
8027}
8028
8029/*
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00008030 * Implementation of map() and filter().
8031 */
8032 static void
8033filter_map(argvars, rettv, map)
Bram Moolenaar33570922005-01-25 22:26:29 +00008034 typval_T *argvars;
8035 typval_T *rettv;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00008036 int map;
8037{
8038 char_u buf[NUMBUFLEN];
Bram Moolenaare9a41262005-01-15 22:18:47 +00008039 char_u *expr;
Bram Moolenaar33570922005-01-25 22:26:29 +00008040 listitem_T *li, *nli;
8041 list_T *l = NULL;
8042 dictitem_T *di;
8043 hashtab_T *ht;
8044 hashitem_T *hi;
8045 dict_T *d = NULL;
8046 typval_T save_val;
8047 typval_T save_key;
Bram Moolenaare9a41262005-01-15 22:18:47 +00008048 int rem;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00008049 int todo;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00008050 char_u *msg = map ? (char_u *)"map()" : (char_u *)"filter()";
8051
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00008052
8053 rettv->vval.v_number = 0;
Bram Moolenaare9a41262005-01-15 22:18:47 +00008054 if (argvars[0].v_type == VAR_LIST)
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00008055 {
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00008056 if ((l = argvars[0].vval.v_list) == NULL
8057 || (map && tv_check_lock(l->lv_lock, msg)))
Bram Moolenaare9a41262005-01-15 22:18:47 +00008058 return;
8059 }
8060 else if (argvars[0].v_type == VAR_DICT)
8061 {
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00008062 if ((d = argvars[0].vval.v_dict) == NULL
8063 || (map && tv_check_lock(d->dv_lock, msg)))
Bram Moolenaare9a41262005-01-15 22:18:47 +00008064 return;
8065 }
8066 else
8067 {
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00008068 EMSG2(_(e_listdictarg), msg);
Bram Moolenaare9a41262005-01-15 22:18:47 +00008069 return;
8070 }
8071
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00008072 prepare_vimvar(VV_VAL, &save_val);
Bram Moolenaare9a41262005-01-15 22:18:47 +00008073 expr = skipwhite(get_tv_string_buf(&argvars[1], buf));
Bram Moolenaare9a41262005-01-15 22:18:47 +00008074
8075 if (argvars[0].v_type == VAR_DICT)
8076 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00008077 prepare_vimvar(VV_KEY, &save_key);
Bram Moolenaar33570922005-01-25 22:26:29 +00008078 vimvars[VV_KEY].vv_type = VAR_STRING;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00008079
Bram Moolenaar33570922005-01-25 22:26:29 +00008080 ht = &d->dv_hashtab;
Bram Moolenaara7043832005-01-21 11:56:39 +00008081 hash_lock(ht);
8082 todo = ht->ht_used;
8083 for (hi = ht->ht_array; todo > 0; ++hi)
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00008084 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00008085 if (!HASHITEM_EMPTY(hi))
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00008086 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00008087 --todo;
8088 di = HI2DI(hi);
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00008089 if (tv_check_lock(di->di_tv.v_lock, msg))
8090 break;
Bram Moolenaar33570922005-01-25 22:26:29 +00008091 vimvars[VV_KEY].vv_str = vim_strsave(di->di_key);
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00008092 if (filter_map_one(&di->di_tv, expr, map, &rem) == FAIL)
8093 break;
8094 if (!map && rem)
8095 dictitem_remove(d, di);
Bram Moolenaar33570922005-01-25 22:26:29 +00008096 clear_tv(&vimvars[VV_KEY].vv_tv);
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00008097 }
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00008098 }
Bram Moolenaara7043832005-01-21 11:56:39 +00008099 hash_unlock(ht);
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00008100
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00008101 restore_vimvar(VV_KEY, &save_key);
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00008102 }
Bram Moolenaare9a41262005-01-15 22:18:47 +00008103 else
8104 {
8105 for (li = l->lv_first; li != NULL; li = nli)
8106 {
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00008107 if (tv_check_lock(li->li_tv.v_lock, msg))
8108 break;
Bram Moolenaare9a41262005-01-15 22:18:47 +00008109 nli = li->li_next;
8110 if (filter_map_one(&li->li_tv, expr, map, &rem) == FAIL)
8111 break;
8112 if (!map && rem)
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00008113 listitem_remove(l, li);
Bram Moolenaare9a41262005-01-15 22:18:47 +00008114 }
8115 }
8116
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00008117 restore_vimvar(VV_VAL, &save_val);
Bram Moolenaare9a41262005-01-15 22:18:47 +00008118
8119 copy_tv(&argvars[0], rettv);
8120}
8121
8122 static int
8123filter_map_one(tv, expr, map, remp)
Bram Moolenaar33570922005-01-25 22:26:29 +00008124 typval_T *tv;
Bram Moolenaare9a41262005-01-15 22:18:47 +00008125 char_u *expr;
8126 int map;
8127 int *remp;
8128{
Bram Moolenaar33570922005-01-25 22:26:29 +00008129 typval_T rettv;
Bram Moolenaare9a41262005-01-15 22:18:47 +00008130 char_u *s;
8131
Bram Moolenaar33570922005-01-25 22:26:29 +00008132 copy_tv(tv, &vimvars[VV_VAL].vv_tv);
Bram Moolenaare9a41262005-01-15 22:18:47 +00008133 s = expr;
8134 if (eval1(&s, &rettv, TRUE) == FAIL)
8135 return FAIL;
8136 if (*s != NUL) /* check for trailing chars after expr */
8137 {
8138 EMSG2(_(e_invexpr2), s);
8139 return FAIL;
8140 }
8141 if (map)
8142 {
8143 /* map(): replace the list item value */
8144 clear_tv(tv);
8145 *tv = rettv;
8146 }
8147 else
8148 {
8149 /* filter(): when expr is zero remove the item */
8150 *remp = (get_tv_number(&rettv) == 0);
8151 clear_tv(&rettv);
8152 }
Bram Moolenaar33570922005-01-25 22:26:29 +00008153 clear_tv(&vimvars[VV_VAL].vv_tv);
Bram Moolenaare9a41262005-01-15 22:18:47 +00008154 return OK;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00008155}
8156
8157/*
8158 * "filter()" function
8159 */
8160 static void
8161f_filter(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008162 typval_T *argvars;
8163 typval_T *rettv;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00008164{
8165 filter_map(argvars, rettv, FALSE);
8166}
8167
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00008168/*
Bram Moolenaar0d660222005-01-07 21:51:51 +00008169 * "finddir({fname}[, {path}[, {count}]])" function
8170 */
8171 static void
8172f_finddir(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008173 typval_T *argvars;
8174 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +00008175{
8176 findfilendir(argvars, rettv, TRUE);
8177}
8178
8179/*
8180 * "findfile({fname}[, {path}[, {count}]])" function
8181 */
8182 static void
8183f_findfile(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008184 typval_T *argvars;
8185 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +00008186{
8187 findfilendir(argvars, rettv, FALSE);
8188}
8189
8190/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00008191 * "fnamemodify({fname}, {mods})" function
8192 */
8193 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008194f_fnamemodify(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008195 typval_T *argvars;
8196 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008197{
8198 char_u *fname;
8199 char_u *mods;
8200 int usedlen = 0;
8201 int len;
8202 char_u *fbuf = NULL;
8203 char_u buf[NUMBUFLEN];
8204
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008205 fname = get_tv_string(&argvars[0]);
8206 mods = get_tv_string_buf(&argvars[1], buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008207 len = (int)STRLEN(fname);
8208
8209 (void)modify_fname(mods, &usedlen, &fname, &fbuf, &len);
8210
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008211 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008212 if (fname == NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008213 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008214 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008215 rettv->vval.v_string = vim_strnsave(fname, len);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008216 vim_free(fbuf);
8217}
8218
Bram Moolenaar33570922005-01-25 22:26:29 +00008219static void foldclosed_both __ARGS((typval_T *argvars, typval_T *rettv, int end));
Bram Moolenaar071d4272004-06-13 20:20:40 +00008220
8221/*
8222 * "foldclosed()" function
8223 */
8224 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008225foldclosed_both(argvars, rettv, end)
Bram Moolenaar33570922005-01-25 22:26:29 +00008226 typval_T *argvars;
8227 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008228 int end;
8229{
8230#ifdef FEAT_FOLDING
8231 linenr_T lnum;
8232 linenr_T first, last;
8233
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008234 lnum = get_tv_lnum(argvars);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008235 if (lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count)
8236 {
8237 if (hasFoldingWin(curwin, lnum, &first, &last, FALSE, NULL))
8238 {
8239 if (end)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008240 rettv->vval.v_number = (varnumber_T)last;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008241 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008242 rettv->vval.v_number = (varnumber_T)first;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008243 return;
8244 }
8245 }
8246#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008247 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008248}
8249
8250/*
Bram Moolenaar0d660222005-01-07 21:51:51 +00008251 * "foldclosed()" function
8252 */
8253 static void
8254f_foldclosed(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008255 typval_T *argvars;
8256 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +00008257{
8258 foldclosed_both(argvars, rettv, FALSE);
8259}
8260
8261/*
8262 * "foldclosedend()" function
8263 */
8264 static void
8265f_foldclosedend(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008266 typval_T *argvars;
8267 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +00008268{
8269 foldclosed_both(argvars, rettv, TRUE);
8270}
8271
8272/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00008273 * "foldlevel()" function
8274 */
8275 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008276f_foldlevel(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008277 typval_T *argvars;
8278 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008279{
8280#ifdef FEAT_FOLDING
8281 linenr_T lnum;
8282
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008283 lnum = get_tv_lnum(argvars);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008284 if (lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008285 rettv->vval.v_number = foldLevel(lnum);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008286 else
8287#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008288 rettv->vval.v_number = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008289}
8290
8291/*
8292 * "foldtext()" function
8293 */
8294/*ARGSUSED*/
8295 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008296f_foldtext(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008297 typval_T *argvars;
8298 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008299{
8300#ifdef FEAT_FOLDING
8301 linenr_T lnum;
8302 char_u *s;
8303 char_u *r;
8304 int len;
8305 char *txt;
8306#endif
8307
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008308 rettv->v_type = VAR_STRING;
8309 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008310#ifdef FEAT_FOLDING
Bram Moolenaare9a41262005-01-15 22:18:47 +00008311 if ((linenr_T)vimvars[VV_FOLDSTART].vv_nr > 0
8312 && (linenr_T)vimvars[VV_FOLDEND].vv_nr
8313 <= curbuf->b_ml.ml_line_count
8314 && vimvars[VV_FOLDDASHES].vv_str != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008315 {
8316 /* Find first non-empty line in the fold. */
Bram Moolenaare9a41262005-01-15 22:18:47 +00008317 lnum = (linenr_T)vimvars[VV_FOLDSTART].vv_nr;
8318 while (lnum < (linenr_T)vimvars[VV_FOLDEND].vv_nr)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008319 {
8320 if (!linewhite(lnum))
8321 break;
8322 ++lnum;
8323 }
8324
8325 /* Find interesting text in this line. */
8326 s = skipwhite(ml_get(lnum));
8327 /* skip C comment-start */
8328 if (s[0] == '/' && (s[1] == '*' || s[1] == '/'))
Bram Moolenaar293ee4d2004-12-09 21:34:53 +00008329 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00008330 s = skipwhite(s + 2);
Bram Moolenaar293ee4d2004-12-09 21:34:53 +00008331 if (*skipwhite(s) == NUL
Bram Moolenaare9a41262005-01-15 22:18:47 +00008332 && lnum + 1 < (linenr_T)vimvars[VV_FOLDEND].vv_nr)
Bram Moolenaar293ee4d2004-12-09 21:34:53 +00008333 {
8334 s = skipwhite(ml_get(lnum + 1));
8335 if (*s == '*')
8336 s = skipwhite(s + 1);
8337 }
8338 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00008339 txt = _("+-%s%3ld lines: ");
8340 r = alloc((unsigned)(STRLEN(txt)
Bram Moolenaare9a41262005-01-15 22:18:47 +00008341 + STRLEN(vimvars[VV_FOLDDASHES].vv_str) /* for %s */
Bram Moolenaar071d4272004-06-13 20:20:40 +00008342 + 20 /* for %3ld */
8343 + STRLEN(s))); /* concatenated */
8344 if (r != NULL)
8345 {
Bram Moolenaare9a41262005-01-15 22:18:47 +00008346 sprintf((char *)r, txt, vimvars[VV_FOLDDASHES].vv_str,
8347 (long)((linenr_T)vimvars[VV_FOLDEND].vv_nr
8348 - (linenr_T)vimvars[VV_FOLDSTART].vv_nr + 1));
Bram Moolenaar071d4272004-06-13 20:20:40 +00008349 len = (int)STRLEN(r);
8350 STRCAT(r, s);
8351 /* remove 'foldmarker' and 'commentstring' */
8352 foldtext_cleanup(r + len);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008353 rettv->vval.v_string = r;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008354 }
8355 }
8356#endif
8357}
8358
8359/*
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00008360 * "foldtextresult(lnum)" function
8361 */
8362/*ARGSUSED*/
8363 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008364f_foldtextresult(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008365 typval_T *argvars;
8366 typval_T *rettv;
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00008367{
8368#ifdef FEAT_FOLDING
8369 linenr_T lnum;
8370 char_u *text;
8371 char_u buf[51];
8372 foldinfo_T foldinfo;
8373 int fold_count;
8374#endif
8375
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008376 rettv->v_type = VAR_STRING;
8377 rettv->vval.v_string = NULL;
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00008378#ifdef FEAT_FOLDING
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008379 lnum = get_tv_lnum(argvars);
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00008380 fold_count = foldedCount(curwin, lnum, &foldinfo);
8381 if (fold_count > 0)
8382 {
8383 text = get_foldtext(curwin, lnum, lnum + fold_count - 1,
8384 &foldinfo, buf);
8385 if (text == buf)
8386 text = vim_strsave(text);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008387 rettv->vval.v_string = text;
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00008388 }
8389#endif
8390}
8391
8392/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00008393 * "foreground()" function
8394 */
8395/*ARGSUSED*/
8396 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008397f_foreground(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008398 typval_T *argvars;
8399 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008400{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008401 rettv->vval.v_number = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008402#ifdef FEAT_GUI
8403 if (gui.in_use)
8404 gui_mch_set_foreground();
8405#else
8406# ifdef WIN32
8407 win32_set_foreground();
8408# endif
8409#endif
8410}
8411
8412/*
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008413 * "function()" function
8414 */
8415/*ARGSUSED*/
8416 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008417f_function(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008418 typval_T *argvars;
8419 typval_T *rettv;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008420{
8421 char_u *s;
8422
Bram Moolenaara7043832005-01-21 11:56:39 +00008423 rettv->vval.v_number = 0;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008424 s = get_tv_string(&argvars[0]);
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00008425 if (s == NULL || *s == NUL || VIM_ISDIGIT(*s))
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008426 EMSG2(_(e_invarg2), s);
8427 else if (!function_exists(s))
Bram Moolenaare49b69a2005-01-08 16:11:57 +00008428 EMSG2(_("E700: Unknown function: %s"), s);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008429 else
8430 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008431 rettv->vval.v_string = vim_strsave(s);
8432 rettv->v_type = VAR_FUNC;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008433 }
8434}
8435
8436/*
Bram Moolenaar0d660222005-01-07 21:51:51 +00008437 * "get()" function
8438 */
8439 static void
8440f_get(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008441 typval_T *argvars;
8442 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +00008443{
Bram Moolenaar33570922005-01-25 22:26:29 +00008444 listitem_T *li;
8445 list_T *l;
8446 dictitem_T *di;
8447 dict_T *d;
8448 typval_T *tv = NULL;
Bram Moolenaar0d660222005-01-07 21:51:51 +00008449
Bram Moolenaare9a41262005-01-15 22:18:47 +00008450 if (argvars[0].v_type == VAR_LIST)
Bram Moolenaar0d660222005-01-07 21:51:51 +00008451 {
Bram Moolenaare9a41262005-01-15 22:18:47 +00008452 if ((l = argvars[0].vval.v_list) != NULL)
Bram Moolenaar0d660222005-01-07 21:51:51 +00008453 {
Bram Moolenaare9a41262005-01-15 22:18:47 +00008454 li = list_find(l, get_tv_number(&argvars[1]));
8455 if (li != NULL)
8456 tv = &li->li_tv;
Bram Moolenaar0d660222005-01-07 21:51:51 +00008457 }
Bram Moolenaar0d660222005-01-07 21:51:51 +00008458 }
Bram Moolenaare9a41262005-01-15 22:18:47 +00008459 else if (argvars[0].v_type == VAR_DICT)
8460 {
8461 if ((d = argvars[0].vval.v_dict) != NULL)
8462 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00008463 di = dict_find(d, get_tv_string(&argvars[1]), -1);
Bram Moolenaare9a41262005-01-15 22:18:47 +00008464 if (di != NULL)
8465 tv = &di->di_tv;
8466 }
8467 }
8468 else
8469 EMSG2(_(e_listdictarg), "get()");
8470
8471 if (tv == NULL)
8472 {
8473 if (argvars[2].v_type == VAR_UNKNOWN)
8474 rettv->vval.v_number = 0;
8475 else
8476 copy_tv(&argvars[2], rettv);
8477 }
8478 else
8479 copy_tv(tv, rettv);
Bram Moolenaar0d660222005-01-07 21:51:51 +00008480}
8481
8482/*
8483 * "getbufvar()" function
8484 */
8485 static void
8486f_getbufvar(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008487 typval_T *argvars;
8488 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +00008489{
8490 buf_T *buf;
8491 buf_T *save_curbuf;
8492 char_u *varname;
Bram Moolenaar33570922005-01-25 22:26:29 +00008493 dictitem_T *v;
Bram Moolenaar0d660222005-01-07 21:51:51 +00008494
8495 ++emsg_off;
8496 buf = get_buf_tv(&argvars[0]);
8497 varname = get_tv_string(&argvars[1]);
8498
8499 rettv->v_type = VAR_STRING;
8500 rettv->vval.v_string = NULL;
8501
8502 if (buf != NULL && varname != NULL)
8503 {
8504 if (*varname == '&') /* buffer-local-option */
8505 {
8506 /* set curbuf to be our buf, temporarily */
8507 save_curbuf = curbuf;
8508 curbuf = buf;
8509
8510 get_option_tv(&varname, rettv, TRUE);
8511
8512 /* restore previous notion of curbuf */
8513 curbuf = save_curbuf;
8514 }
8515 else
8516 {
8517 /* look up the variable */
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00008518 v = find_var_in_ht(&buf->b_vars.dv_hashtab, varname, FALSE);
Bram Moolenaar0d660222005-01-07 21:51:51 +00008519 if (v != NULL)
Bram Moolenaar33570922005-01-25 22:26:29 +00008520 copy_tv(&v->di_tv, rettv);
Bram Moolenaar0d660222005-01-07 21:51:51 +00008521 }
8522 }
8523
8524 --emsg_off;
8525}
8526
8527/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00008528 * "getchar()" function
8529 */
8530 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008531f_getchar(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008532 typval_T *argvars;
8533 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008534{
8535 varnumber_T n;
8536
8537 ++no_mapping;
8538 ++allow_keys;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008539 if (argvars[0].v_type == VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008540 /* getchar(): blocking wait. */
8541 n = safe_vgetc();
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008542 else if (get_tv_number(&argvars[0]) == 1)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008543 /* getchar(1): only check if char avail */
8544 n = vpeekc();
8545 else if (vpeekc() == NUL)
8546 /* getchar(0) and no char avail: return zero */
8547 n = 0;
8548 else
8549 /* getchar(0) and char avail: return char */
8550 n = safe_vgetc();
8551 --no_mapping;
8552 --allow_keys;
8553
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008554 rettv->vval.v_number = n;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008555 if (IS_SPECIAL(n) || mod_mask != 0)
8556 {
8557 char_u temp[10]; /* modifier: 3, mbyte-char: 6, NUL: 1 */
8558 int i = 0;
8559
8560 /* Turn a special key into three bytes, plus modifier. */
8561 if (mod_mask != 0)
8562 {
8563 temp[i++] = K_SPECIAL;
8564 temp[i++] = KS_MODIFIER;
8565 temp[i++] = mod_mask;
8566 }
8567 if (IS_SPECIAL(n))
8568 {
8569 temp[i++] = K_SPECIAL;
8570 temp[i++] = K_SECOND(n);
8571 temp[i++] = K_THIRD(n);
8572 }
8573#ifdef FEAT_MBYTE
8574 else if (has_mbyte)
8575 i += (*mb_char2bytes)(n, temp + i);
8576#endif
8577 else
8578 temp[i++] = n;
8579 temp[i++] = NUL;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008580 rettv->v_type = VAR_STRING;
8581 rettv->vval.v_string = vim_strsave(temp);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008582 }
8583}
8584
8585/*
8586 * "getcharmod()" function
8587 */
8588/*ARGSUSED*/
8589 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008590f_getcharmod(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008591 typval_T *argvars;
8592 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008593{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008594 rettv->vval.v_number = mod_mask;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008595}
8596
8597/*
8598 * "getcmdline()" function
8599 */
8600/*ARGSUSED*/
8601 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008602f_getcmdline(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008603 typval_T *argvars;
8604 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008605{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008606 rettv->v_type = VAR_STRING;
8607 rettv->vval.v_string = get_cmdline_str();
Bram Moolenaar071d4272004-06-13 20:20:40 +00008608}
8609
8610/*
8611 * "getcmdpos()" function
8612 */
8613/*ARGSUSED*/
8614 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008615f_getcmdpos(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008616 typval_T *argvars;
8617 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008618{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008619 rettv->vval.v_number = get_cmdline_pos() + 1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008620}
8621
8622/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00008623 * "getcwd()" function
8624 */
8625/*ARGSUSED*/
8626 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008627f_getcwd(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008628 typval_T *argvars;
8629 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008630{
8631 char_u cwd[MAXPATHL];
8632
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008633 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008634 if (mch_dirname(cwd, MAXPATHL) == FAIL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008635 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008636 else
8637 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008638 rettv->vval.v_string = vim_strsave(cwd);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008639#ifdef BACKSLASH_IN_FILENAME
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008640 slash_adjust(rettv->vval.v_string);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008641#endif
8642 }
8643}
8644
8645/*
Bram Moolenaar46c9c732004-12-12 11:37:09 +00008646 * "getfontname()" function
8647 */
Bram Moolenaar1cd871b2004-12-19 22:46:22 +00008648/*ARGSUSED*/
Bram Moolenaar46c9c732004-12-12 11:37:09 +00008649 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008650f_getfontname(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008651 typval_T *argvars;
8652 typval_T *rettv;
Bram Moolenaar46c9c732004-12-12 11:37:09 +00008653{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008654 rettv->v_type = VAR_STRING;
8655 rettv->vval.v_string = NULL;
Bram Moolenaar46c9c732004-12-12 11:37:09 +00008656#ifdef FEAT_GUI
8657 if (gui.in_use)
8658 {
8659 GuiFont font;
8660 char_u *name = NULL;
8661
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008662 if (argvars[0].v_type == VAR_UNKNOWN)
Bram Moolenaar46c9c732004-12-12 11:37:09 +00008663 {
8664 /* Get the "Normal" font. Either the name saved by
8665 * hl_set_font_name() or from the font ID. */
8666 font = gui.norm_font;
8667 name = hl_get_font_name();
8668 }
8669 else
8670 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008671 name = get_tv_string(&argvars[0]);
Bram Moolenaar46c9c732004-12-12 11:37:09 +00008672 if (STRCMP(name, "*") == 0) /* don't use font dialog */
8673 return;
8674 font = gui_mch_get_font(name, FALSE);
8675 if (font == NOFONT)
8676 return; /* Invalid font name, return empty string. */
8677 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008678 rettv->vval.v_string = gui_mch_get_fontname(font, name);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008679 if (argvars[0].v_type != VAR_UNKNOWN)
Bram Moolenaar46c9c732004-12-12 11:37:09 +00008680 gui_mch_free_font(font);
8681 }
8682#endif
8683}
8684
8685/*
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00008686 * "getfperm({fname})" function
8687 */
8688 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008689f_getfperm(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008690 typval_T *argvars;
8691 typval_T *rettv;
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00008692{
8693 char_u *fname;
8694 struct stat st;
8695 char_u *perm = NULL;
8696 char_u flags[] = "rwx";
8697 int i;
8698
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008699 fname = get_tv_string(&argvars[0]);
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00008700
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008701 rettv->v_type = VAR_STRING;
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00008702 if (mch_stat((char *)fname, &st) >= 0)
8703 {
8704 perm = vim_strsave((char_u *)"---------");
8705 if (perm != NULL)
8706 {
8707 for (i = 0; i < 9; i++)
8708 {
8709 if (st.st_mode & (1 << (8 - i)))
8710 perm[i] = flags[i % 3];
8711 }
8712 }
8713 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008714 rettv->vval.v_string = perm;
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00008715}
8716
8717/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00008718 * "getfsize({fname})" function
8719 */
8720 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008721f_getfsize(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008722 typval_T *argvars;
8723 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008724{
8725 char_u *fname;
8726 struct stat st;
8727
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008728 fname = get_tv_string(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008729
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008730 rettv->v_type = VAR_NUMBER;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008731
8732 if (mch_stat((char *)fname, &st) >= 0)
8733 {
8734 if (mch_isdir(fname))
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008735 rettv->vval.v_number = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008736 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008737 rettv->vval.v_number = (varnumber_T)st.st_size;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008738 }
8739 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008740 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008741}
8742
8743/*
8744 * "getftime({fname})" function
8745 */
8746 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008747f_getftime(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 char_u *fname;
8752 struct stat st;
8753
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008754 fname = get_tv_string(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008755
8756 if (mch_stat((char *)fname, &st) >= 0)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008757 rettv->vval.v_number = (varnumber_T)st.st_mtime;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008758 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008759 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008760}
8761
8762/*
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00008763 * "getftype({fname})" function
8764 */
8765 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008766f_getftype(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008767 typval_T *argvars;
8768 typval_T *rettv;
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00008769{
8770 char_u *fname;
8771 struct stat st;
8772 char_u *type = NULL;
8773 char *t;
8774
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008775 fname = get_tv_string(&argvars[0]);
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00008776
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008777 rettv->v_type = VAR_STRING;
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00008778 if (mch_lstat((char *)fname, &st) >= 0)
8779 {
8780#ifdef S_ISREG
8781 if (S_ISREG(st.st_mode))
8782 t = "file";
8783 else if (S_ISDIR(st.st_mode))
8784 t = "dir";
8785# ifdef S_ISLNK
8786 else if (S_ISLNK(st.st_mode))
8787 t = "link";
8788# endif
8789# ifdef S_ISBLK
8790 else if (S_ISBLK(st.st_mode))
8791 t = "bdev";
8792# endif
8793# ifdef S_ISCHR
8794 else if (S_ISCHR(st.st_mode))
8795 t = "cdev";
8796# endif
8797# ifdef S_ISFIFO
8798 else if (S_ISFIFO(st.st_mode))
8799 t = "fifo";
8800# endif
8801# ifdef S_ISSOCK
8802 else if (S_ISSOCK(st.st_mode))
8803 t = "fifo";
8804# endif
8805 else
8806 t = "other";
8807#else
8808# ifdef S_IFMT
8809 switch (st.st_mode & S_IFMT)
8810 {
8811 case S_IFREG: t = "file"; break;
8812 case S_IFDIR: t = "dir"; break;
8813# ifdef S_IFLNK
8814 case S_IFLNK: t = "link"; break;
8815# endif
8816# ifdef S_IFBLK
8817 case S_IFBLK: t = "bdev"; break;
8818# endif
8819# ifdef S_IFCHR
8820 case S_IFCHR: t = "cdev"; break;
8821# endif
8822# ifdef S_IFIFO
8823 case S_IFIFO: t = "fifo"; break;
8824# endif
8825# ifdef S_IFSOCK
8826 case S_IFSOCK: t = "socket"; break;
8827# endif
8828 default: t = "other";
8829 }
8830# else
8831 if (mch_isdir(fname))
8832 t = "dir";
8833 else
8834 t = "file";
8835# endif
8836#endif
8837 type = vim_strsave((char_u *)t);
8838 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008839 rettv->vval.v_string = type;
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00008840}
8841
8842/*
Bram Moolenaar0d660222005-01-07 21:51:51 +00008843 * "getline(lnum)" function
8844 */
8845 static void
8846f_getline(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008847 typval_T *argvars;
8848 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +00008849{
8850 linenr_T lnum;
8851 linenr_T end;
8852 char_u *p;
Bram Moolenaar33570922005-01-25 22:26:29 +00008853 list_T *l;
8854 listitem_T *li;
Bram Moolenaar0d660222005-01-07 21:51:51 +00008855
8856 lnum = get_tv_lnum(argvars);
8857
8858 if (argvars[1].v_type == VAR_UNKNOWN)
8859 {
8860 if (lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count)
8861 p = ml_get(lnum);
8862 else
8863 p = (char_u *)"";
8864
8865 rettv->v_type = VAR_STRING;
8866 rettv->vval.v_string = vim_strsave(p);
8867 }
8868 else
8869 {
8870 end = get_tv_lnum(&argvars[1]);
8871 if (end < lnum)
8872 {
8873 EMSG(_(e_invrange));
8874 rettv->vval.v_number = 0;
8875 }
8876 else
8877 {
8878 l = list_alloc();
8879 if (l != NULL)
8880 {
8881 if (lnum < 1)
8882 lnum = 1;
8883 if (end > curbuf->b_ml.ml_line_count)
8884 end = curbuf->b_ml.ml_line_count;
8885 while (lnum <= end)
8886 {
8887 li = listitem_alloc();
8888 if (li == NULL)
8889 break;
8890 list_append(l, li);
8891 li->li_tv.v_type = VAR_STRING;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00008892 li->li_tv.v_lock = 0;
Bram Moolenaar0d660222005-01-07 21:51:51 +00008893 li->li_tv.vval.v_string = vim_strsave(ml_get(lnum++));
8894 }
8895 rettv->vval.v_list = l;
8896 rettv->v_type = VAR_LIST;
8897 ++l->lv_refcount;
8898 }
8899 }
8900 }
8901}
8902
8903/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00008904 * "getreg()" function
8905 */
8906 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008907f_getreg(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008908 typval_T *argvars;
8909 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008910{
8911 char_u *strregname;
8912 int regname;
8913
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008914 if (argvars[0].v_type != VAR_UNKNOWN)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008915 strregname = get_tv_string(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008916 else
Bram Moolenaare9a41262005-01-15 22:18:47 +00008917 strregname = vimvars[VV_REG].vv_str;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008918 regname = (strregname == NULL ? '"' : *strregname);
8919 if (regname == 0)
8920 regname = '"';
8921
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008922 rettv->v_type = VAR_STRING;
8923 rettv->vval.v_string = get_reg_contents(regname, TRUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008924}
8925
8926/*
8927 * "getregtype()" function
8928 */
8929 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008930f_getregtype(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008931 typval_T *argvars;
8932 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008933{
8934 char_u *strregname;
8935 int regname;
8936 char_u buf[NUMBUFLEN + 2];
8937 long reglen = 0;
8938
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008939 if (argvars[0].v_type != VAR_UNKNOWN)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008940 strregname = get_tv_string(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008941 else
8942 /* Default to v:register */
Bram Moolenaare9a41262005-01-15 22:18:47 +00008943 strregname = vimvars[VV_REG].vv_str;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008944
8945 regname = (strregname == NULL ? '"' : *strregname);
8946 if (regname == 0)
8947 regname = '"';
8948
8949 buf[0] = NUL;
8950 buf[1] = NUL;
8951 switch (get_reg_type(regname, &reglen))
8952 {
8953 case MLINE: buf[0] = 'V'; break;
8954 case MCHAR: buf[0] = 'v'; break;
8955#ifdef FEAT_VISUAL
8956 case MBLOCK:
8957 buf[0] = Ctrl_V;
8958 sprintf((char *)buf + 1, "%ld", reglen + 1);
8959 break;
8960#endif
8961 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008962 rettv->v_type = VAR_STRING;
8963 rettv->vval.v_string = vim_strsave(buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008964}
8965
8966/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00008967 * "getwinposx()" function
8968 */
8969/*ARGSUSED*/
8970 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008971f_getwinposx(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008972 typval_T *argvars;
8973 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008974{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008975 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008976#ifdef FEAT_GUI
8977 if (gui.in_use)
8978 {
8979 int x, y;
8980
8981 if (gui_mch_get_winpos(&x, &y) == OK)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008982 rettv->vval.v_number = x;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008983 }
8984#endif
8985}
8986
8987/*
8988 * "getwinposy()" function
8989 */
8990/*ARGSUSED*/
8991 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008992f_getwinposy(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008993 typval_T *argvars;
8994 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008995{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008996 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008997#ifdef FEAT_GUI
8998 if (gui.in_use)
8999 {
9000 int x, y;
9001
9002 if (gui_mch_get_winpos(&x, &y) == OK)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009003 rettv->vval.v_number = y;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009004 }
9005#endif
9006}
9007
9008/*
9009 * "getwinvar()" function
9010 */
9011 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009012f_getwinvar(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00009013 typval_T *argvars;
9014 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009015{
9016 win_T *win, *oldcurwin;
9017 char_u *varname;
Bram Moolenaar33570922005-01-25 22:26:29 +00009018 dictitem_T *v;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009019
9020 ++emsg_off;
9021 win = find_win_by_nr(&argvars[0]);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009022 varname = get_tv_string(&argvars[1]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009023
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009024 rettv->v_type = VAR_STRING;
9025 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009026
9027 if (win != NULL && varname != NULL)
9028 {
9029 if (*varname == '&') /* window-local-option */
9030 {
9031 /* set curwin to be our win, temporarily */
9032 oldcurwin = curwin;
9033 curwin = win;
9034
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009035 get_option_tv(&varname, rettv, 1);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009036
9037 /* restore previous notion of curwin */
9038 curwin = oldcurwin;
9039 }
9040 else
9041 {
9042 /* look up the variable */
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00009043 v = find_var_in_ht(&win->w_vars.dv_hashtab, varname, FALSE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009044 if (v != NULL)
Bram Moolenaar33570922005-01-25 22:26:29 +00009045 copy_tv(&v->di_tv, rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009046 }
9047 }
9048
9049 --emsg_off;
9050}
9051
9052/*
9053 * "glob()" function
9054 */
9055 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009056f_glob(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00009057 typval_T *argvars;
9058 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009059{
9060 expand_T xpc;
9061
9062 ExpandInit(&xpc);
9063 xpc.xp_context = EXPAND_FILES;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009064 rettv->v_type = VAR_STRING;
9065 rettv->vval.v_string = ExpandOne(&xpc, get_tv_string(&argvars[0]),
Bram Moolenaar071d4272004-06-13 20:20:40 +00009066 NULL, WILD_USE_NL|WILD_SILENT, WILD_ALL);
9067 ExpandCleanup(&xpc);
9068}
9069
9070/*
9071 * "globpath()" function
9072 */
9073 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009074f_globpath(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00009075 typval_T *argvars;
9076 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009077{
9078 char_u buf1[NUMBUFLEN];
9079
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009080 rettv->v_type = VAR_STRING;
9081 rettv->vval.v_string = globpath(get_tv_string(&argvars[0]),
9082 get_tv_string_buf(&argvars[1], buf1));
Bram Moolenaar071d4272004-06-13 20:20:40 +00009083}
9084
9085/*
9086 * "has()" function
9087 */
9088 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009089f_has(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00009090 typval_T *argvars;
9091 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009092{
9093 int i;
9094 char_u *name;
9095 int n = FALSE;
9096 static char *(has_list[]) =
9097 {
9098#ifdef AMIGA
9099 "amiga",
9100# ifdef FEAT_ARP
9101 "arp",
9102# endif
9103#endif
9104#ifdef __BEOS__
9105 "beos",
9106#endif
9107#ifdef MSDOS
9108# ifdef DJGPP
9109 "dos32",
9110# else
9111 "dos16",
9112# endif
9113#endif
9114#ifdef MACOS /* TODO: Should we add MACOS_CLASSIC, MACOS_X? (Dany) */
9115 "mac",
9116#endif
9117#if defined(MACOS_X_UNIX)
9118 "macunix",
9119#endif
9120#ifdef OS2
9121 "os2",
9122#endif
9123#ifdef __QNX__
9124 "qnx",
9125#endif
9126#ifdef RISCOS
9127 "riscos",
9128#endif
9129#ifdef UNIX
9130 "unix",
9131#endif
9132#ifdef VMS
9133 "vms",
9134#endif
9135#ifdef WIN16
9136 "win16",
9137#endif
9138#ifdef WIN32
9139 "win32",
9140#endif
9141#if defined(UNIX) && (defined(__CYGWIN32__) || defined(__CYGWIN__))
9142 "win32unix",
9143#endif
9144#ifdef WIN64
9145 "win64",
9146#endif
9147#ifdef EBCDIC
9148 "ebcdic",
9149#endif
9150#ifndef CASE_INSENSITIVE_FILENAME
9151 "fname_case",
9152#endif
9153#ifdef FEAT_ARABIC
9154 "arabic",
9155#endif
9156#ifdef FEAT_AUTOCMD
9157 "autocmd",
9158#endif
9159#ifdef FEAT_BEVAL
9160 "balloon_eval",
9161#endif
9162#if defined(SOME_BUILTIN_TCAPS) || defined(ALL_BUILTIN_TCAPS)
9163 "builtin_terms",
9164# ifdef ALL_BUILTIN_TCAPS
9165 "all_builtin_terms",
9166# endif
9167#endif
9168#ifdef FEAT_BYTEOFF
9169 "byte_offset",
9170#endif
9171#ifdef FEAT_CINDENT
9172 "cindent",
9173#endif
9174#ifdef FEAT_CLIENTSERVER
9175 "clientserver",
9176#endif
9177#ifdef FEAT_CLIPBOARD
9178 "clipboard",
9179#endif
9180#ifdef FEAT_CMDL_COMPL
9181 "cmdline_compl",
9182#endif
9183#ifdef FEAT_CMDHIST
9184 "cmdline_hist",
9185#endif
9186#ifdef FEAT_COMMENTS
9187 "comments",
9188#endif
9189#ifdef FEAT_CRYPT
9190 "cryptv",
9191#endif
9192#ifdef FEAT_CSCOPE
9193 "cscope",
9194#endif
9195#ifdef DEBUG
9196 "debug",
9197#endif
9198#ifdef FEAT_CON_DIALOG
9199 "dialog_con",
9200#endif
9201#ifdef FEAT_GUI_DIALOG
9202 "dialog_gui",
9203#endif
9204#ifdef FEAT_DIFF
9205 "diff",
9206#endif
9207#ifdef FEAT_DIGRAPHS
9208 "digraphs",
9209#endif
9210#ifdef FEAT_DND
9211 "dnd",
9212#endif
9213#ifdef FEAT_EMACS_TAGS
9214 "emacs_tags",
9215#endif
9216 "eval", /* always present, of course! */
9217#ifdef FEAT_EX_EXTRA
9218 "ex_extra",
9219#endif
9220#ifdef FEAT_SEARCH_EXTRA
9221 "extra_search",
9222#endif
9223#ifdef FEAT_FKMAP
9224 "farsi",
9225#endif
9226#ifdef FEAT_SEARCHPATH
9227 "file_in_path",
9228#endif
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00009229#if defined(UNIX) && !defined(USE_SYSTEM)
9230 "filterpipe",
9231#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00009232#ifdef FEAT_FIND_ID
9233 "find_in_path",
9234#endif
9235#ifdef FEAT_FOLDING
9236 "folding",
9237#endif
9238#ifdef FEAT_FOOTER
9239 "footer",
9240#endif
9241#if !defined(USE_SYSTEM) && defined(UNIX)
9242 "fork",
9243#endif
9244#ifdef FEAT_GETTEXT
9245 "gettext",
9246#endif
9247#ifdef FEAT_GUI
9248 "gui",
9249#endif
9250#ifdef FEAT_GUI_ATHENA
9251# ifdef FEAT_GUI_NEXTAW
9252 "gui_neXtaw",
9253# else
9254 "gui_athena",
9255# endif
9256#endif
Bram Moolenaar843ee412004-06-30 16:16:41 +00009257#ifdef FEAT_GUI_KDE
9258 "gui_kde",
9259#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00009260#ifdef FEAT_GUI_GTK
9261 "gui_gtk",
9262# ifdef HAVE_GTK2
9263 "gui_gtk2",
9264# endif
9265#endif
9266#ifdef FEAT_GUI_MAC
9267 "gui_mac",
9268#endif
9269#ifdef FEAT_GUI_MOTIF
9270 "gui_motif",
9271#endif
9272#ifdef FEAT_GUI_PHOTON
9273 "gui_photon",
9274#endif
9275#ifdef FEAT_GUI_W16
9276 "gui_win16",
9277#endif
9278#ifdef FEAT_GUI_W32
9279 "gui_win32",
9280#endif
9281#ifdef FEAT_HANGULIN
9282 "hangul_input",
9283#endif
9284#if defined(HAVE_ICONV_H) && defined(USE_ICONV)
9285 "iconv",
9286#endif
9287#ifdef FEAT_INS_EXPAND
9288 "insert_expand",
9289#endif
9290#ifdef FEAT_JUMPLIST
9291 "jumplist",
9292#endif
9293#ifdef FEAT_KEYMAP
9294 "keymap",
9295#endif
9296#ifdef FEAT_LANGMAP
9297 "langmap",
9298#endif
9299#ifdef FEAT_LIBCALL
9300 "libcall",
9301#endif
9302#ifdef FEAT_LINEBREAK
9303 "linebreak",
9304#endif
9305#ifdef FEAT_LISP
9306 "lispindent",
9307#endif
9308#ifdef FEAT_LISTCMDS
9309 "listcmds",
9310#endif
9311#ifdef FEAT_LOCALMAP
9312 "localmap",
9313#endif
9314#ifdef FEAT_MENU
9315 "menu",
9316#endif
9317#ifdef FEAT_SESSION
9318 "mksession",
9319#endif
9320#ifdef FEAT_MODIFY_FNAME
9321 "modify_fname",
9322#endif
9323#ifdef FEAT_MOUSE
9324 "mouse",
9325#endif
9326#ifdef FEAT_MOUSESHAPE
9327 "mouseshape",
9328#endif
9329#if defined(UNIX) || defined(VMS)
9330# ifdef FEAT_MOUSE_DEC
9331 "mouse_dec",
9332# endif
9333# ifdef FEAT_MOUSE_GPM
9334 "mouse_gpm",
9335# endif
9336# ifdef FEAT_MOUSE_JSB
9337 "mouse_jsbterm",
9338# endif
9339# ifdef FEAT_MOUSE_NET
9340 "mouse_netterm",
9341# endif
9342# ifdef FEAT_MOUSE_PTERM
9343 "mouse_pterm",
9344# endif
9345# ifdef FEAT_MOUSE_XTERM
9346 "mouse_xterm",
9347# endif
9348#endif
9349#ifdef FEAT_MBYTE
9350 "multi_byte",
9351#endif
9352#ifdef FEAT_MBYTE_IME
9353 "multi_byte_ime",
9354#endif
9355#ifdef FEAT_MULTI_LANG
9356 "multi_lang",
9357#endif
Bram Moolenaar325b7a22004-07-05 15:58:32 +00009358#ifdef FEAT_MZSCHEME
Bram Moolenaar33570922005-01-25 22:26:29 +00009359#ifndef DYNAMIC_MZSCHEME
Bram Moolenaar325b7a22004-07-05 15:58:32 +00009360 "mzscheme",
9361#endif
Bram Moolenaar33570922005-01-25 22:26:29 +00009362#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00009363#ifdef FEAT_OLE
9364 "ole",
9365#endif
9366#ifdef FEAT_OSFILETYPE
9367 "osfiletype",
9368#endif
9369#ifdef FEAT_PATH_EXTRA
9370 "path_extra",
9371#endif
9372#ifdef FEAT_PERL
9373#ifndef DYNAMIC_PERL
9374 "perl",
9375#endif
9376#endif
9377#ifdef FEAT_PYTHON
9378#ifndef DYNAMIC_PYTHON
9379 "python",
9380#endif
9381#endif
9382#ifdef FEAT_POSTSCRIPT
9383 "postscript",
9384#endif
9385#ifdef FEAT_PRINTER
9386 "printer",
9387#endif
Bram Moolenaar05159a02005-02-26 23:04:13 +00009388#ifdef FEAT_PROFILE
9389 "profile",
9390#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00009391#ifdef FEAT_QUICKFIX
9392 "quickfix",
9393#endif
9394#ifdef FEAT_RIGHTLEFT
9395 "rightleft",
9396#endif
9397#if defined(FEAT_RUBY) && !defined(DYNAMIC_RUBY)
9398 "ruby",
9399#endif
9400#ifdef FEAT_SCROLLBIND
9401 "scrollbind",
9402#endif
9403#ifdef FEAT_CMDL_INFO
9404 "showcmd",
9405 "cmdline_info",
9406#endif
9407#ifdef FEAT_SIGNS
9408 "signs",
9409#endif
9410#ifdef FEAT_SMARTINDENT
9411 "smartindent",
9412#endif
9413#ifdef FEAT_SNIFF
9414 "sniff",
9415#endif
9416#ifdef FEAT_STL_OPT
9417 "statusline",
9418#endif
9419#ifdef FEAT_SUN_WORKSHOP
9420 "sun_workshop",
9421#endif
9422#ifdef FEAT_NETBEANS_INTG
9423 "netbeans_intg",
9424#endif
9425#ifdef FEAT_SYN_HL
9426 "syntax",
9427#endif
9428#if defined(USE_SYSTEM) || !defined(UNIX)
9429 "system",
9430#endif
9431#ifdef FEAT_TAG_BINS
9432 "tag_binary",
9433#endif
9434#ifdef FEAT_TAG_OLDSTATIC
9435 "tag_old_static",
9436#endif
9437#ifdef FEAT_TAG_ANYWHITE
9438 "tag_any_white",
9439#endif
9440#ifdef FEAT_TCL
9441# ifndef DYNAMIC_TCL
9442 "tcl",
9443# endif
9444#endif
9445#ifdef TERMINFO
9446 "terminfo",
9447#endif
9448#ifdef FEAT_TERMRESPONSE
9449 "termresponse",
9450#endif
9451#ifdef FEAT_TEXTOBJ
9452 "textobjects",
9453#endif
9454#ifdef HAVE_TGETENT
9455 "tgetent",
9456#endif
9457#ifdef FEAT_TITLE
9458 "title",
9459#endif
9460#ifdef FEAT_TOOLBAR
9461 "toolbar",
9462#endif
9463#ifdef FEAT_USR_CMDS
9464 "user-commands", /* was accidentally included in 5.4 */
9465 "user_commands",
9466#endif
9467#ifdef FEAT_VIMINFO
9468 "viminfo",
9469#endif
9470#ifdef FEAT_VERTSPLIT
9471 "vertsplit",
9472#endif
9473#ifdef FEAT_VIRTUALEDIT
9474 "virtualedit",
9475#endif
9476#ifdef FEAT_VISUAL
9477 "visual",
9478#endif
9479#ifdef FEAT_VISUALEXTRA
9480 "visualextra",
9481#endif
9482#ifdef FEAT_VREPLACE
9483 "vreplace",
9484#endif
9485#ifdef FEAT_WILDIGN
9486 "wildignore",
9487#endif
9488#ifdef FEAT_WILDMENU
9489 "wildmenu",
9490#endif
9491#ifdef FEAT_WINDOWS
9492 "windows",
9493#endif
9494#ifdef FEAT_WAK
9495 "winaltkeys",
9496#endif
9497#ifdef FEAT_WRITEBACKUP
9498 "writebackup",
9499#endif
9500#ifdef FEAT_XIM
9501 "xim",
9502#endif
9503#ifdef FEAT_XFONTSET
9504 "xfontset",
9505#endif
9506#ifdef USE_XSMP
9507 "xsmp",
9508#endif
9509#ifdef USE_XSMP_INTERACT
9510 "xsmp_interact",
9511#endif
9512#ifdef FEAT_XCLIPBOARD
9513 "xterm_clipboard",
9514#endif
9515#ifdef FEAT_XTERM_SAVE
9516 "xterm_save",
9517#endif
9518#if defined(UNIX) && defined(FEAT_X11)
9519 "X11",
9520#endif
9521 NULL
9522 };
9523
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009524 name = get_tv_string(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009525 for (i = 0; has_list[i] != NULL; ++i)
9526 if (STRICMP(name, has_list[i]) == 0)
9527 {
9528 n = TRUE;
9529 break;
9530 }
9531
9532 if (n == FALSE)
9533 {
9534 if (STRNICMP(name, "patch", 5) == 0)
9535 n = has_patch(atoi((char *)name + 5));
9536 else if (STRICMP(name, "vim_starting") == 0)
9537 n = (starting != 0);
9538#ifdef DYNAMIC_TCL
9539 else if (STRICMP(name, "tcl") == 0)
9540 n = tcl_enabled(FALSE);
9541#endif
9542#if defined(USE_ICONV) && defined(DYNAMIC_ICONV)
9543 else if (STRICMP(name, "iconv") == 0)
9544 n = iconv_enabled(FALSE);
9545#endif
Bram Moolenaar33570922005-01-25 22:26:29 +00009546#ifdef DYNAMIC_MZSCHEME
9547 else if (STRICMP(name, "mzscheme") == 0)
9548 n = mzscheme_enabled(FALSE);
9549#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00009550#ifdef DYNAMIC_RUBY
9551 else if (STRICMP(name, "ruby") == 0)
9552 n = ruby_enabled(FALSE);
9553#endif
9554#ifdef DYNAMIC_PYTHON
9555 else if (STRICMP(name, "python") == 0)
9556 n = python_enabled(FALSE);
9557#endif
9558#ifdef DYNAMIC_PERL
9559 else if (STRICMP(name, "perl") == 0)
9560 n = perl_enabled(FALSE);
9561#endif
9562#ifdef FEAT_GUI
9563 else if (STRICMP(name, "gui_running") == 0)
9564 n = (gui.in_use || gui.starting);
9565# ifdef FEAT_GUI_W32
9566 else if (STRICMP(name, "gui_win32s") == 0)
9567 n = gui_is_win32s();
9568# endif
9569# ifdef FEAT_BROWSE
9570 else if (STRICMP(name, "browse") == 0)
9571 n = gui.in_use; /* gui_mch_browse() works when GUI is running */
9572# endif
9573#endif
9574#ifdef FEAT_SYN_HL
9575 else if (STRICMP(name, "syntax_items") == 0)
9576 n = syntax_present(curbuf);
9577#endif
9578#if defined(WIN3264)
9579 else if (STRICMP(name, "win95") == 0)
9580 n = mch_windows95();
9581#endif
Bram Moolenaar35a9aaa2004-10-24 19:23:07 +00009582#ifdef FEAT_NETBEANS_INTG
9583 else if (STRICMP(name, "netbeans_enabled") == 0)
9584 n = usingNetbeans;
9585#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00009586 }
9587
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009588 rettv->vval.v_number = n;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009589}
9590
9591/*
Bram Moolenaare9a41262005-01-15 22:18:47 +00009592 * "has_key()" function
9593 */
9594 static void
9595f_has_key(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00009596 typval_T *argvars;
9597 typval_T *rettv;
Bram Moolenaare9a41262005-01-15 22:18:47 +00009598{
9599 rettv->vval.v_number = 0;
9600 if (argvars[0].v_type != VAR_DICT)
9601 {
9602 EMSG(_(e_dictreq));
9603 return;
9604 }
9605 if (argvars[0].vval.v_dict == NULL)
9606 return;
9607
9608 rettv->vval.v_number = dict_find(argvars[0].vval.v_dict,
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00009609 get_tv_string(&argvars[1]), -1) != NULL;
Bram Moolenaare9a41262005-01-15 22:18:47 +00009610}
9611
9612/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00009613 * "hasmapto()" function
9614 */
9615 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009616f_hasmapto(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00009617 typval_T *argvars;
9618 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009619{
9620 char_u *name;
9621 char_u *mode;
9622 char_u buf[NUMBUFLEN];
9623
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009624 name = get_tv_string(&argvars[0]);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009625 if (argvars[1].v_type == VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009626 mode = (char_u *)"nvo";
9627 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009628 mode = get_tv_string_buf(&argvars[1], buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009629
9630 if (map_to_exists(name, mode))
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009631 rettv->vval.v_number = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009632 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009633 rettv->vval.v_number = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009634}
9635
9636/*
9637 * "histadd()" function
9638 */
9639/*ARGSUSED*/
9640 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009641f_histadd(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00009642 typval_T *argvars;
9643 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009644{
9645#ifdef FEAT_CMDHIST
9646 int histype;
9647 char_u *str;
9648 char_u buf[NUMBUFLEN];
9649#endif
9650
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009651 rettv->vval.v_number = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009652 if (check_restricted() || check_secure())
9653 return;
9654#ifdef FEAT_CMDHIST
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009655 histype = get_histtype(get_tv_string(&argvars[0]));
Bram Moolenaar071d4272004-06-13 20:20:40 +00009656 if (histype >= 0)
9657 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009658 str = get_tv_string_buf(&argvars[1], buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009659 if (*str != NUL)
9660 {
9661 add_to_history(histype, str, FALSE, NUL);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009662 rettv->vval.v_number = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009663 return;
9664 }
9665 }
9666#endif
9667}
9668
9669/*
9670 * "histdel()" function
9671 */
9672/*ARGSUSED*/
9673 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009674f_histdel(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00009675 typval_T *argvars;
9676 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009677{
9678#ifdef FEAT_CMDHIST
9679 int n;
9680 char_u buf[NUMBUFLEN];
9681
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009682 if (argvars[1].v_type == VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009683 /* only one argument: clear entire history */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009684 n = clr_history(get_histtype(get_tv_string(&argvars[0])));
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009685 else if (argvars[1].v_type == VAR_NUMBER)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009686 /* index given: remove that entry */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009687 n = del_history_idx(get_histtype(get_tv_string(&argvars[0])),
9688 (int)get_tv_number(&argvars[1]));
Bram Moolenaar071d4272004-06-13 20:20:40 +00009689 else
9690 /* string given: remove all matching entries */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009691 n = del_history_entry(get_histtype(get_tv_string(&argvars[0])),
9692 get_tv_string_buf(&argvars[1], buf));
9693 rettv->vval.v_number = n;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009694#else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009695 rettv->vval.v_number = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009696#endif
9697}
9698
9699/*
9700 * "histget()" function
9701 */
9702/*ARGSUSED*/
9703 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009704f_histget(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00009705 typval_T *argvars;
9706 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009707{
9708#ifdef FEAT_CMDHIST
9709 int type;
9710 int idx;
9711
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009712 type = get_histtype(get_tv_string(&argvars[0]));
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009713 if (argvars[1].v_type == VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009714 idx = get_history_idx(type);
9715 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009716 idx = (int)get_tv_number(&argvars[1]);
9717 rettv->vval.v_string = vim_strsave(get_history_entry(type, idx));
Bram Moolenaar071d4272004-06-13 20:20:40 +00009718#else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009719 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009720#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009721 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009722}
9723
9724/*
9725 * "histnr()" function
9726 */
9727/*ARGSUSED*/
9728 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009729f_histnr(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00009730 typval_T *argvars;
9731 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009732{
9733 int i;
9734
9735#ifdef FEAT_CMDHIST
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009736 i = get_histtype(get_tv_string(&argvars[0]));
Bram Moolenaar071d4272004-06-13 20:20:40 +00009737 if (i >= HIST_CMD && i < HIST_COUNT)
9738 i = get_history_idx(i);
9739 else
9740#endif
9741 i = -1;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009742 rettv->vval.v_number = i;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009743}
9744
9745/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00009746 * "highlightID(name)" function
9747 */
9748 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009749f_hlID(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00009750 typval_T *argvars;
9751 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009752{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009753 rettv->vval.v_number = syn_name2id(get_tv_string(&argvars[0]));
Bram Moolenaar071d4272004-06-13 20:20:40 +00009754}
9755
9756/*
Bram Moolenaar0d660222005-01-07 21:51:51 +00009757 * "highlight_exists()" function
9758 */
9759 static void
9760f_hlexists(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00009761 typval_T *argvars;
9762 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +00009763{
9764 rettv->vval.v_number = highlight_exists(get_tv_string(&argvars[0]));
9765}
9766
9767/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00009768 * "hostname()" function
9769 */
9770/*ARGSUSED*/
9771 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009772f_hostname(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00009773 typval_T *argvars;
9774 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009775{
9776 char_u hostname[256];
9777
9778 mch_get_host_name(hostname, 256);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009779 rettv->v_type = VAR_STRING;
9780 rettv->vval.v_string = vim_strsave(hostname);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009781}
9782
9783/*
9784 * iconv() function
9785 */
9786/*ARGSUSED*/
9787 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009788f_iconv(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00009789 typval_T *argvars;
9790 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009791{
9792#ifdef FEAT_MBYTE
9793 char_u buf1[NUMBUFLEN];
9794 char_u buf2[NUMBUFLEN];
9795 char_u *from, *to, *str;
9796 vimconv_T vimconv;
9797#endif
9798
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009799 rettv->v_type = VAR_STRING;
9800 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009801
9802#ifdef FEAT_MBYTE
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009803 str = get_tv_string(&argvars[0]);
9804 from = enc_canonize(enc_skip(get_tv_string_buf(&argvars[1], buf1)));
9805 to = enc_canonize(enc_skip(get_tv_string_buf(&argvars[2], buf2)));
Bram Moolenaar071d4272004-06-13 20:20:40 +00009806 vimconv.vc_type = CONV_NONE;
9807 convert_setup(&vimconv, from, to);
9808
9809 /* If the encodings are equal, no conversion needed. */
9810 if (vimconv.vc_type == CONV_NONE)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009811 rettv->vval.v_string = vim_strsave(str);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009812 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009813 rettv->vval.v_string = string_convert(&vimconv, str, NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009814
9815 convert_setup(&vimconv, NULL, NULL);
9816 vim_free(from);
9817 vim_free(to);
9818#endif
9819}
9820
9821/*
9822 * "indent()" function
9823 */
9824 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009825f_indent(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00009826 typval_T *argvars;
9827 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009828{
9829 linenr_T lnum;
9830
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009831 lnum = get_tv_lnum(argvars);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009832 if (lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009833 rettv->vval.v_number = get_indent_lnum(lnum);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009834 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009835 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009836}
9837
Bram Moolenaar8a283e52005-01-06 23:28:25 +00009838/*
9839 * "index()" function
9840 */
9841 static void
9842f_index(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00009843 typval_T *argvars;
9844 typval_T *rettv;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00009845{
Bram Moolenaar33570922005-01-25 22:26:29 +00009846 list_T *l;
9847 listitem_T *item;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00009848 long idx = 0;
9849 int ic = FALSE;
9850
9851 rettv->vval.v_number = -1;
9852 if (argvars[0].v_type != VAR_LIST)
9853 {
9854 EMSG(_(e_listreq));
9855 return;
9856 }
9857 l = argvars[0].vval.v_list;
9858 if (l != NULL)
9859 {
Bram Moolenaar758711c2005-02-02 23:11:38 +00009860 item = l->lv_first;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00009861 if (argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00009862 {
Bram Moolenaar758711c2005-02-02 23:11:38 +00009863 /* Start at specified item. Use the cached index that list_find()
9864 * sets, so that a negative number also works. */
9865 item = list_find(l, get_tv_number(&argvars[2]));
9866 idx = l->lv_idx;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00009867 if (argvars[3].v_type != VAR_UNKNOWN)
9868 ic = get_tv_number(&argvars[3]);
9869 }
Bram Moolenaar8a283e52005-01-06 23:28:25 +00009870
Bram Moolenaar758711c2005-02-02 23:11:38 +00009871 for ( ; item != NULL; item = item->li_next, ++idx)
9872 if (tv_equal(&item->li_tv, &argvars[1], ic))
Bram Moolenaar8a283e52005-01-06 23:28:25 +00009873 {
9874 rettv->vval.v_number = idx;
9875 break;
9876 }
9877 }
9878}
9879
Bram Moolenaar071d4272004-06-13 20:20:40 +00009880static int inputsecret_flag = 0;
9881
9882/*
9883 * "input()" function
9884 * Also handles inputsecret() when inputsecret is set.
9885 */
9886 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009887f_input(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00009888 typval_T *argvars;
9889 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009890{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009891 char_u *prompt = get_tv_string(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009892 char_u *p = NULL;
9893 int c;
9894 char_u buf[NUMBUFLEN];
9895 int cmd_silent_save = cmd_silent;
9896
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009897 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009898
9899#ifdef NO_CONSOLE_INPUT
9900 /* While starting up, there is no place to enter text. */
9901 if (no_console_input())
9902 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009903 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009904 return;
9905 }
9906#endif
9907
9908 cmd_silent = FALSE; /* Want to see the prompt. */
9909 if (prompt != NULL)
9910 {
9911 /* Only the part of the message after the last NL is considered as
9912 * prompt for the command line */
9913 p = vim_strrchr(prompt, '\n');
9914 if (p == NULL)
9915 p = prompt;
9916 else
9917 {
9918 ++p;
9919 c = *p;
9920 *p = NUL;
9921 msg_start();
9922 msg_clr_eos();
9923 msg_puts_attr(prompt, echo_attr);
9924 msg_didout = FALSE;
9925 msg_starthere();
9926 *p = c;
9927 }
9928 cmdline_row = msg_row;
9929 }
9930
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009931 if (argvars[1].v_type != VAR_UNKNOWN)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009932 stuffReadbuffSpec(get_tv_string_buf(&argvars[1], buf));
Bram Moolenaar071d4272004-06-13 20:20:40 +00009933
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009934 rettv->vval.v_string =
Bram Moolenaar071d4272004-06-13 20:20:40 +00009935 getcmdline_prompt(inputsecret_flag ? NUL : '@', p, echo_attr);
9936
9937 /* since the user typed this, no need to wait for return */
9938 need_wait_return = FALSE;
9939 msg_didout = FALSE;
9940 cmd_silent = cmd_silent_save;
9941}
9942
9943/*
9944 * "inputdialog()" function
9945 */
9946 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009947f_inputdialog(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00009948 typval_T *argvars;
9949 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009950{
9951#if defined(FEAT_GUI_TEXTDIALOG)
9952 /* Use a GUI dialog if the GUI is running and 'c' is not in 'guioptions' */
9953 if (gui.in_use && vim_strchr(p_go, GO_CONDIALOG) == NULL)
9954 {
9955 char_u *message;
9956 char_u buf[NUMBUFLEN];
9957
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009958 message = get_tv_string(&argvars[0]);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009959 if (argvars[1].v_type != VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009960 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009961 STRNCPY(IObuff, get_tv_string_buf(&argvars[1], buf), IOSIZE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009962 IObuff[IOSIZE - 1] = NUL;
9963 }
9964 else
9965 IObuff[0] = NUL;
9966 if (do_dialog(VIM_QUESTION, NULL, message, (char_u *)_("&OK\n&Cancel"),
9967 1, IObuff) == 1)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009968 rettv->vval.v_string = vim_strsave(IObuff);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009969 else
9970 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009971 if (argvars[1].v_type != VAR_UNKNOWN
9972 && argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009973 rettv->vval.v_string = vim_strsave(
9974 get_tv_string_buf(&argvars[2], buf));
Bram Moolenaar071d4272004-06-13 20:20:40 +00009975 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009976 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009977 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009978 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009979 }
9980 else
9981#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009982 f_input(argvars, rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009983}
9984
9985static garray_T ga_userinput = {0, 0, sizeof(tasave_T), 4, NULL};
9986
9987/*
9988 * "inputrestore()" function
9989 */
9990/*ARGSUSED*/
9991 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009992f_inputrestore(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00009993 typval_T *argvars;
9994 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009995{
9996 if (ga_userinput.ga_len > 0)
9997 {
9998 --ga_userinput.ga_len;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009999 restore_typeahead((tasave_T *)(ga_userinput.ga_data)
10000 + ga_userinput.ga_len);
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010001 rettv->vval.v_number = 0; /* OK */
Bram Moolenaar071d4272004-06-13 20:20:40 +000010002 }
10003 else if (p_verbose > 1)
10004 {
10005 msg((char_u *)_("called inputrestore() more often than inputsave()"));
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010006 rettv->vval.v_number = 1; /* Failed */
Bram Moolenaar071d4272004-06-13 20:20:40 +000010007 }
10008}
10009
10010/*
10011 * "inputsave()" function
10012 */
10013/*ARGSUSED*/
10014 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010015f_inputsave(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010016 typval_T *argvars;
10017 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010018{
10019 /* Add an entry to the stack of typehead storage. */
10020 if (ga_grow(&ga_userinput, 1) == OK)
10021 {
10022 save_typeahead((tasave_T *)(ga_userinput.ga_data)
10023 + ga_userinput.ga_len);
10024 ++ga_userinput.ga_len;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010025 rettv->vval.v_number = 0; /* OK */
Bram Moolenaar071d4272004-06-13 20:20:40 +000010026 }
10027 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010028 rettv->vval.v_number = 1; /* Failed */
Bram Moolenaar071d4272004-06-13 20:20:40 +000010029}
10030
10031/*
10032 * "inputsecret()" function
10033 */
10034 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010035f_inputsecret(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010036 typval_T *argvars;
10037 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010038{
10039 ++cmdline_star;
10040 ++inputsecret_flag;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010041 f_input(argvars, rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010042 --cmdline_star;
10043 --inputsecret_flag;
10044}
10045
10046/*
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010047 * "insert()" function
10048 */
10049 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010050f_insert(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010051 typval_T *argvars;
10052 typval_T *rettv;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010053{
10054 long before = 0;
Bram Moolenaar33570922005-01-25 22:26:29 +000010055 listitem_T *item;
10056 list_T *l;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010057
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000010058 rettv->vval.v_number = 0;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010059 if (argvars[0].v_type != VAR_LIST)
Bram Moolenaar0d660222005-01-07 21:51:51 +000010060 EMSG2(_(e_listarg), "insert()");
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000010061 else if ((l = argvars[0].vval.v_list) != NULL
10062 && !tv_check_lock(l->lv_lock, (char_u *)"insert()"))
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010063 {
10064 if (argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010065 before = get_tv_number(&argvars[2]);
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010066
Bram Moolenaar758711c2005-02-02 23:11:38 +000010067 if (before == l->lv_len)
10068 item = NULL;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010069 else
10070 {
Bram Moolenaar758711c2005-02-02 23:11:38 +000010071 item = list_find(l, before);
10072 if (item == NULL)
10073 {
10074 EMSGN(_(e_listidx), before);
10075 l = NULL;
10076 }
10077 }
10078 if (l != NULL)
10079 {
Bram Moolenaar8a283e52005-01-06 23:28:25 +000010080 list_insert_tv(l, &argvars[1], item);
10081 ++l->lv_refcount;
10082 copy_tv(&argvars[0], rettv);
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010083 }
10084 }
10085}
10086
10087/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000010088 * "isdirectory()" function
10089 */
10090 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010091f_isdirectory(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010092 typval_T *argvars;
10093 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010094{
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010095 rettv->vval.v_number = mch_isdir(get_tv_string(&argvars[0]));
Bram Moolenaar071d4272004-06-13 20:20:40 +000010096}
10097
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000010098/*
10099 * Return TRUE if typeval "tv" is locked: Either tha value is locked itself or
10100 * it refers to a List or Dictionary that is locked.
10101 */
10102 static int
10103tv_islocked(tv)
10104 typval_T *tv;
10105{
10106 return (tv->v_lock & VAR_LOCKED)
10107 || (tv->v_type == VAR_LIST
10108 && tv->vval.v_list != NULL
10109 && (tv->vval.v_list->lv_lock & VAR_LOCKED))
10110 || (tv->v_type == VAR_DICT
10111 && tv->vval.v_dict != NULL
10112 && (tv->vval.v_dict->dv_lock & VAR_LOCKED));
10113}
10114
10115/*
10116 * "islocked()" function
10117 */
10118 static void
10119f_islocked(argvars, rettv)
10120 typval_T *argvars;
10121 typval_T *rettv;
10122{
10123 lval_T lv;
10124 char_u *end;
10125 dictitem_T *di;
10126
10127 rettv->vval.v_number = -1;
10128 end = get_lval(get_tv_string(&argvars[0]), NULL, &lv, FALSE, FALSE, FALSE);
10129 if (end != NULL && lv.ll_name != NULL)
10130 {
10131 if (*end != NUL)
10132 EMSG(_(e_trailing));
10133 else
10134 {
10135 if (lv.ll_tv == NULL)
10136 {
10137 if (check_changedtick(lv.ll_name))
10138 rettv->vval.v_number = 1; /* always locked */
10139 else
10140 {
10141 di = find_var(lv.ll_name, NULL);
10142 if (di != NULL)
10143 {
10144 /* Consider a variable locked when:
10145 * 1. the variable itself is locked
10146 * 2. the value of the variable is locked.
10147 * 3. the List or Dict value is locked.
10148 */
10149 rettv->vval.v_number = ((di->di_flags & DI_FLAGS_LOCK)
10150 || tv_islocked(&di->di_tv));
10151 }
10152 }
10153 }
10154 else if (lv.ll_range)
10155 EMSG(_("E745: Range not allowed"));
10156 else if (lv.ll_newkey != NULL)
10157 EMSG2(_(e_dictkey), lv.ll_newkey);
10158 else if (lv.ll_list != NULL)
10159 /* List item. */
10160 rettv->vval.v_number = tv_islocked(&lv.ll_li->li_tv);
10161 else
10162 /* Dictionary item. */
10163 rettv->vval.v_number = tv_islocked(&lv.ll_di->di_tv);
10164 }
10165 }
10166
10167 clear_lval(&lv);
10168}
10169
Bram Moolenaar33570922005-01-25 22:26:29 +000010170static void dict_list __ARGS((typval_T *argvars, typval_T *rettv, int what));
Bram Moolenaar8c711452005-01-14 21:53:12 +000010171
10172/*
10173 * Turn a dict into a list:
10174 * "what" == 0: list of keys
10175 * "what" == 1: list of values
10176 * "what" == 2: list of items
10177 */
10178 static void
10179dict_list(argvars, rettv, what)
Bram Moolenaar33570922005-01-25 22:26:29 +000010180 typval_T *argvars;
10181 typval_T *rettv;
Bram Moolenaar8c711452005-01-14 21:53:12 +000010182 int what;
10183{
Bram Moolenaar33570922005-01-25 22:26:29 +000010184 list_T *l;
10185 list_T *l2;
10186 dictitem_T *di;
10187 hashitem_T *hi;
10188 listitem_T *li;
10189 listitem_T *li2;
10190 dict_T *d;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000010191 int todo;
Bram Moolenaar8c711452005-01-14 21:53:12 +000010192
10193 rettv->vval.v_number = 0;
10194 if (argvars[0].v_type != VAR_DICT)
10195 {
10196 EMSG(_(e_dictreq));
10197 return;
10198 }
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000010199 if ((d = argvars[0].vval.v_dict) == NULL)
Bram Moolenaar8c711452005-01-14 21:53:12 +000010200 return;
10201
10202 l = list_alloc();
10203 if (l == NULL)
10204 return;
10205 rettv->v_type = VAR_LIST;
10206 rettv->vval.v_list = l;
10207 ++l->lv_refcount;
10208
Bram Moolenaar33570922005-01-25 22:26:29 +000010209 todo = d->dv_hashtab.ht_used;
10210 for (hi = d->dv_hashtab.ht_array; todo > 0; ++hi)
Bram Moolenaar8c711452005-01-14 21:53:12 +000010211 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000010212 if (!HASHITEM_EMPTY(hi))
Bram Moolenaar8c711452005-01-14 21:53:12 +000010213 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000010214 --todo;
10215 di = HI2DI(hi);
Bram Moolenaar8c711452005-01-14 21:53:12 +000010216
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000010217 li = listitem_alloc();
10218 if (li == NULL)
Bram Moolenaar8c711452005-01-14 21:53:12 +000010219 break;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000010220 list_append(l, li);
Bram Moolenaar8c711452005-01-14 21:53:12 +000010221
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000010222 if (what == 0)
10223 {
10224 /* keys() */
10225 li->li_tv.v_type = VAR_STRING;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000010226 li->li_tv.v_lock = 0;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000010227 li->li_tv.vval.v_string = vim_strsave(di->di_key);
10228 }
10229 else if (what == 1)
10230 {
10231 /* values() */
10232 copy_tv(&di->di_tv, &li->li_tv);
10233 }
10234 else
10235 {
10236 /* items() */
10237 l2 = list_alloc();
10238 li->li_tv.v_type = VAR_LIST;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000010239 li->li_tv.v_lock = 0;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000010240 li->li_tv.vval.v_list = l2;
10241 if (l2 == NULL)
10242 break;
10243 ++l2->lv_refcount;
10244
10245 li2 = listitem_alloc();
10246 if (li2 == NULL)
10247 break;
10248 list_append(l2, li2);
10249 li2->li_tv.v_type = VAR_STRING;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000010250 li2->li_tv.v_lock = 0;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000010251 li2->li_tv.vval.v_string = vim_strsave(di->di_key);
10252
10253 li2 = listitem_alloc();
10254 if (li2 == NULL)
10255 break;
10256 list_append(l2, li2);
10257 copy_tv(&di->di_tv, &li2->li_tv);
10258 }
Bram Moolenaar8c711452005-01-14 21:53:12 +000010259 }
10260 }
10261}
10262
10263/*
10264 * "items(dict)" function
10265 */
10266 static void
10267f_items(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010268 typval_T *argvars;
10269 typval_T *rettv;
Bram Moolenaar8c711452005-01-14 21:53:12 +000010270{
10271 dict_list(argvars, rettv, 2);
10272}
10273
Bram Moolenaar071d4272004-06-13 20:20:40 +000010274/*
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000010275 * "join()" function
10276 */
10277 static void
10278f_join(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010279 typval_T *argvars;
10280 typval_T *rettv;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000010281{
10282 garray_T ga;
10283 char_u *sep;
10284
10285 rettv->vval.v_number = 0;
10286 if (argvars[0].v_type != VAR_LIST)
10287 {
10288 EMSG(_(e_listreq));
10289 return;
10290 }
10291 if (argvars[0].vval.v_list == NULL)
10292 return;
10293 if (argvars[1].v_type == VAR_UNKNOWN)
10294 sep = (char_u *)" ";
10295 else
10296 sep = get_tv_string(&argvars[1]);
10297
10298 ga_init2(&ga, (int)sizeof(char), 80);
10299 list_join(&ga, argvars[0].vval.v_list, sep, TRUE);
10300 ga_append(&ga, NUL);
10301
10302 rettv->v_type = VAR_STRING;
10303 rettv->vval.v_string = (char_u *)ga.ga_data;
10304}
10305
10306/*
Bram Moolenaar8c711452005-01-14 21:53:12 +000010307 * "keys()" function
10308 */
10309 static void
10310f_keys(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010311 typval_T *argvars;
10312 typval_T *rettv;
Bram Moolenaar8c711452005-01-14 21:53:12 +000010313{
10314 dict_list(argvars, rettv, 0);
10315}
10316
10317/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000010318 * "last_buffer_nr()" function.
10319 */
10320/*ARGSUSED*/
10321 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010322f_last_buffer_nr(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010323 typval_T *argvars;
10324 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010325{
10326 int n = 0;
10327 buf_T *buf;
10328
10329 for (buf = firstbuf; buf != NULL; buf = buf->b_next)
10330 if (n < buf->b_fnum)
10331 n = buf->b_fnum;
10332
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010333 rettv->vval.v_number = n;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010334}
10335
10336/*
10337 * "len()" function
10338 */
10339 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010340f_len(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010341 typval_T *argvars;
10342 typval_T *rettv;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010343{
10344 switch (argvars[0].v_type)
10345 {
10346 case VAR_STRING:
10347 case VAR_NUMBER:
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010348 rettv->vval.v_number = (varnumber_T)STRLEN(
10349 get_tv_string(&argvars[0]));
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010350 break;
10351 case VAR_LIST:
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010352 rettv->vval.v_number = list_len(argvars[0].vval.v_list);
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010353 break;
Bram Moolenaare9a41262005-01-15 22:18:47 +000010354 case VAR_DICT:
10355 rettv->vval.v_number = dict_len(argvars[0].vval.v_dict);
10356 break;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010357 default:
Bram Moolenaare49b69a2005-01-08 16:11:57 +000010358 EMSG(_("E701: Invalid type for len()"));
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010359 break;
10360 }
10361}
10362
Bram Moolenaar33570922005-01-25 22:26:29 +000010363static void libcall_common __ARGS((typval_T *argvars, typval_T *rettv, int type));
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010364
10365 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010366libcall_common(argvars, rettv, type)
Bram Moolenaar33570922005-01-25 22:26:29 +000010367 typval_T *argvars;
10368 typval_T *rettv;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010369 int type;
10370{
10371#ifdef FEAT_LIBCALL
10372 char_u *string_in;
10373 char_u **string_result;
10374 int nr_result;
10375#endif
10376
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010377 rettv->v_type = type;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010378 if (type == VAR_NUMBER)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010379 rettv->vval.v_number = 0;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010380 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010381 rettv->vval.v_string = NULL;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010382
10383 if (check_restricted() || check_secure())
10384 return;
10385
10386#ifdef FEAT_LIBCALL
10387 /* The first two args must be strings, otherwise its meaningless */
10388 if (argvars[0].v_type == VAR_STRING && argvars[1].v_type == VAR_STRING)
10389 {
Bram Moolenaar758711c2005-02-02 23:11:38 +000010390 string_in = NULL;
10391 if (argvars[2].v_type == VAR_STRING)
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010392 string_in = argvars[2].vval.v_string;
10393 if (type == VAR_NUMBER)
10394 string_result = NULL;
10395 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010396 string_result = &rettv->vval.v_string;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010397 if (mch_libcall(argvars[0].vval.v_string,
10398 argvars[1].vval.v_string,
10399 string_in,
10400 argvars[2].vval.v_number,
10401 string_result,
10402 &nr_result) == OK
10403 && type == VAR_NUMBER)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010404 rettv->vval.v_number = nr_result;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010405 }
10406#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000010407}
10408
10409/*
Bram Moolenaar0d660222005-01-07 21:51:51 +000010410 * "libcall()" function
10411 */
10412 static void
10413f_libcall(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010414 typval_T *argvars;
10415 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000010416{
10417 libcall_common(argvars, rettv, VAR_STRING);
10418}
10419
10420/*
10421 * "libcallnr()" function
10422 */
10423 static void
10424f_libcallnr(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010425 typval_T *argvars;
10426 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000010427{
10428 libcall_common(argvars, rettv, VAR_NUMBER);
10429}
10430
10431/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000010432 * "line(string)" function
10433 */
10434 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010435f_line(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010436 typval_T *argvars;
10437 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010438{
10439 linenr_T lnum = 0;
10440 pos_T *fp;
10441
10442 fp = var2fpos(&argvars[0], TRUE);
10443 if (fp != NULL)
10444 lnum = fp->lnum;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010445 rettv->vval.v_number = lnum;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010446}
10447
10448/*
10449 * "line2byte(lnum)" function
10450 */
10451/*ARGSUSED*/
10452 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010453f_line2byte(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010454 typval_T *argvars;
10455 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010456{
10457#ifndef FEAT_BYTEOFF
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010458 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010459#else
10460 linenr_T lnum;
10461
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010462 lnum = get_tv_lnum(argvars);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010463 if (lnum < 1 || lnum > curbuf->b_ml.ml_line_count + 1)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010464 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010465 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010466 rettv->vval.v_number = ml_find_line_or_offset(curbuf, lnum, NULL);
10467 if (rettv->vval.v_number >= 0)
10468 ++rettv->vval.v_number;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010469#endif
10470}
10471
10472/*
10473 * "lispindent(lnum)" function
10474 */
10475 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010476f_lispindent(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010477 typval_T *argvars;
10478 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010479{
10480#ifdef FEAT_LISP
10481 pos_T pos;
10482 linenr_T lnum;
10483
10484 pos = curwin->w_cursor;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010485 lnum = get_tv_lnum(argvars);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010486 if (lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count)
10487 {
10488 curwin->w_cursor.lnum = lnum;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010489 rettv->vval.v_number = get_lisp_indent();
Bram Moolenaar071d4272004-06-13 20:20:40 +000010490 curwin->w_cursor = pos;
10491 }
10492 else
10493#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010494 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010495}
10496
10497/*
10498 * "localtime()" function
10499 */
10500/*ARGSUSED*/
10501 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010502f_localtime(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010503 typval_T *argvars;
10504 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010505{
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010506 rettv->vval.v_number = (varnumber_T)time(NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010507}
10508
Bram Moolenaar33570922005-01-25 22:26:29 +000010509static void get_maparg __ARGS((typval_T *argvars, typval_T *rettv, int exact));
Bram Moolenaar071d4272004-06-13 20:20:40 +000010510
10511 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010512get_maparg(argvars, rettv, exact)
Bram Moolenaar33570922005-01-25 22:26:29 +000010513 typval_T *argvars;
10514 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010515 int exact;
10516{
10517 char_u *keys;
10518 char_u *which;
10519 char_u buf[NUMBUFLEN];
10520 char_u *keys_buf = NULL;
10521 char_u *rhs;
10522 int mode;
10523 garray_T ga;
10524
10525 /* return empty string for failure */
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010526 rettv->v_type = VAR_STRING;
10527 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010528
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010529 keys = get_tv_string(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010530 if (*keys == NUL)
10531 return;
10532
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010533 if (argvars[1].v_type != VAR_UNKNOWN)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010534 which = get_tv_string_buf(&argvars[1], buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010535 else
10536 which = (char_u *)"";
10537 mode = get_map_mode(&which, 0);
10538
10539 keys = replace_termcodes(keys, &keys_buf, TRUE, TRUE);
10540 rhs = check_map(keys, mode, exact);
10541 vim_free(keys_buf);
10542 if (rhs != NULL)
10543 {
10544 ga_init(&ga);
10545 ga.ga_itemsize = 1;
10546 ga.ga_growsize = 40;
10547
10548 while (*rhs != NUL)
10549 ga_concat(&ga, str2special(&rhs, FALSE));
10550
10551 ga_append(&ga, NUL);
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010552 rettv->vval.v_string = (char_u *)ga.ga_data;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010553 }
10554}
10555
10556/*
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000010557 * "map()" function
10558 */
10559 static void
10560f_map(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010561 typval_T *argvars;
10562 typval_T *rettv;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000010563{
10564 filter_map(argvars, rettv, TRUE);
10565}
10566
10567/*
Bram Moolenaar0d660222005-01-07 21:51:51 +000010568 * "maparg()" function
Bram Moolenaar071d4272004-06-13 20:20:40 +000010569 */
10570 static void
Bram Moolenaar0d660222005-01-07 21:51:51 +000010571f_maparg(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010572 typval_T *argvars;
10573 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010574{
Bram Moolenaar0d660222005-01-07 21:51:51 +000010575 get_maparg(argvars, rettv, TRUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010576}
10577
10578/*
Bram Moolenaar0d660222005-01-07 21:51:51 +000010579 * "mapcheck()" function
Bram Moolenaar071d4272004-06-13 20:20:40 +000010580 */
10581 static void
Bram Moolenaar0d660222005-01-07 21:51:51 +000010582f_mapcheck(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010583 typval_T *argvars;
10584 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010585{
Bram Moolenaar0d660222005-01-07 21:51:51 +000010586 get_maparg(argvars, rettv, FALSE);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010587}
10588
Bram Moolenaar33570922005-01-25 22:26:29 +000010589static void find_some_match __ARGS((typval_T *argvars, typval_T *rettv, int start));
Bram Moolenaar071d4272004-06-13 20:20:40 +000010590
10591 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010592find_some_match(argvars, rettv, type)
Bram Moolenaar33570922005-01-25 22:26:29 +000010593 typval_T *argvars;
10594 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010595 int type;
10596{
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000010597 char_u *str = NULL;
10598 char_u *expr = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010599 char_u *pat;
10600 regmatch_T regmatch;
10601 char_u patbuf[NUMBUFLEN];
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000010602 char_u strbuf[NUMBUFLEN];
Bram Moolenaar071d4272004-06-13 20:20:40 +000010603 char_u *save_cpo;
10604 long start = 0;
Bram Moolenaar89cb5e02004-07-19 20:55:54 +000010605 long nth = 1;
Bram Moolenaar81bf7082005-02-12 14:31:42 +000010606 int match = 0;
Bram Moolenaar33570922005-01-25 22:26:29 +000010607 list_T *l = NULL;
10608 listitem_T *li = NULL;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000010609 long idx = 0;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000010610 char_u *tofree = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010611
10612 /* Make 'cpoptions' empty, the 'l' flag should not be used here. */
10613 save_cpo = p_cpo;
10614 p_cpo = (char_u *)"";
10615
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000010616 rettv->vval.v_number = -1;
10617 if (type == 3)
10618 {
10619 /* return empty list when there are no matches */
10620 if ((rettv->vval.v_list = list_alloc()) == NULL)
10621 goto theend;
10622 rettv->v_type = VAR_LIST;
10623 ++rettv->vval.v_list->lv_refcount;
10624 }
10625 else if (type == 2)
Bram Moolenaar071d4272004-06-13 20:20:40 +000010626 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010627 rettv->v_type = VAR_STRING;
10628 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010629 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000010630
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000010631 if (argvars[0].v_type == VAR_LIST)
10632 {
10633 if ((l = argvars[0].vval.v_list) == NULL)
10634 goto theend;
10635 li = l->lv_first;
10636 }
10637 else
10638 expr = str = get_tv_string(&argvars[0]);
10639
10640 pat = get_tv_string_buf(&argvars[1], patbuf);
10641
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010642 if (argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +000010643 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010644 start = get_tv_number(&argvars[2]);
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000010645 if (l != NULL)
10646 {
10647 li = list_find(l, start);
10648 if (li == NULL)
10649 goto theend;
Bram Moolenaar758711c2005-02-02 23:11:38 +000010650 idx = l->lv_idx; /* use the cached index */
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000010651 }
10652 else
10653 {
10654 if (start < 0)
10655 start = 0;
10656 if (start > (long)STRLEN(str))
10657 goto theend;
10658 str += start;
10659 }
Bram Moolenaar89cb5e02004-07-19 20:55:54 +000010660
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010661 if (argvars[3].v_type != VAR_UNKNOWN)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010662 nth = get_tv_number(&argvars[3]);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010663 }
10664
10665 regmatch.regprog = vim_regcomp(pat, RE_MAGIC + RE_STRING);
10666 if (regmatch.regprog != NULL)
10667 {
10668 regmatch.rm_ic = p_ic;
Bram Moolenaar89cb5e02004-07-19 20:55:54 +000010669
10670 while (1)
10671 {
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000010672 if (l != NULL)
10673 {
10674 if (li == NULL)
10675 {
10676 match = FALSE;
10677 break;
10678 }
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000010679 vim_free(tofree);
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000010680 str = echo_string(&li->li_tv, &tofree, strbuf);
Bram Moolenaar81bf7082005-02-12 14:31:42 +000010681 if (str == NULL)
10682 break;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000010683 }
10684
Bram Moolenaar89cb5e02004-07-19 20:55:54 +000010685 match = vim_regexec_nl(&regmatch, str, (colnr_T)0);
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000010686
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000010687 if (match && --nth <= 0)
Bram Moolenaar89cb5e02004-07-19 20:55:54 +000010688 break;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000010689 if (l == NULL && !match)
10690 break;
10691
Bram Moolenaar89cb5e02004-07-19 20:55:54 +000010692 /* Advance to just after the match. */
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000010693 if (l != NULL)
10694 {
10695 li = li->li_next;
10696 ++idx;
10697 }
10698 else
10699 {
Bram Moolenaar89cb5e02004-07-19 20:55:54 +000010700#ifdef FEAT_MBYTE
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000010701 str = regmatch.startp[0] + mb_ptr2len_check(regmatch.startp[0]);
Bram Moolenaar89cb5e02004-07-19 20:55:54 +000010702#else
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000010703 str = regmatch.startp[0] + 1;
Bram Moolenaar89cb5e02004-07-19 20:55:54 +000010704#endif
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000010705 }
Bram Moolenaar89cb5e02004-07-19 20:55:54 +000010706 }
10707
10708 if (match)
Bram Moolenaar071d4272004-06-13 20:20:40 +000010709 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000010710 if (type == 3)
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000010711 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000010712 int i;
10713
10714 /* return list with matched string and submatches */
10715 for (i = 0; i < NSUBEXP; ++i)
10716 {
10717 if (regmatch.endp[i] == NULL)
10718 break;
10719 li = listitem_alloc();
10720 if (li == NULL)
10721 break;
10722 li->li_tv.v_type = VAR_STRING;
10723 li->li_tv.v_lock = 0;
10724 li->li_tv.vval.v_string = vim_strnsave(regmatch.startp[i],
10725 (int)(regmatch.endp[i] - regmatch.startp[i]));
10726 list_append(rettv->vval.v_list, li);
10727 }
10728 }
10729 else if (type == 2)
10730 {
10731 /* return matched string */
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000010732 if (l != NULL)
10733 copy_tv(&li->li_tv, rettv);
10734 else
10735 rettv->vval.v_string = vim_strnsave(regmatch.startp[0],
Bram Moolenaar071d4272004-06-13 20:20:40 +000010736 (int)(regmatch.endp[0] - regmatch.startp[0]));
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000010737 }
10738 else if (l != NULL)
10739 rettv->vval.v_number = idx;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010740 else
10741 {
10742 if (type != 0)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010743 rettv->vval.v_number =
Bram Moolenaar071d4272004-06-13 20:20:40 +000010744 (varnumber_T)(regmatch.startp[0] - str);
10745 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010746 rettv->vval.v_number =
Bram Moolenaar071d4272004-06-13 20:20:40 +000010747 (varnumber_T)(regmatch.endp[0] - str);
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010748 rettv->vval.v_number += str - expr;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010749 }
10750 }
10751 vim_free(regmatch.regprog);
10752 }
10753
10754theend:
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000010755 vim_free(tofree);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010756 p_cpo = save_cpo;
10757}
10758
10759/*
Bram Moolenaar0d660222005-01-07 21:51:51 +000010760 * "match()" function
10761 */
10762 static void
10763f_match(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010764 typval_T *argvars;
10765 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000010766{
10767 find_some_match(argvars, rettv, 1);
10768}
10769
10770/*
10771 * "matchend()" function
10772 */
10773 static void
10774f_matchend(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010775 typval_T *argvars;
10776 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000010777{
10778 find_some_match(argvars, rettv, 0);
10779}
10780
10781/*
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000010782 * "matchlist()" function
10783 */
10784 static void
10785f_matchlist(argvars, rettv)
10786 typval_T *argvars;
10787 typval_T *rettv;
10788{
10789 find_some_match(argvars, rettv, 3);
10790}
10791
10792/*
Bram Moolenaar0d660222005-01-07 21:51:51 +000010793 * "matchstr()" function
10794 */
10795 static void
10796f_matchstr(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010797 typval_T *argvars;
10798 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000010799{
10800 find_some_match(argvars, rettv, 2);
10801}
10802
Bram Moolenaar33570922005-01-25 22:26:29 +000010803static void max_min __ARGS((typval_T *argvars, typval_T *rettv, int domax));
Bram Moolenaar6cc16192005-01-08 21:49:45 +000010804
10805 static void
10806max_min(argvars, rettv, domax)
Bram Moolenaar33570922005-01-25 22:26:29 +000010807 typval_T *argvars;
10808 typval_T *rettv;
Bram Moolenaar6cc16192005-01-08 21:49:45 +000010809 int domax;
10810{
Bram Moolenaar6cc16192005-01-08 21:49:45 +000010811 long n = 0;
10812 long i;
10813
10814 if (argvars[0].v_type == VAR_LIST)
10815 {
Bram Moolenaar33570922005-01-25 22:26:29 +000010816 list_T *l;
10817 listitem_T *li;
Bram Moolenaare9a41262005-01-15 22:18:47 +000010818
Bram Moolenaar6cc16192005-01-08 21:49:45 +000010819 l = argvars[0].vval.v_list;
10820 if (l != NULL)
10821 {
10822 li = l->lv_first;
10823 if (li != NULL)
10824 {
10825 n = get_tv_number(&li->li_tv);
10826 while (1)
10827 {
10828 li = li->li_next;
10829 if (li == NULL)
10830 break;
10831 i = get_tv_number(&li->li_tv);
10832 if (domax ? i > n : i < n)
10833 n = i;
10834 }
10835 }
10836 }
10837 }
Bram Moolenaare9a41262005-01-15 22:18:47 +000010838 else if (argvars[0].v_type == VAR_DICT)
10839 {
Bram Moolenaar33570922005-01-25 22:26:29 +000010840 dict_T *d;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000010841 int first = TRUE;
Bram Moolenaar33570922005-01-25 22:26:29 +000010842 hashitem_T *hi;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000010843 int todo;
Bram Moolenaare9a41262005-01-15 22:18:47 +000010844
10845 d = argvars[0].vval.v_dict;
10846 if (d != NULL)
10847 {
Bram Moolenaar33570922005-01-25 22:26:29 +000010848 todo = d->dv_hashtab.ht_used;
10849 for (hi = d->dv_hashtab.ht_array; todo > 0; ++hi)
Bram Moolenaare9a41262005-01-15 22:18:47 +000010850 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000010851 if (!HASHITEM_EMPTY(hi))
Bram Moolenaare9a41262005-01-15 22:18:47 +000010852 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000010853 --todo;
10854 i = get_tv_number(&HI2DI(hi)->di_tv);
10855 if (first)
10856 {
10857 n = i;
10858 first = FALSE;
10859 }
10860 else if (domax ? i > n : i < n)
Bram Moolenaare9a41262005-01-15 22:18:47 +000010861 n = i;
10862 }
10863 }
10864 }
10865 }
Bram Moolenaar6cc16192005-01-08 21:49:45 +000010866 else
Bram Moolenaar758711c2005-02-02 23:11:38 +000010867 EMSG(_(e_listdictarg));
Bram Moolenaar6cc16192005-01-08 21:49:45 +000010868 rettv->vval.v_number = n;
10869}
10870
10871/*
10872 * "max()" function
10873 */
10874 static void
10875f_max(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010876 typval_T *argvars;
10877 typval_T *rettv;
Bram Moolenaar6cc16192005-01-08 21:49:45 +000010878{
10879 max_min(argvars, rettv, TRUE);
10880}
10881
10882/*
10883 * "min()" function
10884 */
10885 static void
10886f_min(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010887 typval_T *argvars;
10888 typval_T *rettv;
Bram Moolenaar6cc16192005-01-08 21:49:45 +000010889{
10890 max_min(argvars, rettv, FALSE);
10891}
10892
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000010893static int mkdir_recurse __ARGS((char_u *dir, int prot));
10894
10895/*
10896 * Create the directory in which "dir" is located, and higher levels when
10897 * needed.
10898 */
10899 static int
10900mkdir_recurse(dir, prot)
10901 char_u *dir;
10902 int prot;
10903{
10904 char_u *p;
10905 char_u *updir;
10906 int r = FAIL;
10907
10908 /* Get end of directory name in "dir".
10909 * We're done when it's "/" or "c:/". */
10910 p = gettail_sep(dir);
10911 if (p <= get_past_head(dir))
10912 return OK;
10913
10914 /* If the directory exists we're done. Otherwise: create it.*/
10915 updir = vim_strnsave(dir, (int)(p - dir));
10916 if (updir == NULL)
10917 return FAIL;
10918 if (mch_isdir(updir))
10919 r = OK;
10920 else if (mkdir_recurse(updir, prot) == OK)
10921 r = vim_mkdir_emsg(updir, prot);
10922 vim_free(updir);
10923 return r;
10924}
10925
10926#ifdef vim_mkdir
10927/*
10928 * "mkdir()" function
10929 */
10930 static void
10931f_mkdir(argvars, rettv)
10932 typval_T *argvars;
10933 typval_T *rettv;
10934{
10935 char_u *dir;
10936 char_u buf[NUMBUFLEN];
10937 int prot = 0755;
10938
10939 rettv->vval.v_number = FAIL;
10940 if (check_restricted() || check_secure())
10941 return;
10942
10943 dir = get_tv_string_buf(&argvars[0], buf);
10944 if (argvars[1].v_type != VAR_UNKNOWN)
10945 {
10946 if (argvars[2].v_type != VAR_UNKNOWN)
10947 prot = get_tv_number(&argvars[2]);
10948 if (STRCMP(get_tv_string(&argvars[1]), "p") == 0)
10949 mkdir_recurse(dir, prot);
10950 }
10951 rettv->vval.v_number = vim_mkdir_emsg(dir, prot);
10952}
10953#endif
10954
Bram Moolenaar0d660222005-01-07 21:51:51 +000010955/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000010956 * "mode()" function
10957 */
10958/*ARGSUSED*/
10959 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010960f_mode(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010961 typval_T *argvars;
10962 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010963{
10964 char_u buf[2];
10965
10966#ifdef FEAT_VISUAL
10967 if (VIsual_active)
10968 {
10969 if (VIsual_select)
10970 buf[0] = VIsual_mode + 's' - 'v';
10971 else
10972 buf[0] = VIsual_mode;
10973 }
10974 else
10975#endif
10976 if (State == HITRETURN || State == ASKMORE || State == SETWSIZE)
10977 buf[0] = 'r';
10978 else if (State & INSERT)
10979 {
10980 if (State & REPLACE_FLAG)
10981 buf[0] = 'R';
10982 else
10983 buf[0] = 'i';
10984 }
10985 else if (State & CMDLINE)
10986 buf[0] = 'c';
10987 else
10988 buf[0] = 'n';
10989
10990 buf[1] = NUL;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010991 rettv->vval.v_string = vim_strsave(buf);
10992 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010993}
10994
10995/*
Bram Moolenaar0d660222005-01-07 21:51:51 +000010996 * "nextnonblank()" function
10997 */
10998 static void
10999f_nextnonblank(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000011000 typval_T *argvars;
11001 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000011002{
11003 linenr_T lnum;
11004
11005 for (lnum = get_tv_lnum(argvars); ; ++lnum)
11006 {
11007 if (lnum > curbuf->b_ml.ml_line_count)
11008 {
11009 lnum = 0;
11010 break;
11011 }
11012 if (*skipwhite(ml_get(lnum)) != NUL)
11013 break;
11014 }
11015 rettv->vval.v_number = lnum;
11016}
11017
11018/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000011019 * "nr2char()" function
11020 */
11021 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011022f_nr2char(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000011023 typval_T *argvars;
11024 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011025{
11026 char_u buf[NUMBUFLEN];
11027
11028#ifdef FEAT_MBYTE
11029 if (has_mbyte)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011030 buf[(*mb_char2bytes)((int)get_tv_number(&argvars[0]), buf)] = NUL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011031 else
11032#endif
11033 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011034 buf[0] = (char_u)get_tv_number(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +000011035 buf[1] = NUL;
11036 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011037 rettv->v_type = VAR_STRING;
11038 rettv->vval.v_string = vim_strsave(buf);
Bram Moolenaar49cd9572005-01-03 21:06:01 +000011039}
11040
11041/*
Bram Moolenaar0d660222005-01-07 21:51:51 +000011042 * "prevnonblank()" function
11043 */
11044 static void
11045f_prevnonblank(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000011046 typval_T *argvars;
11047 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000011048{
11049 linenr_T lnum;
11050
11051 lnum = get_tv_lnum(argvars);
11052 if (lnum < 1 || lnum > curbuf->b_ml.ml_line_count)
11053 lnum = 0;
11054 else
11055 while (lnum >= 1 && *skipwhite(ml_get(lnum)) == NUL)
11056 --lnum;
11057 rettv->vval.v_number = lnum;
11058}
11059
Bram Moolenaar8c711452005-01-14 21:53:12 +000011060/*
11061 * "range()" function
11062 */
11063 static void
11064f_range(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000011065 typval_T *argvars;
11066 typval_T *rettv;
Bram Moolenaar8c711452005-01-14 21:53:12 +000011067{
11068 long start;
11069 long end;
11070 long stride = 1;
11071 long i;
Bram Moolenaar33570922005-01-25 22:26:29 +000011072 list_T *l;
11073 listitem_T *li;
Bram Moolenaar8c711452005-01-14 21:53:12 +000011074
11075 start = get_tv_number(&argvars[0]);
11076 if (argvars[1].v_type == VAR_UNKNOWN)
11077 {
11078 end = start - 1;
11079 start = 0;
11080 }
11081 else
11082 {
11083 end = get_tv_number(&argvars[1]);
11084 if (argvars[2].v_type != VAR_UNKNOWN)
11085 stride = get_tv_number(&argvars[2]);
11086 }
11087
11088 rettv->vval.v_number = 0;
11089 if (stride == 0)
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000011090 EMSG(_("E726: Stride is zero"));
Bram Moolenaar8c711452005-01-14 21:53:12 +000011091 else if (stride > 0 ? end < start : end > start)
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000011092 EMSG(_("E727: Start past end"));
Bram Moolenaar8c711452005-01-14 21:53:12 +000011093 else
11094 {
11095 l = list_alloc();
11096 if (l != NULL)
11097 {
11098 rettv->v_type = VAR_LIST;
11099 rettv->vval.v_list = l;
11100 ++l->lv_refcount;
11101
11102 for (i = start; stride > 0 ? i <= end : i >= end; i += stride)
11103 {
11104 li = listitem_alloc();
11105 if (li == NULL)
11106 break;
11107 li->li_tv.v_type = VAR_NUMBER;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000011108 li->li_tv.v_lock = 0;
Bram Moolenaar8c711452005-01-14 21:53:12 +000011109 li->li_tv.vval.v_number = i;
11110 list_append(l, li);
11111 }
11112 }
11113 }
11114}
11115
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000011116/*
11117 * "readfile()" function
11118 */
11119 static void
11120f_readfile(argvars, rettv)
11121 typval_T *argvars;
11122 typval_T *rettv;
11123{
11124 int binary = FALSE;
11125 char_u *fname;
11126 FILE *fd;
11127 list_T *l;
11128 listitem_T *li;
11129#define FREAD_SIZE 200 /* optimized for text lines */
11130 char_u buf[FREAD_SIZE];
11131 int readlen; /* size of last fread() */
11132 int buflen; /* nr of valid chars in buf[] */
11133 int filtd; /* how much in buf[] was NUL -> '\n' filtered */
11134 int tolist; /* first byte in buf[] still to be put in list */
11135 int chop; /* how many CR to chop off */
11136 char_u *prev = NULL; /* previously read bytes, if any */
11137 int prevlen = 0; /* length of "prev" if not NULL */
11138 char_u *s;
11139 int len;
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000011140 long maxline = MAXLNUM;
11141 long cnt = 0;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000011142
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000011143 if (argvars[1].v_type != VAR_UNKNOWN)
11144 {
11145 if (STRCMP(get_tv_string(&argvars[1]), "b") == 0)
11146 binary = TRUE;
11147 if (argvars[2].v_type != VAR_UNKNOWN)
11148 maxline = get_tv_number(&argvars[2]);
11149 }
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000011150
11151 l = list_alloc();
11152 if (l == NULL)
11153 return;
11154 rettv->v_type = VAR_LIST;
11155 rettv->vval.v_list = l;
11156 l->lv_refcount = 1;
11157
11158 /* Always open the file in binary mode, library functions have a mind of
11159 * their own about CR-LF conversion. */
11160 fname = get_tv_string(&argvars[0]);
11161 if (*fname == NUL || (fd = mch_fopen((char *)fname, READBIN)) == NULL)
11162 {
11163 EMSG2(_(e_notopen), *fname == NUL ? (char_u *)_("<empty>") : fname);
11164 return;
11165 }
11166
11167 filtd = 0;
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000011168 while (cnt < maxline)
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000011169 {
11170 readlen = fread(buf + filtd, 1, FREAD_SIZE - filtd, fd);
11171 buflen = filtd + readlen;
11172 tolist = 0;
11173 for ( ; filtd < buflen || readlen <= 0; ++filtd)
11174 {
11175 if (buf[filtd] == '\n' || readlen <= 0)
11176 {
11177 /* Only when in binary mode add an empty list item when the
11178 * last line ends in a '\n'. */
11179 if (!binary && readlen == 0 && filtd == 0)
11180 break;
11181
11182 /* Found end-of-line or end-of-file: add a text line to the
11183 * list. */
11184 chop = 0;
11185 if (!binary)
11186 while (filtd - chop - 1 >= tolist
11187 && buf[filtd - chop - 1] == '\r')
11188 ++chop;
11189 len = filtd - tolist - chop;
11190 if (prev == NULL)
11191 s = vim_strnsave(buf + tolist, len);
11192 else
11193 {
11194 s = alloc((unsigned)(prevlen + len + 1));
11195 if (s != NULL)
11196 {
11197 mch_memmove(s, prev, prevlen);
11198 vim_free(prev);
11199 prev = NULL;
11200 mch_memmove(s + prevlen, buf + tolist, len);
11201 s[prevlen + len] = NUL;
11202 }
11203 }
11204 tolist = filtd + 1;
11205
11206 li = listitem_alloc();
11207 if (li == NULL)
11208 {
11209 vim_free(s);
11210 break;
11211 }
11212 li->li_tv.v_type = VAR_STRING;
11213 li->li_tv.v_lock = 0;
11214 li->li_tv.vval.v_string = s;
11215 list_append(l, li);
11216
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000011217 if (++cnt >= maxline)
11218 break;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000011219 if (readlen <= 0)
11220 break;
11221 }
11222 else if (buf[filtd] == NUL)
11223 buf[filtd] = '\n';
11224 }
11225 if (readlen <= 0)
11226 break;
11227
11228 if (tolist == 0)
11229 {
11230 /* "buf" is full, need to move text to an allocated buffer */
11231 if (prev == NULL)
11232 {
11233 prev = vim_strnsave(buf, buflen);
11234 prevlen = buflen;
11235 }
11236 else
11237 {
11238 s = alloc((unsigned)(prevlen + buflen));
11239 if (s != NULL)
11240 {
11241 mch_memmove(s, prev, prevlen);
11242 mch_memmove(s + prevlen, buf, buflen);
11243 vim_free(prev);
11244 prev = s;
11245 prevlen += buflen;
11246 }
11247 }
11248 filtd = 0;
11249 }
11250 else
11251 {
11252 mch_memmove(buf, buf + tolist, buflen - tolist);
11253 filtd -= tolist;
11254 }
11255 }
11256
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000011257 vim_free(prev);
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000011258 fclose(fd);
11259}
11260
11261
Bram Moolenaar0d660222005-01-07 21:51:51 +000011262#if defined(FEAT_CLIENTSERVER) && defined(FEAT_X11)
11263static void make_connection __ARGS((void));
11264static int check_connection __ARGS((void));
11265
11266 static void
11267make_connection()
11268{
11269 if (X_DISPLAY == NULL
11270# ifdef FEAT_GUI
11271 && !gui.in_use
11272# endif
11273 )
11274 {
11275 x_force_connect = TRUE;
11276 setup_term_clip();
11277 x_force_connect = FALSE;
11278 }
11279}
11280
11281 static int
11282check_connection()
11283{
11284 make_connection();
11285 if (X_DISPLAY == NULL)
11286 {
11287 EMSG(_("E240: No connection to Vim server"));
11288 return FAIL;
11289 }
11290 return OK;
11291}
11292#endif
11293
11294#ifdef FEAT_CLIENTSERVER
Bram Moolenaar33570922005-01-25 22:26:29 +000011295static void remote_common __ARGS((typval_T *argvars, typval_T *rettv, int expr));
Bram Moolenaar0d660222005-01-07 21:51:51 +000011296
11297 static void
11298remote_common(argvars, rettv, expr)
Bram Moolenaar33570922005-01-25 22:26:29 +000011299 typval_T *argvars;
11300 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000011301 int expr;
11302{
11303 char_u *server_name;
11304 char_u *keys;
11305 char_u *r = NULL;
11306 char_u buf[NUMBUFLEN];
11307# ifdef WIN32
11308 HWND w;
11309# else
11310 Window w;
11311# endif
11312
11313 if (check_restricted() || check_secure())
11314 return;
11315
11316# ifdef FEAT_X11
11317 if (check_connection() == FAIL)
11318 return;
11319# endif
11320
11321 server_name = get_tv_string(&argvars[0]);
11322 keys = get_tv_string_buf(&argvars[1], buf);
11323# ifdef WIN32
11324 if (serverSendToVim(server_name, keys, &r, &w, expr, TRUE) < 0)
11325# else
11326 if (serverSendToVim(X_DISPLAY, server_name, keys, &r, &w, expr, 0, TRUE)
11327 < 0)
11328# endif
11329 {
11330 if (r != NULL)
11331 EMSG(r); /* sending worked but evaluation failed */
11332 else
11333 EMSG2(_("E241: Unable to send to %s"), server_name);
11334 return;
11335 }
11336
11337 rettv->vval.v_string = r;
11338
11339 if (argvars[2].v_type != VAR_UNKNOWN)
11340 {
Bram Moolenaar33570922005-01-25 22:26:29 +000011341 dictitem_T v;
Bram Moolenaar0d660222005-01-07 21:51:51 +000011342 char_u str[30];
11343
11344 sprintf((char *)str, "0x%x", (unsigned int)w);
Bram Moolenaar33570922005-01-25 22:26:29 +000011345 v.di_tv.v_type = VAR_STRING;
11346 v.di_tv.vval.v_string = vim_strsave(str);
11347 set_var(get_tv_string(&argvars[2]), &v.di_tv, FALSE);
11348 vim_free(v.di_tv.vval.v_string);
Bram Moolenaar0d660222005-01-07 21:51:51 +000011349 }
11350}
11351#endif
11352
11353/*
11354 * "remote_expr()" function
11355 */
11356/*ARGSUSED*/
11357 static void
11358f_remote_expr(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000011359 typval_T *argvars;
11360 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000011361{
11362 rettv->v_type = VAR_STRING;
11363 rettv->vval.v_string = NULL;
11364#ifdef FEAT_CLIENTSERVER
11365 remote_common(argvars, rettv, TRUE);
11366#endif
11367}
11368
11369/*
11370 * "remote_foreground()" function
11371 */
11372/*ARGSUSED*/
11373 static void
11374f_remote_foreground(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 rettv->vval.v_number = 0;
11379#ifdef FEAT_CLIENTSERVER
11380# ifdef WIN32
11381 /* On Win32 it's done in this application. */
11382 serverForeground(get_tv_string(&argvars[0]));
11383# else
11384 /* Send a foreground() expression to the server. */
11385 argvars[1].v_type = VAR_STRING;
11386 argvars[1].vval.v_string = vim_strsave((char_u *)"foreground()");
11387 argvars[2].v_type = VAR_UNKNOWN;
11388 remote_common(argvars, rettv, TRUE);
11389 vim_free(argvars[1].vval.v_string);
11390# endif
11391#endif
11392}
11393
11394/*ARGSUSED*/
11395 static void
11396f_remote_peek(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000011397 typval_T *argvars;
11398 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000011399{
11400#ifdef FEAT_CLIENTSERVER
Bram Moolenaar33570922005-01-25 22:26:29 +000011401 dictitem_T v;
Bram Moolenaar0d660222005-01-07 21:51:51 +000011402 char_u *s = NULL;
11403# ifdef WIN32
11404 int n = 0;
11405# endif
11406
11407 if (check_restricted() || check_secure())
11408 {
11409 rettv->vval.v_number = -1;
11410 return;
11411 }
11412# ifdef WIN32
11413 sscanf(get_tv_string(&argvars[0]), "%x", &n);
11414 if (n == 0)
11415 rettv->vval.v_number = -1;
11416 else
11417 {
11418 s = serverGetReply((HWND)n, FALSE, FALSE, FALSE);
11419 rettv->vval.v_number = (s != NULL);
11420 }
11421# else
11422 rettv->vval.v_number = 0;
11423 if (check_connection() == FAIL)
11424 return;
11425
11426 rettv->vval.v_number = serverPeekReply(X_DISPLAY,
11427 serverStrToWin(get_tv_string(&argvars[0])), &s);
11428# endif
11429
11430 if (argvars[1].v_type != VAR_UNKNOWN && rettv->vval.v_number > 0)
11431 {
Bram Moolenaar33570922005-01-25 22:26:29 +000011432 v.di_tv.v_type = VAR_STRING;
11433 v.di_tv.vval.v_string = vim_strsave(s);
11434 set_var(get_tv_string(&argvars[1]), &v.di_tv, FALSE);
11435 vim_free(v.di_tv.vval.v_string);
Bram Moolenaar0d660222005-01-07 21:51:51 +000011436 }
11437#else
11438 rettv->vval.v_number = -1;
11439#endif
11440}
11441
11442/*ARGSUSED*/
11443 static void
11444f_remote_read(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000011445 typval_T *argvars;
11446 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000011447{
11448 char_u *r = NULL;
11449
11450#ifdef FEAT_CLIENTSERVER
11451 if (!check_restricted() && !check_secure())
11452 {
11453# ifdef WIN32
11454 /* The server's HWND is encoded in the 'id' parameter */
11455 int n = 0;
11456
11457 sscanf(get_tv_string(&argvars[0]), "%x", &n);
11458 if (n != 0)
11459 r = serverGetReply((HWND)n, FALSE, TRUE, TRUE);
11460 if (r == NULL)
11461# else
11462 if (check_connection() == FAIL || serverReadReply(X_DISPLAY,
11463 serverStrToWin(get_tv_string(&argvars[0])), &r, FALSE) < 0)
11464# endif
11465 EMSG(_("E277: Unable to read a server reply"));
11466 }
11467#endif
11468 rettv->v_type = VAR_STRING;
11469 rettv->vval.v_string = r;
11470}
11471
11472/*
11473 * "remote_send()" function
11474 */
11475/*ARGSUSED*/
11476 static void
11477f_remote_send(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000011478 typval_T *argvars;
11479 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000011480{
11481 rettv->v_type = VAR_STRING;
11482 rettv->vval.v_string = NULL;
11483#ifdef FEAT_CLIENTSERVER
11484 remote_common(argvars, rettv, FALSE);
11485#endif
11486}
11487
11488/*
Bram Moolenaar8c711452005-01-14 21:53:12 +000011489 * "remove()" function
Bram Moolenaar49cd9572005-01-03 21:06:01 +000011490 */
11491 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011492f_remove(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000011493 typval_T *argvars;
11494 typval_T *rettv;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000011495{
Bram Moolenaar33570922005-01-25 22:26:29 +000011496 list_T *l;
11497 listitem_T *item, *item2;
11498 listitem_T *li;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000011499 long idx;
Bram Moolenaar8a283e52005-01-06 23:28:25 +000011500 long end;
Bram Moolenaar8c711452005-01-14 21:53:12 +000011501 char_u *key;
Bram Moolenaar33570922005-01-25 22:26:29 +000011502 dict_T *d;
11503 dictitem_T *di;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000011504
Bram Moolenaar8a283e52005-01-06 23:28:25 +000011505 rettv->vval.v_number = 0;
Bram Moolenaar8c711452005-01-14 21:53:12 +000011506 if (argvars[0].v_type == VAR_DICT)
11507 {
11508 if (argvars[2].v_type != VAR_UNKNOWN)
11509 EMSG2(_(e_toomanyarg), "remove()");
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000011510 else if ((d = argvars[0].vval.v_dict) != NULL
Bram Moolenaar758711c2005-02-02 23:11:38 +000011511 && !tv_check_lock(d->dv_lock, (char_u *)"remove()"))
Bram Moolenaar8c711452005-01-14 21:53:12 +000011512 {
11513 key = get_tv_string(&argvars[1]);
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000011514 di = dict_find(d, key, -1);
Bram Moolenaar8c711452005-01-14 21:53:12 +000011515 if (di == NULL)
11516 EMSG2(_(e_dictkey), key);
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000011517 else
11518 {
11519 *rettv = di->di_tv;
11520 init_tv(&di->di_tv);
11521 dictitem_remove(d, di);
11522 }
Bram Moolenaar8c711452005-01-14 21:53:12 +000011523 }
11524 }
11525 else if (argvars[0].v_type != VAR_LIST)
11526 EMSG2(_(e_listdictarg), "remove()");
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000011527 else if ((l = argvars[0].vval.v_list) != NULL
11528 && !tv_check_lock(l->lv_lock, (char_u *)"remove()"))
Bram Moolenaar49cd9572005-01-03 21:06:01 +000011529 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011530 idx = get_tv_number(&argvars[1]);
Bram Moolenaar8a283e52005-01-06 23:28:25 +000011531 item = list_find(l, idx);
Bram Moolenaar49cd9572005-01-03 21:06:01 +000011532 if (item == NULL)
11533 EMSGN(_(e_listidx), idx);
11534 else
11535 {
Bram Moolenaar8a283e52005-01-06 23:28:25 +000011536 if (argvars[2].v_type == VAR_UNKNOWN)
11537 {
11538 /* Remove one item, return its value. */
Bram Moolenaar7480b5c2005-01-16 22:07:38 +000011539 list_remove(l, item, item);
Bram Moolenaar8a283e52005-01-06 23:28:25 +000011540 *rettv = item->li_tv;
11541 vim_free(item);
11542 }
11543 else
11544 {
11545 /* Remove range of items, return list with values. */
11546 end = get_tv_number(&argvars[2]);
11547 item2 = list_find(l, end);
11548 if (item2 == NULL)
11549 EMSGN(_(e_listidx), end);
11550 else
11551 {
Bram Moolenaar758711c2005-02-02 23:11:38 +000011552 int cnt = 0;
11553
11554 for (li = item; li != NULL; li = li->li_next)
11555 {
11556 ++cnt;
11557 if (li == item2)
11558 break;
11559 }
Bram Moolenaar8a283e52005-01-06 23:28:25 +000011560 if (li == NULL) /* didn't find "item2" after "item" */
11561 EMSG(_(e_invrange));
11562 else
11563 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +000011564 list_remove(l, item, item2);
Bram Moolenaar8a283e52005-01-06 23:28:25 +000011565 l = list_alloc();
11566 if (l != NULL)
11567 {
11568 rettv->v_type = VAR_LIST;
11569 rettv->vval.v_list = l;
11570 l->lv_first = item;
11571 l->lv_last = item2;
11572 l->lv_refcount = 1;
11573 item->li_prev = NULL;
11574 item2->li_next = NULL;
Bram Moolenaar758711c2005-02-02 23:11:38 +000011575 l->lv_len = cnt;
Bram Moolenaar8a283e52005-01-06 23:28:25 +000011576 }
11577 }
11578 }
11579 }
Bram Moolenaar49cd9572005-01-03 21:06:01 +000011580 }
11581 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000011582}
11583
11584/*
11585 * "rename({from}, {to})" function
11586 */
11587 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011588f_rename(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000011589 typval_T *argvars;
11590 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011591{
11592 char_u buf[NUMBUFLEN];
11593
11594 if (check_restricted() || check_secure())
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011595 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011596 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011597 rettv->vval.v_number = vim_rename(get_tv_string(&argvars[0]),
11598 get_tv_string_buf(&argvars[1], buf));
Bram Moolenaar071d4272004-06-13 20:20:40 +000011599}
11600
11601/*
Bram Moolenaar8a283e52005-01-06 23:28:25 +000011602 * "repeat()" function
11603 */
11604/*ARGSUSED*/
11605 static void
11606f_repeat(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000011607 typval_T *argvars;
11608 typval_T *rettv;
Bram Moolenaar8a283e52005-01-06 23:28:25 +000011609{
11610 char_u *p;
11611 int n;
11612 int slen;
11613 int len;
11614 char_u *r;
11615 int i;
Bram Moolenaar33570922005-01-25 22:26:29 +000011616 list_T *l;
Bram Moolenaar8a283e52005-01-06 23:28:25 +000011617
11618 n = get_tv_number(&argvars[1]);
11619 if (argvars[0].v_type == VAR_LIST)
11620 {
11621 l = list_alloc();
11622 if (l != NULL && argvars[0].vval.v_list != NULL)
11623 {
11624 l->lv_refcount = 1;
11625 while (n-- > 0)
11626 if (list_extend(l, argvars[0].vval.v_list, NULL) == FAIL)
11627 break;
11628 }
11629 rettv->v_type = VAR_LIST;
11630 rettv->vval.v_list = l;
11631 }
11632 else
11633 {
11634 p = get_tv_string(&argvars[0]);
11635 rettv->v_type = VAR_STRING;
11636 rettv->vval.v_string = NULL;
11637
11638 slen = (int)STRLEN(p);
11639 len = slen * n;
11640 if (len <= 0)
11641 return;
11642
11643 r = alloc(len + 1);
11644 if (r != NULL)
11645 {
11646 for (i = 0; i < n; i++)
11647 mch_memmove(r + i * slen, p, (size_t)slen);
11648 r[len] = NUL;
11649 }
11650
11651 rettv->vval.v_string = r;
11652 }
11653}
11654
11655/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000011656 * "resolve()" function
11657 */
11658 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011659f_resolve(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000011660 typval_T *argvars;
11661 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011662{
11663 char_u *p;
11664
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011665 p = get_tv_string(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +000011666#ifdef FEAT_SHORTCUT
11667 {
11668 char_u *v = NULL;
11669
11670 v = mch_resolve_shortcut(p);
11671 if (v != NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011672 rettv->vval.v_string = v;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011673 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011674 rettv->vval.v_string = vim_strsave(p);
Bram Moolenaar071d4272004-06-13 20:20:40 +000011675 }
11676#else
11677# ifdef HAVE_READLINK
11678 {
11679 char_u buf[MAXPATHL + 1];
11680 char_u *cpy;
11681 int len;
11682 char_u *remain = NULL;
11683 char_u *q;
11684 int is_relative_to_current = FALSE;
11685 int has_trailing_pathsep = FALSE;
11686 int limit = 100;
11687
11688 p = vim_strsave(p);
11689
11690 if (p[0] == '.' && (vim_ispathsep(p[1])
11691 || (p[1] == '.' && (vim_ispathsep(p[2])))))
11692 is_relative_to_current = TRUE;
11693
11694 len = STRLEN(p);
Bram Moolenaar1cd871b2004-12-19 22:46:22 +000011695 if (len > 0 && after_pathsep(p, p + len))
Bram Moolenaar071d4272004-06-13 20:20:40 +000011696 has_trailing_pathsep = TRUE;
11697
11698 q = getnextcomp(p);
11699 if (*q != NUL)
11700 {
11701 /* Separate the first path component in "p", and keep the
11702 * remainder (beginning with the path separator). */
11703 remain = vim_strsave(q - 1);
11704 q[-1] = NUL;
11705 }
11706
11707 for (;;)
11708 {
11709 for (;;)
11710 {
11711 len = readlink((char *)p, (char *)buf, MAXPATHL);
11712 if (len <= 0)
11713 break;
11714 buf[len] = NUL;
11715
11716 if (limit-- == 0)
11717 {
11718 vim_free(p);
11719 vim_free(remain);
11720 EMSG(_("E655: Too many symbolic links (cycle?)"));
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011721 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011722 goto fail;
11723 }
11724
11725 /* Ensure that the result will have a trailing path separator
11726 * if the argument has one. */
11727 if (remain == NULL && has_trailing_pathsep)
11728 add_pathsep(buf);
11729
11730 /* Separate the first path component in the link value and
11731 * concatenate the remainders. */
11732 q = getnextcomp(vim_ispathsep(*buf) ? buf + 1 : buf);
11733 if (*q != NUL)
11734 {
11735 if (remain == NULL)
11736 remain = vim_strsave(q - 1);
11737 else
11738 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000011739 cpy = vim_strnsave(q-1, STRLEN(q-1) + STRLEN(remain));
Bram Moolenaar071d4272004-06-13 20:20:40 +000011740 if (cpy != NULL)
11741 {
11742 STRCAT(cpy, remain);
11743 vim_free(remain);
11744 remain = cpy;
11745 }
11746 }
11747 q[-1] = NUL;
11748 }
11749
11750 q = gettail(p);
11751 if (q > p && *q == NUL)
11752 {
11753 /* Ignore trailing path separator. */
11754 q[-1] = NUL;
11755 q = gettail(p);
11756 }
11757 if (q > p && !mch_isFullName(buf))
11758 {
11759 /* symlink is relative to directory of argument */
11760 cpy = alloc((unsigned)(STRLEN(p) + STRLEN(buf) + 1));
11761 if (cpy != NULL)
11762 {
11763 STRCPY(cpy, p);
11764 STRCPY(gettail(cpy), buf);
11765 vim_free(p);
11766 p = cpy;
11767 }
11768 }
11769 else
11770 {
11771 vim_free(p);
11772 p = vim_strsave(buf);
11773 }
11774 }
11775
11776 if (remain == NULL)
11777 break;
11778
11779 /* Append the first path component of "remain" to "p". */
11780 q = getnextcomp(remain + 1);
11781 len = q - remain - (*q != NUL);
11782 cpy = vim_strnsave(p, STRLEN(p) + len);
11783 if (cpy != NULL)
11784 {
11785 STRNCAT(cpy, remain, len);
11786 vim_free(p);
11787 p = cpy;
11788 }
11789 /* Shorten "remain". */
11790 if (*q != NUL)
11791 STRCPY(remain, q - 1);
11792 else
11793 {
11794 vim_free(remain);
11795 remain = NULL;
11796 }
11797 }
11798
11799 /* If the result is a relative path name, make it explicitly relative to
11800 * the current directory if and only if the argument had this form. */
11801 if (!vim_ispathsep(*p))
11802 {
11803 if (is_relative_to_current
11804 && *p != NUL
11805 && !(p[0] == '.'
11806 && (p[1] == NUL
11807 || vim_ispathsep(p[1])
11808 || (p[1] == '.'
11809 && (p[2] == NUL
11810 || vim_ispathsep(p[2]))))))
11811 {
11812 /* Prepend "./". */
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000011813 cpy = concat_str((char_u *)"./", p);
Bram Moolenaar071d4272004-06-13 20:20:40 +000011814 if (cpy != NULL)
11815 {
Bram Moolenaar071d4272004-06-13 20:20:40 +000011816 vim_free(p);
11817 p = cpy;
11818 }
11819 }
11820 else if (!is_relative_to_current)
11821 {
11822 /* Strip leading "./". */
11823 q = p;
11824 while (q[0] == '.' && vim_ispathsep(q[1]))
11825 q += 2;
11826 if (q > p)
11827 mch_memmove(p, p + 2, STRLEN(p + 2) + (size_t)1);
11828 }
11829 }
11830
11831 /* Ensure that the result will have no trailing path separator
11832 * if the argument had none. But keep "/" or "//". */
11833 if (!has_trailing_pathsep)
11834 {
11835 q = p + STRLEN(p);
Bram Moolenaar1cd871b2004-12-19 22:46:22 +000011836 if (after_pathsep(p, q))
11837 *gettail_sep(p) = NUL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011838 }
11839
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011840 rettv->vval.v_string = p;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011841 }
11842# else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011843 rettv->vval.v_string = vim_strsave(p);
Bram Moolenaar071d4272004-06-13 20:20:40 +000011844# endif
11845#endif
11846
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011847 simplify_filename(rettv->vval.v_string);
Bram Moolenaar071d4272004-06-13 20:20:40 +000011848
11849#ifdef HAVE_READLINK
11850fail:
11851#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011852 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011853}
11854
11855/*
Bram Moolenaar0d660222005-01-07 21:51:51 +000011856 * "reverse({list})" function
Bram Moolenaar071d4272004-06-13 20:20:40 +000011857 */
11858 static void
Bram Moolenaar0d660222005-01-07 21:51:51 +000011859f_reverse(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000011860 typval_T *argvars;
11861 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011862{
Bram Moolenaar33570922005-01-25 22:26:29 +000011863 list_T *l;
11864 listitem_T *li, *ni;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011865
Bram Moolenaar0d660222005-01-07 21:51:51 +000011866 rettv->vval.v_number = 0;
11867 if (argvars[0].v_type != VAR_LIST)
11868 EMSG2(_(e_listarg), "reverse()");
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000011869 else if ((l = argvars[0].vval.v_list) != NULL
11870 && !tv_check_lock(l->lv_lock, (char_u *)"reverse()"))
Bram Moolenaar0d660222005-01-07 21:51:51 +000011871 {
11872 li = l->lv_last;
Bram Moolenaar81bf7082005-02-12 14:31:42 +000011873 l->lv_first = l->lv_last = NULL;
Bram Moolenaar758711c2005-02-02 23:11:38 +000011874 l->lv_len = 0;
Bram Moolenaar0d660222005-01-07 21:51:51 +000011875 while (li != NULL)
11876 {
11877 ni = li->li_prev;
11878 list_append(l, li);
11879 li = ni;
11880 }
11881 rettv->vval.v_list = l;
11882 rettv->v_type = VAR_LIST;
11883 ++l->lv_refcount;
11884 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000011885}
11886
Bram Moolenaar5eb86f92004-07-26 12:53:41 +000011887#define SP_NOMOVE 1 /* don't move cursor */
11888#define SP_REPEAT 2 /* repeat to find outer pair */
11889#define SP_RETCOUNT 4 /* return matchcount */
11890
Bram Moolenaar33570922005-01-25 22:26:29 +000011891static int get_search_arg __ARGS((typval_T *varp, int *flagsp));
Bram Moolenaar0d660222005-01-07 21:51:51 +000011892
11893/*
11894 * Get flags for a search function.
11895 * Possibly sets "p_ws".
11896 * Returns BACKWARD, FORWARD or zero (for an error).
11897 */
11898 static int
11899get_search_arg(varp, flagsp)
Bram Moolenaar33570922005-01-25 22:26:29 +000011900 typval_T *varp;
Bram Moolenaar0d660222005-01-07 21:51:51 +000011901 int *flagsp;
11902{
11903 int dir = FORWARD;
11904 char_u *flags;
11905 char_u nbuf[NUMBUFLEN];
11906 int mask;
11907
11908 if (varp->v_type != VAR_UNKNOWN)
11909 {
11910 flags = get_tv_string_buf(varp, nbuf);
11911 while (*flags != NUL)
11912 {
11913 switch (*flags)
11914 {
11915 case 'b': dir = BACKWARD; break;
11916 case 'w': p_ws = TRUE; break;
11917 case 'W': p_ws = FALSE; break;
11918 default: mask = 0;
11919 if (flagsp != NULL)
11920 switch (*flags)
11921 {
11922 case 'n': mask = SP_NOMOVE; break;
11923 case 'r': mask = SP_REPEAT; break;
11924 case 'm': mask = SP_RETCOUNT; break;
11925 }
11926 if (mask == 0)
11927 {
11928 EMSG2(_(e_invarg2), flags);
11929 dir = 0;
11930 }
11931 else
11932 *flagsp |= mask;
11933 }
11934 if (dir == 0)
11935 break;
11936 ++flags;
11937 }
11938 }
11939 return dir;
11940}
11941
Bram Moolenaar071d4272004-06-13 20:20:40 +000011942/*
11943 * "search()" function
11944 */
11945 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011946f_search(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000011947 typval_T *argvars;
11948 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011949{
11950 char_u *pat;
11951 pos_T pos;
Bram Moolenaar5eb86f92004-07-26 12:53:41 +000011952 pos_T save_cursor;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011953 int save_p_ws = p_ws;
11954 int dir;
Bram Moolenaar5eb86f92004-07-26 12:53:41 +000011955 int flags = 0;
11956
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011957 rettv->vval.v_number = 0; /* default: FAIL */
Bram Moolenaar071d4272004-06-13 20:20:40 +000011958
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011959 pat = get_tv_string(&argvars[0]);
Bram Moolenaar5eb86f92004-07-26 12:53:41 +000011960 dir = get_search_arg(&argvars[1], &flags); /* may set p_ws */
11961 if (dir == 0)
11962 goto theend;
11963 if ((flags & ~SP_NOMOVE) != 0)
11964 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011965 EMSG2(_(e_invarg2), get_tv_string(&argvars[1]));
Bram Moolenaar5eb86f92004-07-26 12:53:41 +000011966 goto theend;
11967 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000011968
Bram Moolenaar5eb86f92004-07-26 12:53:41 +000011969 pos = save_cursor = curwin->w_cursor;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011970 if (searchit(curwin, curbuf, &pos, dir, pat, 1L,
11971 SEARCH_KEEP, RE_SEARCH) != FAIL)
11972 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011973 rettv->vval.v_number = pos.lnum;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011974 curwin->w_cursor = pos;
11975 /* "/$" will put the cursor after the end of the line, may need to
11976 * correct that here */
11977 check_cursor();
11978 }
Bram Moolenaar5eb86f92004-07-26 12:53:41 +000011979
11980 /* If 'n' flag is used: restore cursor position. */
11981 if (flags & SP_NOMOVE)
11982 curwin->w_cursor = save_cursor;
11983theend:
Bram Moolenaar071d4272004-06-13 20:20:40 +000011984 p_ws = save_p_ws;
11985}
11986
Bram Moolenaar071d4272004-06-13 20:20:40 +000011987/*
11988 * "searchpair()" function
11989 */
11990 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011991f_searchpair(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000011992 typval_T *argvars;
11993 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011994{
11995 char_u *spat, *mpat, *epat;
11996 char_u *skip;
11997 char_u *pat, *pat2, *pat3;
11998 pos_T pos;
11999 pos_T firstpos;
12000 pos_T save_cursor;
12001 pos_T save_pos;
12002 int save_p_ws = p_ws;
12003 char_u *save_cpo;
12004 int dir;
12005 int flags = 0;
12006 char_u nbuf1[NUMBUFLEN];
12007 char_u nbuf2[NUMBUFLEN];
12008 char_u nbuf3[NUMBUFLEN];
12009 int n;
12010 int r;
12011 int nest = 1;
12012 int err;
12013
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012014 rettv->vval.v_number = 0; /* default: FAIL */
Bram Moolenaar071d4272004-06-13 20:20:40 +000012015
12016 /* Make 'cpoptions' empty, the 'l' flag should not be used here. */
12017 save_cpo = p_cpo;
12018 p_cpo = (char_u *)"";
12019
12020 /* Get the three pattern arguments: start, middle, end. */
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012021 spat = get_tv_string(&argvars[0]);
12022 mpat = get_tv_string_buf(&argvars[1], nbuf1);
12023 epat = get_tv_string_buf(&argvars[2], nbuf2);
Bram Moolenaar071d4272004-06-13 20:20:40 +000012024
12025 /* Make two search patterns: start/end (pat2, for in nested pairs) and
12026 * start/middle/end (pat3, for the top pair). */
12027 pat2 = alloc((unsigned)(STRLEN(spat) + STRLEN(epat) + 15));
12028 pat3 = alloc((unsigned)(STRLEN(spat) + STRLEN(mpat) + STRLEN(epat) + 23));
12029 if (pat2 == NULL || pat3 == NULL)
12030 goto theend;
12031 sprintf((char *)pat2, "\\(%s\\m\\)\\|\\(%s\\m\\)", spat, epat);
12032 if (*mpat == NUL)
12033 STRCPY(pat3, pat2);
12034 else
12035 sprintf((char *)pat3, "\\(%s\\m\\)\\|\\(%s\\m\\)\\|\\(%s\\m\\)",
12036 spat, epat, mpat);
12037
12038 /* Handle the optional fourth argument: flags */
12039 dir = get_search_arg(&argvars[3], &flags); /* may set p_ws */
Bram Moolenaar5eb86f92004-07-26 12:53:41 +000012040 if (dir == 0)
12041 goto theend;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012042
12043 /* Optional fifth argument: skip expresion */
Bram Moolenaar49cd9572005-01-03 21:06:01 +000012044 if (argvars[3].v_type == VAR_UNKNOWN
12045 || argvars[4].v_type == VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +000012046 skip = (char_u *)"";
12047 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012048 skip = get_tv_string_buf(&argvars[4], nbuf3);
Bram Moolenaar071d4272004-06-13 20:20:40 +000012049
12050 save_cursor = curwin->w_cursor;
12051 pos = curwin->w_cursor;
12052 firstpos.lnum = 0;
12053 pat = pat3;
12054 for (;;)
12055 {
12056 n = searchit(curwin, curbuf, &pos, dir, pat, 1L,
12057 SEARCH_KEEP, RE_SEARCH);
12058 if (n == FAIL || (firstpos.lnum != 0 && equalpos(pos, firstpos)))
12059 /* didn't find it or found the first match again: FAIL */
12060 break;
12061
12062 if (firstpos.lnum == 0)
12063 firstpos = pos;
12064
12065 /* If the skip pattern matches, ignore this match. */
12066 if (*skip != NUL)
12067 {
12068 save_pos = curwin->w_cursor;
12069 curwin->w_cursor = pos;
12070 r = eval_to_bool(skip, &err, NULL, FALSE);
12071 curwin->w_cursor = save_pos;
12072 if (err)
12073 {
12074 /* Evaluating {skip} caused an error, break here. */
12075 curwin->w_cursor = save_cursor;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012076 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012077 break;
12078 }
12079 if (r)
12080 continue;
12081 }
12082
12083 if ((dir == BACKWARD && n == 3) || (dir == FORWARD && n == 2))
12084 {
12085 /* Found end when searching backwards or start when searching
12086 * forward: nested pair. */
12087 ++nest;
12088 pat = pat2; /* nested, don't search for middle */
12089 }
12090 else
12091 {
12092 /* Found end when searching forward or start when searching
12093 * backward: end of (nested) pair; or found middle in outer pair. */
12094 if (--nest == 1)
12095 pat = pat3; /* outer level, search for middle */
12096 }
12097
12098 if (nest == 0)
12099 {
12100 /* Found the match: return matchcount or line number. */
12101 if (flags & SP_RETCOUNT)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012102 ++rettv->vval.v_number;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012103 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012104 rettv->vval.v_number = pos.lnum;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012105 curwin->w_cursor = pos;
12106 if (!(flags & SP_REPEAT))
12107 break;
12108 nest = 1; /* search for next unmatched */
12109 }
12110 }
12111
12112 /* If 'n' flag is used or search failed: restore cursor position. */
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012113 if ((flags & SP_NOMOVE) || rettv->vval.v_number == 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +000012114 curwin->w_cursor = save_cursor;
12115
12116theend:
12117 vim_free(pat2);
12118 vim_free(pat3);
12119 p_ws = save_p_ws;
12120 p_cpo = save_cpo;
12121}
12122
Bram Moolenaar0d660222005-01-07 21:51:51 +000012123/*ARGSUSED*/
12124 static void
12125f_server2client(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000012126 typval_T *argvars;
12127 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012128{
Bram Moolenaar0d660222005-01-07 21:51:51 +000012129#ifdef FEAT_CLIENTSERVER
12130 char_u buf[NUMBUFLEN];
12131 char_u *server = get_tv_string(&argvars[0]);
12132 char_u *reply = get_tv_string_buf(&argvars[1], buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +000012133
Bram Moolenaar0d660222005-01-07 21:51:51 +000012134 rettv->vval.v_number = -1;
12135 if (check_restricted() || check_secure())
12136 return;
12137# ifdef FEAT_X11
12138 if (check_connection() == FAIL)
12139 return;
12140# endif
12141
12142 if (serverSendReply(server, reply) < 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +000012143 {
Bram Moolenaar0d660222005-01-07 21:51:51 +000012144 EMSG(_("E258: Unable to send to client"));
12145 return;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012146 }
Bram Moolenaar0d660222005-01-07 21:51:51 +000012147 rettv->vval.v_number = 0;
12148#else
12149 rettv->vval.v_number = -1;
12150#endif
12151}
12152
12153/*ARGSUSED*/
12154 static void
12155f_serverlist(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000012156 typval_T *argvars;
12157 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000012158{
12159 char_u *r = NULL;
12160
12161#ifdef FEAT_CLIENTSERVER
12162# ifdef WIN32
12163 r = serverGetVimNames();
12164# else
12165 make_connection();
12166 if (X_DISPLAY != NULL)
12167 r = serverGetVimNames(X_DISPLAY);
12168# endif
12169#endif
12170 rettv->v_type = VAR_STRING;
12171 rettv->vval.v_string = r;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012172}
12173
12174/*
12175 * "setbufvar()" function
12176 */
12177/*ARGSUSED*/
12178 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012179f_setbufvar(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000012180 typval_T *argvars;
12181 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012182{
12183 buf_T *buf;
12184#ifdef FEAT_AUTOCMD
12185 aco_save_T aco;
12186#else
12187 buf_T *save_curbuf;
12188#endif
12189 char_u *varname, *bufvarname;
Bram Moolenaar33570922005-01-25 22:26:29 +000012190 typval_T *varp;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012191 char_u nbuf[NUMBUFLEN];
12192
12193 if (check_restricted() || check_secure())
12194 return;
12195 ++emsg_off;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012196 buf = get_buf_tv(&argvars[0]);
12197 varname = get_tv_string(&argvars[1]);
Bram Moolenaar071d4272004-06-13 20:20:40 +000012198 varp = &argvars[2];
12199
12200 if (buf != NULL && varname != NULL && varp != NULL)
12201 {
12202 /* set curbuf to be our buf, temporarily */
12203#ifdef FEAT_AUTOCMD
12204 aucmd_prepbuf(&aco, buf);
12205#else
12206 save_curbuf = curbuf;
12207 curbuf = buf;
12208#endif
12209
12210 if (*varname == '&')
12211 {
12212 ++varname;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012213 set_option_value(varname, get_tv_number(varp),
12214 get_tv_string_buf(varp, nbuf), OPT_LOCAL);
Bram Moolenaar071d4272004-06-13 20:20:40 +000012215 }
12216 else
12217 {
12218 bufvarname = alloc((unsigned)STRLEN(varname) + 3);
12219 if (bufvarname != NULL)
12220 {
12221 STRCPY(bufvarname, "b:");
12222 STRCPY(bufvarname + 2, varname);
Bram Moolenaar1c2fda22005-01-02 11:43:19 +000012223 set_var(bufvarname, varp, TRUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +000012224 vim_free(bufvarname);
12225 }
12226 }
12227
12228 /* reset notion of buffer */
12229#ifdef FEAT_AUTOCMD
12230 aucmd_restbuf(&aco);
12231#else
12232 curbuf = save_curbuf;
12233#endif
12234 }
12235 --emsg_off;
12236}
12237
12238/*
12239 * "setcmdpos()" function
12240 */
12241 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012242f_setcmdpos(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000012243 typval_T *argvars;
12244 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012245{
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012246 rettv->vval.v_number = set_cmdline_pos(
12247 (int)get_tv_number(&argvars[0]) - 1);
Bram Moolenaar071d4272004-06-13 20:20:40 +000012248}
12249
12250/*
12251 * "setline()" function
12252 */
12253 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012254f_setline(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000012255 typval_T *argvars;
12256 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012257{
12258 linenr_T lnum;
12259 char_u *line;
12260
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012261 lnum = get_tv_lnum(argvars);
12262 line = get_tv_string(&argvars[1]);
12263 rettv->vval.v_number = 1; /* FAIL is default */
Bram Moolenaar071d4272004-06-13 20:20:40 +000012264
12265 if (lnum >= 1
12266 && lnum <= curbuf->b_ml.ml_line_count
12267 && u_savesub(lnum) == OK
12268 && ml_replace(lnum, line, TRUE) == OK)
12269 {
12270 changed_bytes(lnum, 0);
12271 check_cursor_col();
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012272 rettv->vval.v_number = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012273 }
12274}
12275
12276/*
12277 * "setreg()" function
12278 */
12279 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012280f_setreg(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000012281 typval_T *argvars;
12282 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012283{
12284 int regname;
12285 char_u *strregname;
12286 char_u *stropt;
12287 int append;
12288 char_u yank_type;
12289 long block_len;
12290
12291 block_len = -1;
12292 yank_type = MAUTO;
12293 append = FALSE;
12294
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012295 strregname = get_tv_string(argvars);
12296 rettv->vval.v_number = 1; /* FAIL is default */
Bram Moolenaar071d4272004-06-13 20:20:40 +000012297
12298 regname = (strregname == NULL ? '"' : *strregname);
12299 if (regname == 0 || regname == '@')
12300 regname = '"';
12301 else if (regname == '=')
12302 return;
12303
Bram Moolenaar49cd9572005-01-03 21:06:01 +000012304 if (argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +000012305 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012306 for (stropt = get_tv_string(&argvars[2]); *stropt != NUL; ++stropt)
Bram Moolenaar071d4272004-06-13 20:20:40 +000012307 switch (*stropt)
12308 {
12309 case 'a': case 'A': /* append */
12310 append = TRUE;
12311 break;
12312 case 'v': case 'c': /* character-wise selection */
12313 yank_type = MCHAR;
12314 break;
12315 case 'V': case 'l': /* line-wise selection */
12316 yank_type = MLINE;
12317 break;
12318#ifdef FEAT_VISUAL
12319 case 'b': case Ctrl_V: /* block-wise selection */
12320 yank_type = MBLOCK;
12321 if (VIM_ISDIGIT(stropt[1]))
12322 {
12323 ++stropt;
12324 block_len = getdigits(&stropt) - 1;
12325 --stropt;
12326 }
12327 break;
12328#endif
12329 }
12330 }
12331
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012332 write_reg_contents_ex(regname, get_tv_string(&argvars[1]), -1,
Bram Moolenaar071d4272004-06-13 20:20:40 +000012333 append, yank_type, block_len);
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012334 rettv->vval.v_number = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012335}
12336
12337
12338/*
12339 * "setwinvar(expr)" function
12340 */
12341/*ARGSUSED*/
12342 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012343f_setwinvar(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000012344 typval_T *argvars;
12345 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012346{
12347 win_T *win;
12348#ifdef FEAT_WINDOWS
12349 win_T *save_curwin;
12350#endif
12351 char_u *varname, *winvarname;
Bram Moolenaar33570922005-01-25 22:26:29 +000012352 typval_T *varp;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012353 char_u nbuf[NUMBUFLEN];
12354
12355 if (check_restricted() || check_secure())
12356 return;
12357 ++emsg_off;
12358 win = find_win_by_nr(&argvars[0]);
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012359 varname = get_tv_string(&argvars[1]);
Bram Moolenaar071d4272004-06-13 20:20:40 +000012360 varp = &argvars[2];
12361
12362 if (win != NULL && varname != NULL && varp != NULL)
12363 {
12364#ifdef FEAT_WINDOWS
12365 /* set curwin to be our win, temporarily */
12366 save_curwin = curwin;
12367 curwin = win;
12368 curbuf = curwin->w_buffer;
12369#endif
12370
12371 if (*varname == '&')
12372 {
12373 ++varname;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012374 set_option_value(varname, get_tv_number(varp),
12375 get_tv_string_buf(varp, nbuf), OPT_LOCAL);
Bram Moolenaar071d4272004-06-13 20:20:40 +000012376 }
12377 else
12378 {
12379 winvarname = alloc((unsigned)STRLEN(varname) + 3);
12380 if (winvarname != NULL)
12381 {
12382 STRCPY(winvarname, "w:");
12383 STRCPY(winvarname + 2, varname);
Bram Moolenaar1c2fda22005-01-02 11:43:19 +000012384 set_var(winvarname, varp, TRUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +000012385 vim_free(winvarname);
12386 }
12387 }
12388
12389#ifdef FEAT_WINDOWS
12390 /* Restore current window, if it's still valid (autocomands can make
12391 * it invalid). */
12392 if (win_valid(save_curwin))
12393 {
12394 curwin = save_curwin;
12395 curbuf = curwin->w_buffer;
12396 }
12397#endif
12398 }
12399 --emsg_off;
12400}
12401
12402/*
Bram Moolenaar0d660222005-01-07 21:51:51 +000012403 * "simplify()" function
Bram Moolenaar071d4272004-06-13 20:20:40 +000012404 */
12405 static void
Bram Moolenaar0d660222005-01-07 21:51:51 +000012406f_simplify(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000012407 typval_T *argvars;
12408 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012409{
Bram Moolenaar0d660222005-01-07 21:51:51 +000012410 char_u *p;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012411
Bram Moolenaar0d660222005-01-07 21:51:51 +000012412 p = get_tv_string(&argvars[0]);
12413 rettv->vval.v_string = vim_strsave(p);
12414 simplify_filename(rettv->vval.v_string); /* simplify in place */
12415 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012416}
12417
Bram Moolenaar0d660222005-01-07 21:51:51 +000012418static int
12419#ifdef __BORLANDC__
12420 _RTLENTRYF
12421#endif
12422 item_compare __ARGS((const void *s1, const void *s2));
12423static int
12424#ifdef __BORLANDC__
12425 _RTLENTRYF
12426#endif
12427 item_compare2 __ARGS((const void *s1, const void *s2));
12428
12429static int item_compare_ic;
12430static char_u *item_compare_func;
12431#define ITEM_COMPARE_FAIL 999
12432
Bram Moolenaar071d4272004-06-13 20:20:40 +000012433/*
Bram Moolenaar0d660222005-01-07 21:51:51 +000012434 * Compare functions for f_sort() below.
Bram Moolenaar071d4272004-06-13 20:20:40 +000012435 */
Bram Moolenaar0d660222005-01-07 21:51:51 +000012436 static int
12437#ifdef __BORLANDC__
12438_RTLENTRYF
12439#endif
12440item_compare(s1, s2)
12441 const void *s1;
12442 const void *s2;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012443{
Bram Moolenaar0d660222005-01-07 21:51:51 +000012444 char_u *p1, *p2;
12445 char_u *tofree1, *tofree2;
12446 int res;
12447 char_u numbuf1[NUMBUFLEN];
12448 char_u numbuf2[NUMBUFLEN];
Bram Moolenaar071d4272004-06-13 20:20:40 +000012449
Bram Moolenaar33570922005-01-25 22:26:29 +000012450 p1 = tv2string(&(*(listitem_T **)s1)->li_tv, &tofree1, numbuf1);
12451 p2 = tv2string(&(*(listitem_T **)s2)->li_tv, &tofree2, numbuf2);
Bram Moolenaar0d660222005-01-07 21:51:51 +000012452 if (item_compare_ic)
12453 res = STRICMP(p1, p2);
Bram Moolenaar071d4272004-06-13 20:20:40 +000012454 else
Bram Moolenaar0d660222005-01-07 21:51:51 +000012455 res = STRCMP(p1, p2);
12456 vim_free(tofree1);
12457 vim_free(tofree2);
12458 return res;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012459}
12460
12461 static int
Bram Moolenaar0d660222005-01-07 21:51:51 +000012462#ifdef __BORLANDC__
12463_RTLENTRYF
Bram Moolenaar071d4272004-06-13 20:20:40 +000012464#endif
Bram Moolenaar0d660222005-01-07 21:51:51 +000012465item_compare2(s1, s2)
12466 const void *s1;
12467 const void *s2;
12468{
12469 int res;
Bram Moolenaar33570922005-01-25 22:26:29 +000012470 typval_T rettv;
12471 typval_T argv[2];
Bram Moolenaar0d660222005-01-07 21:51:51 +000012472 int dummy;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012473
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000012474 /* copy the values. This is needed to be able to set v_lock to VAR_FIXED
12475 * in the copy without changing the original list items. */
Bram Moolenaar33570922005-01-25 22:26:29 +000012476 copy_tv(&(*(listitem_T **)s1)->li_tv, &argv[0]);
12477 copy_tv(&(*(listitem_T **)s2)->li_tv, &argv[1]);
Bram Moolenaar0d660222005-01-07 21:51:51 +000012478
12479 rettv.v_type = VAR_UNKNOWN; /* clear_tv() uses this */
12480 res = call_func(item_compare_func, STRLEN(item_compare_func),
Bram Moolenaare9a41262005-01-15 22:18:47 +000012481 &rettv, 2, argv, 0L, 0L, &dummy, TRUE, NULL);
Bram Moolenaar0d660222005-01-07 21:51:51 +000012482 clear_tv(&argv[0]);
12483 clear_tv(&argv[1]);
12484
12485 if (res == FAIL)
12486 res = ITEM_COMPARE_FAIL;
12487 else
12488 res = get_tv_number(&rettv);
12489 clear_tv(&rettv);
12490 return res;
12491}
12492
12493/*
12494 * "sort({list})" function
12495 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000012496 static void
Bram Moolenaar0d660222005-01-07 21:51:51 +000012497f_sort(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000012498 typval_T *argvars;
12499 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012500{
Bram Moolenaar33570922005-01-25 22:26:29 +000012501 list_T *l;
12502 listitem_T *li;
12503 listitem_T **ptrs;
Bram Moolenaar0d660222005-01-07 21:51:51 +000012504 long len;
12505 long i;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012506
Bram Moolenaar0d660222005-01-07 21:51:51 +000012507 rettv->vval.v_number = 0;
12508 if (argvars[0].v_type != VAR_LIST)
12509 EMSG2(_(e_listarg), "sort()");
Bram Moolenaar071d4272004-06-13 20:20:40 +000012510 else
12511 {
Bram Moolenaar0d660222005-01-07 21:51:51 +000012512 l = argvars[0].vval.v_list;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000012513 if (l == NULL || tv_check_lock(l->lv_lock, (char_u *)"sort()"))
Bram Moolenaar0d660222005-01-07 21:51:51 +000012514 return;
12515 rettv->vval.v_list = l;
12516 rettv->v_type = VAR_LIST;
12517 ++l->lv_refcount;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012518
Bram Moolenaar0d660222005-01-07 21:51:51 +000012519 len = list_len(l);
12520 if (len <= 1)
12521 return; /* short list sorts pretty quickly */
Bram Moolenaar071d4272004-06-13 20:20:40 +000012522
Bram Moolenaar0d660222005-01-07 21:51:51 +000012523 item_compare_ic = FALSE;
12524 item_compare_func = NULL;
12525 if (argvars[1].v_type != VAR_UNKNOWN)
12526 {
12527 if (argvars[1].v_type == VAR_FUNC)
12528 item_compare_func = argvars[0].vval.v_string;
12529 else
12530 {
12531 i = get_tv_number(&argvars[1]);
12532 if (i == 1)
12533 item_compare_ic = TRUE;
12534 else
12535 item_compare_func = get_tv_string(&argvars[1]);
12536 }
12537 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000012538
Bram Moolenaar0d660222005-01-07 21:51:51 +000012539 /* Make an array with each entry pointing to an item in the List. */
Bram Moolenaar33570922005-01-25 22:26:29 +000012540 ptrs = (listitem_T **)alloc((int)(len * sizeof(listitem_T *)));
Bram Moolenaar0d660222005-01-07 21:51:51 +000012541 if (ptrs == NULL)
12542 return;
12543 i = 0;
12544 for (li = l->lv_first; li != NULL; li = li->li_next)
12545 ptrs[i++] = li;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012546
Bram Moolenaar0d660222005-01-07 21:51:51 +000012547 /* test the compare function */
12548 if (item_compare_func != NULL
12549 && item_compare2((void *)&ptrs[0], (void *)&ptrs[1])
12550 == ITEM_COMPARE_FAIL)
Bram Moolenaare49b69a2005-01-08 16:11:57 +000012551 EMSG(_("E702: Sort compare function failed"));
Bram Moolenaar071d4272004-06-13 20:20:40 +000012552 else
Bram Moolenaar0d660222005-01-07 21:51:51 +000012553 {
12554 /* Sort the array with item pointers. */
Bram Moolenaar33570922005-01-25 22:26:29 +000012555 qsort((void *)ptrs, (size_t)len, sizeof(listitem_T *),
Bram Moolenaar0d660222005-01-07 21:51:51 +000012556 item_compare_func == NULL ? item_compare : item_compare2);
12557
12558 /* Clear the List and append the items in the sorted order. */
12559 l->lv_first = l->lv_last = NULL;
Bram Moolenaar758711c2005-02-02 23:11:38 +000012560 l->lv_len = 0;
Bram Moolenaar0d660222005-01-07 21:51:51 +000012561 for (i = 0; i < len; ++i)
12562 list_append(l, ptrs[i]);
12563 }
12564
12565 vim_free(ptrs);
12566 }
12567}
12568
12569 static void
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000012570f_split(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000012571 typval_T *argvars;
12572 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000012573{
12574 char_u *str;
12575 char_u *end;
12576 char_u *pat;
12577 regmatch_T regmatch;
12578 char_u patbuf[NUMBUFLEN];
12579 char_u *save_cpo;
12580 int match;
Bram Moolenaar33570922005-01-25 22:26:29 +000012581 listitem_T *ni;
12582 list_T *l;
Bram Moolenaar0d660222005-01-07 21:51:51 +000012583 colnr_T col = 0;
12584
12585 /* Make 'cpoptions' empty, the 'l' flag should not be used here. */
12586 save_cpo = p_cpo;
12587 p_cpo = (char_u *)"";
12588
12589 str = get_tv_string(&argvars[0]);
12590 if (argvars[1].v_type == VAR_UNKNOWN)
12591 pat = (char_u *)"[\\x01- ]\\+";
12592 else
12593 pat = get_tv_string_buf(&argvars[1], patbuf);
12594
12595 l = list_alloc();
12596 if (l == NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000012597 return;
Bram Moolenaar0d660222005-01-07 21:51:51 +000012598 rettv->v_type = VAR_LIST;
12599 rettv->vval.v_list = l;
12600 ++l->lv_refcount;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012601
Bram Moolenaar0d660222005-01-07 21:51:51 +000012602 regmatch.regprog = vim_regcomp(pat, RE_MAGIC + RE_STRING);
12603 if (regmatch.regprog != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000012604 {
Bram Moolenaar0d660222005-01-07 21:51:51 +000012605 regmatch.rm_ic = FALSE;
12606 while (*str != NUL)
12607 {
12608 match = vim_regexec_nl(&regmatch, str, col);
12609 if (match)
12610 end = regmatch.startp[0];
12611 else
12612 end = str + STRLEN(str);
12613 if (end > str)
12614 {
12615 ni = listitem_alloc();
12616 if (ni == NULL)
12617 break;
12618 ni->li_tv.v_type = VAR_STRING;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000012619 ni->li_tv.v_lock = 0;
Bram Moolenaar0d660222005-01-07 21:51:51 +000012620 ni->li_tv.vval.v_string = vim_strnsave(str, end - str);
12621 list_append(l, ni);
12622 }
12623 if (!match)
12624 break;
12625 /* Advance to just after the match. */
12626 if (regmatch.endp[0] > str)
12627 col = 0;
12628 else
12629 {
12630 /* Don't get stuck at the same match. */
12631#ifdef FEAT_MBYTE
12632 col = mb_ptr2len_check(regmatch.endp[0]);
12633#else
12634 col = 1;
12635#endif
12636 }
12637 str = regmatch.endp[0];
12638 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000012639
Bram Moolenaar0d660222005-01-07 21:51:51 +000012640 vim_free(regmatch.regprog);
Bram Moolenaar071d4272004-06-13 20:20:40 +000012641 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000012642
Bram Moolenaar0d660222005-01-07 21:51:51 +000012643 p_cpo = save_cpo;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012644}
12645
12646#ifdef HAVE_STRFTIME
12647/*
12648 * "strftime({format}[, {time}])" function
12649 */
12650 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012651f_strftime(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000012652 typval_T *argvars;
12653 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012654{
12655 char_u result_buf[256];
12656 struct tm *curtime;
12657 time_t seconds;
12658 char_u *p;
12659
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012660 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012661
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012662 p = get_tv_string(&argvars[0]);
Bram Moolenaar49cd9572005-01-03 21:06:01 +000012663 if (argvars[1].v_type == VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +000012664 seconds = time(NULL);
12665 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012666 seconds = (time_t)get_tv_number(&argvars[1]);
Bram Moolenaar071d4272004-06-13 20:20:40 +000012667 curtime = localtime(&seconds);
12668 /* MSVC returns NULL for an invalid value of seconds. */
12669 if (curtime == NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012670 rettv->vval.v_string = vim_strsave((char_u *)_("(Invalid)"));
Bram Moolenaar071d4272004-06-13 20:20:40 +000012671 else
12672 {
12673# ifdef FEAT_MBYTE
12674 vimconv_T conv;
12675 char_u *enc;
12676
12677 conv.vc_type = CONV_NONE;
12678 enc = enc_locale();
12679 convert_setup(&conv, p_enc, enc);
12680 if (conv.vc_type != CONV_NONE)
12681 p = string_convert(&conv, p, NULL);
12682# endif
12683 if (p != NULL)
12684 (void)strftime((char *)result_buf, sizeof(result_buf),
12685 (char *)p, curtime);
12686 else
12687 result_buf[0] = NUL;
12688
12689# ifdef FEAT_MBYTE
12690 if (conv.vc_type != CONV_NONE)
12691 vim_free(p);
12692 convert_setup(&conv, enc, p_enc);
12693 if (conv.vc_type != CONV_NONE)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012694 rettv->vval.v_string = string_convert(&conv, result_buf, NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +000012695 else
12696# endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012697 rettv->vval.v_string = vim_strsave(result_buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +000012698
12699# ifdef FEAT_MBYTE
12700 /* Release conversion descriptors */
12701 convert_setup(&conv, NULL, NULL);
12702 vim_free(enc);
12703# endif
12704 }
12705}
12706#endif
12707
12708/*
12709 * "stridx()" function
12710 */
12711 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012712f_stridx(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000012713 typval_T *argvars;
12714 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012715{
12716 char_u buf[NUMBUFLEN];
12717 char_u *needle;
12718 char_u *haystack;
Bram Moolenaar33570922005-01-25 22:26:29 +000012719 char_u *save_haystack;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012720 char_u *pos;
Bram Moolenaar33570922005-01-25 22:26:29 +000012721 int start_idx;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012722
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012723 needle = get_tv_string(&argvars[1]);
Bram Moolenaar33570922005-01-25 22:26:29 +000012724 save_haystack = haystack = get_tv_string_buf(&argvars[0], buf);
12725 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012726
Bram Moolenaar33570922005-01-25 22:26:29 +000012727 if (argvars[2].v_type != VAR_UNKNOWN)
12728 {
12729 start_idx = get_tv_number(&argvars[2]);
Bram Moolenaar532c7802005-01-27 14:44:31 +000012730 if (start_idx >= (int)STRLEN(haystack))
Bram Moolenaar33570922005-01-25 22:26:29 +000012731 return;
Bram Moolenaar532c7802005-01-27 14:44:31 +000012732 if (start_idx >= 0)
12733 haystack += start_idx;
Bram Moolenaar33570922005-01-25 22:26:29 +000012734 }
12735
12736 pos = (char_u *)strstr((char *)haystack, (char *)needle);
12737 if (pos != NULL)
12738 rettv->vval.v_number = (varnumber_T)(pos - save_haystack);
Bram Moolenaar071d4272004-06-13 20:20:40 +000012739}
12740
12741/*
Bram Moolenaar49cd9572005-01-03 21:06:01 +000012742 * "string()" function
12743 */
12744 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012745f_string(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000012746 typval_T *argvars;
12747 typval_T *rettv;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000012748{
12749 char_u *tofree;
Bram Moolenaar8a283e52005-01-06 23:28:25 +000012750 char_u numbuf[NUMBUFLEN];
Bram Moolenaar49cd9572005-01-03 21:06:01 +000012751
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012752 rettv->v_type = VAR_STRING;
Bram Moolenaar8a283e52005-01-06 23:28:25 +000012753 rettv->vval.v_string = tv2string(&argvars[0], &tofree, numbuf);
Bram Moolenaar49cd9572005-01-03 21:06:01 +000012754 if (tofree == NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012755 rettv->vval.v_string = vim_strsave(rettv->vval.v_string);
Bram Moolenaar071d4272004-06-13 20:20:40 +000012756}
12757
12758/*
12759 * "strlen()" function
12760 */
12761 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012762f_strlen(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000012763 typval_T *argvars;
12764 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012765{
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012766 rettv->vval.v_number = (varnumber_T)(STRLEN(
12767 get_tv_string(&argvars[0])));
Bram Moolenaar071d4272004-06-13 20:20:40 +000012768}
12769
12770/*
12771 * "strpart()" function
12772 */
12773 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012774f_strpart(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000012775 typval_T *argvars;
12776 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012777{
12778 char_u *p;
12779 int n;
12780 int len;
12781 int slen;
12782
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012783 p = get_tv_string(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +000012784 slen = (int)STRLEN(p);
12785
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012786 n = get_tv_number(&argvars[1]);
Bram Moolenaar49cd9572005-01-03 21:06:01 +000012787 if (argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012788 len = get_tv_number(&argvars[2]);
Bram Moolenaar071d4272004-06-13 20:20:40 +000012789 else
12790 len = slen - n; /* default len: all bytes that are available. */
12791
12792 /*
12793 * Only return the overlap between the specified part and the actual
12794 * string.
12795 */
12796 if (n < 0)
12797 {
12798 len += n;
12799 n = 0;
12800 }
12801 else if (n > slen)
12802 n = slen;
12803 if (len < 0)
12804 len = 0;
12805 else if (n + len > slen)
12806 len = slen - n;
12807
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012808 rettv->v_type = VAR_STRING;
12809 rettv->vval.v_string = vim_strnsave(p + n, len);
Bram Moolenaar071d4272004-06-13 20:20:40 +000012810}
12811
12812/*
Bram Moolenaar0d660222005-01-07 21:51:51 +000012813 * "strridx()" function
12814 */
12815 static void
12816f_strridx(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000012817 typval_T *argvars;
12818 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000012819{
12820 char_u buf[NUMBUFLEN];
12821 char_u *needle;
12822 char_u *haystack;
12823 char_u *rest;
12824 char_u *lastmatch = NULL;
Bram Moolenaar532c7802005-01-27 14:44:31 +000012825 int haystack_len, end_idx;
Bram Moolenaar0d660222005-01-07 21:51:51 +000012826
12827 needle = get_tv_string(&argvars[1]);
12828 haystack = get_tv_string_buf(&argvars[0], buf);
Bram Moolenaar532c7802005-01-27 14:44:31 +000012829 haystack_len = STRLEN(haystack);
Bram Moolenaar05159a02005-02-26 23:04:13 +000012830 if (argvars[2].v_type != VAR_UNKNOWN)
12831 {
12832 /* Third argument: upper limit for index */
12833 end_idx = get_tv_number(&argvars[2]);
12834 if (end_idx < 0)
12835 {
12836 /* can never find a match */
12837 rettv->vval.v_number = -1;
12838 return;
12839 }
12840 }
12841 else
12842 end_idx = haystack_len;
12843
Bram Moolenaar0d660222005-01-07 21:51:51 +000012844 if (*needle == NUL)
Bram Moolenaar05159a02005-02-26 23:04:13 +000012845 {
Bram Moolenaar0d660222005-01-07 21:51:51 +000012846 /* Empty string matches past the end. */
Bram Moolenaar05159a02005-02-26 23:04:13 +000012847 lastmatch = haystack + end_idx;
12848 }
Bram Moolenaar0d660222005-01-07 21:51:51 +000012849 else
Bram Moolenaar532c7802005-01-27 14:44:31 +000012850 {
Bram Moolenaar0d660222005-01-07 21:51:51 +000012851 for (rest = haystack; *rest != '\0'; ++rest)
12852 {
12853 rest = (char_u *)strstr((char *)rest, (char *)needle);
Bram Moolenaar532c7802005-01-27 14:44:31 +000012854 if (rest == NULL || rest > haystack + end_idx)
Bram Moolenaar0d660222005-01-07 21:51:51 +000012855 break;
12856 lastmatch = rest;
12857 }
Bram Moolenaar532c7802005-01-27 14:44:31 +000012858 }
Bram Moolenaar0d660222005-01-07 21:51:51 +000012859
12860 if (lastmatch == NULL)
12861 rettv->vval.v_number = -1;
12862 else
12863 rettv->vval.v_number = (varnumber_T)(lastmatch - haystack);
12864}
12865
12866/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000012867 * "strtrans()" function
12868 */
12869 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012870f_strtrans(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000012871 typval_T *argvars;
12872 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012873{
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012874 rettv->v_type = VAR_STRING;
12875 rettv->vval.v_string = transstr(get_tv_string(&argvars[0]));
Bram Moolenaar071d4272004-06-13 20:20:40 +000012876}
12877
12878/*
Bram Moolenaar0d660222005-01-07 21:51:51 +000012879 * "submatch()" function
12880 */
12881 static void
12882f_submatch(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000012883 typval_T *argvars;
12884 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000012885{
12886 rettv->v_type = VAR_STRING;
12887 rettv->vval.v_string = reg_submatch((int)get_tv_number(&argvars[0]));
12888}
12889
12890/*
12891 * "substitute()" function
12892 */
12893 static void
12894f_substitute(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000012895 typval_T *argvars;
12896 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000012897{
12898 char_u patbuf[NUMBUFLEN];
12899 char_u subbuf[NUMBUFLEN];
12900 char_u flagsbuf[NUMBUFLEN];
12901
12902 rettv->v_type = VAR_STRING;
12903 rettv->vval.v_string = do_string_sub(
12904 get_tv_string(&argvars[0]),
12905 get_tv_string_buf(&argvars[1], patbuf),
12906 get_tv_string_buf(&argvars[2], subbuf),
12907 get_tv_string_buf(&argvars[3], flagsbuf));
12908}
12909
12910/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000012911 * "synID(line, col, trans)" function
12912 */
12913/*ARGSUSED*/
12914 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012915f_synID(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000012916 typval_T *argvars;
12917 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012918{
12919 int id = 0;
12920#ifdef FEAT_SYN_HL
12921 long line;
12922 long col;
12923 int trans;
12924
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012925 line = get_tv_lnum(argvars);
12926 col = get_tv_number(&argvars[1]) - 1;
12927 trans = get_tv_number(&argvars[2]);
Bram Moolenaar071d4272004-06-13 20:20:40 +000012928
12929 if (line >= 1 && line <= curbuf->b_ml.ml_line_count
12930 && col >= 0 && col < (long)STRLEN(ml_get(line)))
12931 id = syn_get_id(line, col, trans);
12932#endif
12933
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012934 rettv->vval.v_number = id;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012935}
12936
12937/*
12938 * "synIDattr(id, what [, mode])" function
12939 */
12940/*ARGSUSED*/
12941 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012942f_synIDattr(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000012943 typval_T *argvars;
12944 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012945{
12946 char_u *p = NULL;
12947#ifdef FEAT_SYN_HL
12948 int id;
12949 char_u *what;
12950 char_u *mode;
12951 char_u modebuf[NUMBUFLEN];
12952 int modec;
12953
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012954 id = get_tv_number(&argvars[0]);
12955 what = get_tv_string(&argvars[1]);
Bram Moolenaar49cd9572005-01-03 21:06:01 +000012956 if (argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +000012957 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012958 mode = get_tv_string_buf(&argvars[2], modebuf);
Bram Moolenaar071d4272004-06-13 20:20:40 +000012959 modec = TOLOWER_ASC(mode[0]);
12960 if (modec != 't' && modec != 'c'
12961#ifdef FEAT_GUI
12962 && modec != 'g'
12963#endif
12964 )
12965 modec = 0; /* replace invalid with current */
12966 }
12967 else
12968 {
12969#ifdef FEAT_GUI
12970 if (gui.in_use)
12971 modec = 'g';
12972 else
12973#endif
12974 if (t_colors > 1)
12975 modec = 'c';
12976 else
12977 modec = 't';
12978 }
12979
12980
12981 switch (TOLOWER_ASC(what[0]))
12982 {
12983 case 'b':
12984 if (TOLOWER_ASC(what[1]) == 'g') /* bg[#] */
12985 p = highlight_color(id, what, modec);
12986 else /* bold */
12987 p = highlight_has_attr(id, HL_BOLD, modec);
12988 break;
12989
12990 case 'f': /* fg[#] */
12991 p = highlight_color(id, what, modec);
12992 break;
12993
12994 case 'i':
12995 if (TOLOWER_ASC(what[1]) == 'n') /* inverse */
12996 p = highlight_has_attr(id, HL_INVERSE, modec);
12997 else /* italic */
12998 p = highlight_has_attr(id, HL_ITALIC, modec);
12999 break;
13000
13001 case 'n': /* name */
13002 p = get_highlight_name(NULL, id - 1);
13003 break;
13004
13005 case 'r': /* reverse */
13006 p = highlight_has_attr(id, HL_INVERSE, modec);
13007 break;
13008
13009 case 's': /* standout */
13010 p = highlight_has_attr(id, HL_STANDOUT, modec);
13011 break;
13012
13013 case 'u': /* underline */
13014 p = highlight_has_attr(id, HL_UNDERLINE, modec);
13015 break;
13016 }
13017
13018 if (p != NULL)
13019 p = vim_strsave(p);
13020#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013021 rettv->v_type = VAR_STRING;
13022 rettv->vval.v_string = p;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013023}
13024
13025/*
13026 * "synIDtrans(id)" function
13027 */
13028/*ARGSUSED*/
13029 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013030f_synIDtrans(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000013031 typval_T *argvars;
13032 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013033{
13034 int id;
13035
13036#ifdef FEAT_SYN_HL
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013037 id = get_tv_number(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +000013038
13039 if (id > 0)
13040 id = syn_get_final_id(id);
13041 else
13042#endif
13043 id = 0;
13044
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013045 rettv->vval.v_number = id;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013046}
13047
13048/*
13049 * "system()" function
13050 */
13051 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013052f_system(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000013053 typval_T *argvars;
13054 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013055{
Bram Moolenaarc0197e22004-09-13 20:26:32 +000013056 char_u *res = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013057 char_u *p;
Bram Moolenaarc0197e22004-09-13 20:26:32 +000013058 char_u *infile = NULL;
13059 char_u buf[NUMBUFLEN];
13060 int err = FALSE;
13061 FILE *fd;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013062
Bram Moolenaar49cd9572005-01-03 21:06:01 +000013063 if (argvars[1].v_type != VAR_UNKNOWN)
Bram Moolenaarc0197e22004-09-13 20:26:32 +000013064 {
13065 /*
13066 * Write the string to a temp file, to be used for input of the shell
13067 * command.
13068 */
13069 if ((infile = vim_tempname('i')) == NULL)
13070 {
13071 EMSG(_(e_notmp));
13072 return;
13073 }
13074
13075 fd = mch_fopen((char *)infile, WRITEBIN);
13076 if (fd == NULL)
13077 {
13078 EMSG2(_(e_notopen), infile);
13079 goto done;
13080 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013081 p = get_tv_string_buf(&argvars[1], buf);
Bram Moolenaarc0197e22004-09-13 20:26:32 +000013082 if (fwrite(p, STRLEN(p), 1, fd) != 1)
13083 err = TRUE;
13084 if (fclose(fd) != 0)
13085 err = TRUE;
13086 if (err)
13087 {
13088 EMSG(_("E677: Error writing temp file"));
13089 goto done;
13090 }
13091 }
13092
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013093 res = get_cmd_output(get_tv_string(&argvars[0]), infile, SHELL_SILENT);
Bram Moolenaarc0197e22004-09-13 20:26:32 +000013094
Bram Moolenaar071d4272004-06-13 20:20:40 +000013095#ifdef USE_CR
13096 /* translate <CR> into <NL> */
Bram Moolenaarc0197e22004-09-13 20:26:32 +000013097 if (res != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000013098 {
13099 char_u *s;
13100
Bram Moolenaarc0197e22004-09-13 20:26:32 +000013101 for (s = res; *s; ++s)
Bram Moolenaar071d4272004-06-13 20:20:40 +000013102 {
13103 if (*s == CAR)
13104 *s = NL;
13105 }
13106 }
13107#else
13108# ifdef USE_CRNL
13109 /* translate <CR><NL> into <NL> */
Bram Moolenaarc0197e22004-09-13 20:26:32 +000013110 if (res != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000013111 {
13112 char_u *s, *d;
13113
Bram Moolenaarc0197e22004-09-13 20:26:32 +000013114 d = res;
13115 for (s = res; *s; ++s)
Bram Moolenaar071d4272004-06-13 20:20:40 +000013116 {
13117 if (s[0] == CAR && s[1] == NL)
13118 ++s;
13119 *d++ = *s;
13120 }
13121 *d = NUL;
13122 }
13123# endif
13124#endif
Bram Moolenaarc0197e22004-09-13 20:26:32 +000013125
13126done:
13127 if (infile != NULL)
13128 {
13129 mch_remove(infile);
13130 vim_free(infile);
13131 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013132 rettv->v_type = VAR_STRING;
13133 rettv->vval.v_string = res;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013134}
13135
13136/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000013137 * "tempname()" function
13138 */
13139/*ARGSUSED*/
13140 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013141f_tempname(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000013142 typval_T *argvars;
13143 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013144{
13145 static int x = 'A';
13146
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013147 rettv->v_type = VAR_STRING;
13148 rettv->vval.v_string = vim_tempname(x);
Bram Moolenaar071d4272004-06-13 20:20:40 +000013149
13150 /* Advance 'x' to use A-Z and 0-9, so that there are at least 34 different
13151 * names. Skip 'I' and 'O', they are used for shell redirection. */
13152 do
13153 {
13154 if (x == 'Z')
13155 x = '0';
13156 else if (x == '9')
13157 x = 'A';
13158 else
13159 {
13160#ifdef EBCDIC
13161 if (x == 'I')
13162 x = 'J';
13163 else if (x == 'R')
13164 x = 'S';
13165 else
13166#endif
13167 ++x;
13168 }
13169 } while (x == 'I' || x == 'O');
13170}
13171
13172/*
13173 * "tolower(string)" function
13174 */
13175 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013176f_tolower(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000013177 typval_T *argvars;
13178 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013179{
13180 char_u *p;
13181
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013182 p = vim_strsave(get_tv_string(&argvars[0]));
13183 rettv->v_type = VAR_STRING;
13184 rettv->vval.v_string = p;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013185
13186 if (p != NULL)
13187 while (*p != NUL)
13188 {
13189#ifdef FEAT_MBYTE
13190 int l;
13191
13192 if (enc_utf8)
13193 {
13194 int c, lc;
13195
13196 c = utf_ptr2char(p);
13197 lc = utf_tolower(c);
13198 l = utf_ptr2len_check(p);
13199 /* TODO: reallocate string when byte count changes. */
13200 if (utf_char2len(lc) == l)
13201 utf_char2bytes(lc, p);
13202 p += l;
13203 }
13204 else if (has_mbyte && (l = (*mb_ptr2len_check)(p)) > 1)
13205 p += l; /* skip multi-byte character */
13206 else
13207#endif
13208 {
13209 *p = TOLOWER_LOC(*p); /* note that tolower() can be a macro */
13210 ++p;
13211 }
13212 }
13213}
13214
13215/*
13216 * "toupper(string)" function
13217 */
13218 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013219f_toupper(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000013220 typval_T *argvars;
13221 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013222{
13223 char_u *p;
13224
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013225 p = vim_strsave(get_tv_string(&argvars[0]));
13226 rettv->v_type = VAR_STRING;
13227 rettv->vval.v_string = p;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013228
13229 if (p != NULL)
13230 while (*p != NUL)
13231 {
13232#ifdef FEAT_MBYTE
13233 int l;
13234
13235 if (enc_utf8)
13236 {
13237 int c, uc;
13238
13239 c = utf_ptr2char(p);
13240 uc = utf_toupper(c);
13241 l = utf_ptr2len_check(p);
13242 /* TODO: reallocate string when byte count changes. */
13243 if (utf_char2len(uc) == l)
13244 utf_char2bytes(uc, p);
13245 p += l;
13246 }
13247 else if (has_mbyte && (l = (*mb_ptr2len_check)(p)) > 1)
13248 p += l; /* skip multi-byte character */
13249 else
13250#endif
13251 {
13252 *p = TOUPPER_LOC(*p); /* note that toupper() can be a macro */
13253 p++;
13254 }
13255 }
13256}
13257
13258/*
Bram Moolenaar8299df92004-07-10 09:47:34 +000013259 * "tr(string, fromstr, tostr)" function
13260 */
13261 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013262f_tr(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000013263 typval_T *argvars;
13264 typval_T *rettv;
Bram Moolenaar8299df92004-07-10 09:47:34 +000013265{
13266 char_u *instr;
13267 char_u *fromstr;
13268 char_u *tostr;
13269 char_u *p;
13270#ifdef FEAT_MBYTE
13271 int inlen;
13272 int fromlen;
13273 int tolen;
13274 int idx;
13275 char_u *cpstr;
13276 int cplen;
13277 int first = TRUE;
13278#endif
13279 char_u buf[NUMBUFLEN];
13280 char_u buf2[NUMBUFLEN];
13281 garray_T ga;
13282
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013283 instr = get_tv_string(&argvars[0]);
13284 fromstr = get_tv_string_buf(&argvars[1], buf);
13285 tostr = get_tv_string_buf(&argvars[2], buf2);
Bram Moolenaar8299df92004-07-10 09:47:34 +000013286
13287 /* Default return value: empty string. */
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013288 rettv->v_type = VAR_STRING;
13289 rettv->vval.v_string = NULL;
Bram Moolenaar8299df92004-07-10 09:47:34 +000013290 ga_init2(&ga, (int)sizeof(char), 80);
13291
13292#ifdef FEAT_MBYTE
13293 if (!has_mbyte)
13294#endif
13295 /* not multi-byte: fromstr and tostr must be the same length */
13296 if (STRLEN(fromstr) != STRLEN(tostr))
13297 {
Bram Moolenaar5eb86f92004-07-26 12:53:41 +000013298#ifdef FEAT_MBYTE
Bram Moolenaar8299df92004-07-10 09:47:34 +000013299error:
Bram Moolenaar5eb86f92004-07-26 12:53:41 +000013300#endif
Bram Moolenaar8299df92004-07-10 09:47:34 +000013301 EMSG2(_(e_invarg2), fromstr);
13302 ga_clear(&ga);
13303 return;
13304 }
13305
13306 /* fromstr and tostr have to contain the same number of chars */
13307 while (*instr != NUL)
13308 {
13309#ifdef FEAT_MBYTE
13310 if (has_mbyte)
13311 {
13312 inlen = mb_ptr2len_check(instr);
13313 cpstr = instr;
13314 cplen = inlen;
13315 idx = 0;
13316 for (p = fromstr; *p != NUL; p += fromlen)
13317 {
13318 fromlen = mb_ptr2len_check(p);
13319 if (fromlen == inlen && STRNCMP(instr, p, inlen) == 0)
13320 {
13321 for (p = tostr; *p != NUL; p += tolen)
13322 {
13323 tolen = mb_ptr2len_check(p);
13324 if (idx-- == 0)
13325 {
13326 cplen = tolen;
13327 cpstr = p;
13328 break;
13329 }
13330 }
13331 if (*p == NUL) /* tostr is shorter than fromstr */
13332 goto error;
13333 break;
13334 }
13335 ++idx;
13336 }
13337
13338 if (first && cpstr == instr)
13339 {
13340 /* Check that fromstr and tostr have the same number of
13341 * (multi-byte) characters. Done only once when a character
13342 * of instr doesn't appear in fromstr. */
13343 first = FALSE;
13344 for (p = tostr; *p != NUL; p += tolen)
13345 {
13346 tolen = mb_ptr2len_check(p);
13347 --idx;
13348 }
13349 if (idx != 0)
13350 goto error;
13351 }
13352
13353 ga_grow(&ga, cplen);
Bram Moolenaar2df6dcc2004-07-12 15:53:54 +000013354 mch_memmove((char *)ga.ga_data + ga.ga_len, cpstr, (size_t)cplen);
Bram Moolenaar8299df92004-07-10 09:47:34 +000013355 ga.ga_len += cplen;
Bram Moolenaar8299df92004-07-10 09:47:34 +000013356
13357 instr += inlen;
13358 }
13359 else
13360#endif
13361 {
13362 /* When not using multi-byte chars we can do it faster. */
13363 p = vim_strchr(fromstr, *instr);
13364 if (p != NULL)
13365 ga_append(&ga, tostr[p - fromstr]);
13366 else
13367 ga_append(&ga, *instr);
13368 ++instr;
13369 }
13370 }
13371
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013372 rettv->vval.v_string = ga.ga_data;
Bram Moolenaar8299df92004-07-10 09:47:34 +000013373}
13374
13375/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000013376 * "type(expr)" function
13377 */
13378 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013379f_type(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000013380 typval_T *argvars;
13381 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013382{
Bram Moolenaar6cc16192005-01-08 21:49:45 +000013383 int n;
13384
13385 switch (argvars[0].v_type)
13386 {
13387 case VAR_NUMBER: n = 0; break;
13388 case VAR_STRING: n = 1; break;
13389 case VAR_FUNC: n = 2; break;
13390 case VAR_LIST: n = 3; break;
Bram Moolenaar758711c2005-02-02 23:11:38 +000013391 case VAR_DICT: n = 4; break;
Bram Moolenaar6cc16192005-01-08 21:49:45 +000013392 default: EMSG2(_(e_intern2), "f_type()"); n = 0; break;
13393 }
13394 rettv->vval.v_number = n;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013395}
13396
13397/*
Bram Moolenaar8c711452005-01-14 21:53:12 +000013398 * "values(dict)" function
13399 */
13400 static void
13401f_values(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000013402 typval_T *argvars;
13403 typval_T *rettv;
Bram Moolenaar8c711452005-01-14 21:53:12 +000013404{
13405 dict_list(argvars, rettv, 1);
13406}
13407
13408/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000013409 * "virtcol(string)" function
13410 */
13411 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013412f_virtcol(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000013413 typval_T *argvars;
13414 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013415{
13416 colnr_T vcol = 0;
13417 pos_T *fp;
13418
13419 fp = var2fpos(&argvars[0], FALSE);
13420 if (fp != NULL && fp->lnum <= curbuf->b_ml.ml_line_count)
13421 {
13422 getvvcol(curwin, fp, NULL, NULL, &vcol);
13423 ++vcol;
13424 }
13425
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013426 rettv->vval.v_number = vcol;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013427}
13428
13429/*
13430 * "visualmode()" function
13431 */
13432/*ARGSUSED*/
13433 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013434f_visualmode(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000013435 typval_T *argvars;
13436 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013437{
13438#ifdef FEAT_VISUAL
13439 char_u str[2];
13440
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013441 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013442 str[0] = curbuf->b_visual_mode_eval;
13443 str[1] = NUL;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013444 rettv->vval.v_string = vim_strsave(str);
Bram Moolenaar071d4272004-06-13 20:20:40 +000013445
13446 /* A non-zero number or non-empty string argument: reset mode. */
Bram Moolenaar49cd9572005-01-03 21:06:01 +000013447 if ((argvars[0].v_type == VAR_NUMBER
13448 && argvars[0].vval.v_number != 0)
13449 || (argvars[0].v_type == VAR_STRING
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013450 && *get_tv_string(&argvars[0]) != NUL))
Bram Moolenaar071d4272004-06-13 20:20:40 +000013451 curbuf->b_visual_mode_eval = NUL;
13452#else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013453 rettv->vval.v_number = 0; /* return anything, it won't work anyway */
Bram Moolenaar071d4272004-06-13 20:20:40 +000013454#endif
13455}
13456
13457/*
13458 * "winbufnr(nr)" function
13459 */
13460 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013461f_winbufnr(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000013462 typval_T *argvars;
13463 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013464{
13465 win_T *wp;
13466
13467 wp = find_win_by_nr(&argvars[0]);
13468 if (wp == NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013469 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013470 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013471 rettv->vval.v_number = wp->w_buffer->b_fnum;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013472}
13473
13474/*
13475 * "wincol()" function
13476 */
13477/*ARGSUSED*/
13478 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013479f_wincol(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000013480 typval_T *argvars;
13481 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013482{
13483 validate_cursor();
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013484 rettv->vval.v_number = curwin->w_wcol + 1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013485}
13486
13487/*
13488 * "winheight(nr)" function
13489 */
13490 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013491f_winheight(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000013492 typval_T *argvars;
13493 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013494{
13495 win_T *wp;
13496
13497 wp = find_win_by_nr(&argvars[0]);
13498 if (wp == NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013499 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013500 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013501 rettv->vval.v_number = wp->w_height;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013502}
13503
13504/*
13505 * "winline()" function
13506 */
13507/*ARGSUSED*/
13508 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013509f_winline(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000013510 typval_T *argvars;
13511 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013512{
13513 validate_cursor();
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013514 rettv->vval.v_number = curwin->w_wrow + 1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013515}
13516
13517/*
13518 * "winnr()" function
13519 */
13520/* ARGSUSED */
13521 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013522f_winnr(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000013523 typval_T *argvars;
13524 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013525{
13526 int nr = 1;
13527#ifdef FEAT_WINDOWS
13528 win_T *wp;
Bram Moolenaar5eb86f92004-07-26 12:53:41 +000013529 win_T *twin = curwin;
13530 char_u *arg;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013531
Bram Moolenaar49cd9572005-01-03 21:06:01 +000013532 if (argvars[0].v_type != VAR_UNKNOWN)
Bram Moolenaar5eb86f92004-07-26 12:53:41 +000013533 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013534 arg = get_tv_string(&argvars[0]);
Bram Moolenaar5eb86f92004-07-26 12:53:41 +000013535 if (STRCMP(arg, "$") == 0)
13536 twin = lastwin;
13537 else if (STRCMP(arg, "#") == 0)
13538 {
13539 twin = prevwin;
13540 if (prevwin == NULL)
13541 nr = 0;
13542 }
13543 else
13544 {
13545 EMSG2(_(e_invexpr2), arg);
13546 nr = 0;
13547 }
13548 }
13549
13550 if (nr > 0)
13551 for (wp = firstwin; wp != twin; wp = wp->w_next)
13552 ++nr;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013553#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013554 rettv->vval.v_number = nr;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013555}
13556
13557/*
13558 * "winrestcmd()" function
13559 */
13560/* ARGSUSED */
13561 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013562f_winrestcmd(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000013563 typval_T *argvars;
13564 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013565{
13566#ifdef FEAT_WINDOWS
13567 win_T *wp;
13568 int winnr = 1;
13569 garray_T ga;
13570 char_u buf[50];
13571
13572 ga_init2(&ga, (int)sizeof(char), 70);
13573 for (wp = firstwin; wp != NULL; wp = wp->w_next)
13574 {
13575 sprintf((char *)buf, "%dresize %d|", winnr, wp->w_height);
13576 ga_concat(&ga, buf);
13577# ifdef FEAT_VERTSPLIT
13578 sprintf((char *)buf, "vert %dresize %d|", winnr, wp->w_width);
13579 ga_concat(&ga, buf);
13580# endif
13581 ++winnr;
13582 }
Bram Moolenaar269ec652004-07-29 08:43:53 +000013583 ga_append(&ga, NUL);
Bram Moolenaar071d4272004-06-13 20:20:40 +000013584
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013585 rettv->vval.v_string = ga.ga_data;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013586#else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013587 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013588#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013589 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013590}
13591
13592/*
13593 * "winwidth(nr)" function
13594 */
13595 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013596f_winwidth(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000013597 typval_T *argvars;
13598 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013599{
13600 win_T *wp;
13601
13602 wp = find_win_by_nr(&argvars[0]);
13603 if (wp == NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013604 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013605 else
13606#ifdef FEAT_VERTSPLIT
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013607 rettv->vval.v_number = wp->w_width;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013608#else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013609 rettv->vval.v_number = Columns;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013610#endif
13611}
13612
13613 static win_T *
13614find_win_by_nr(vp)
Bram Moolenaar33570922005-01-25 22:26:29 +000013615 typval_T *vp;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013616{
13617#ifdef FEAT_WINDOWS
13618 win_T *wp;
13619#endif
13620 int nr;
13621
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013622 nr = get_tv_number(vp);
Bram Moolenaar071d4272004-06-13 20:20:40 +000013623
13624#ifdef FEAT_WINDOWS
13625 if (nr == 0)
13626 return curwin;
13627
13628 for (wp = firstwin; wp != NULL; wp = wp->w_next)
13629 if (--nr <= 0)
13630 break;
13631 return wp;
13632#else
13633 if (nr == 0 || nr == 1)
13634 return curwin;
13635 return NULL;
13636#endif
13637}
13638
13639/*
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000013640 * "writefile()" function
13641 */
13642 static void
13643f_writefile(argvars, rettv)
13644 typval_T *argvars;
13645 typval_T *rettv;
13646{
13647 int binary = FALSE;
13648 char_u *fname;
13649 FILE *fd;
13650 listitem_T *li;
13651 char_u *s;
13652 int ret = 0;
13653 int c;
13654
13655 if (argvars[0].v_type != VAR_LIST)
13656 {
13657 EMSG2(_(e_listarg), "writefile()");
13658 return;
13659 }
13660 if (argvars[0].vval.v_list == NULL)
13661 return;
13662
13663 if (argvars[2].v_type != VAR_UNKNOWN
13664 && STRCMP(get_tv_string(&argvars[2]), "b") == 0)
13665 binary = TRUE;
13666
13667 /* Always open the file in binary mode, library functions have a mind of
13668 * their own about CR-LF conversion. */
13669 fname = get_tv_string(&argvars[1]);
13670 if (*fname == NUL || (fd = mch_fopen((char *)fname, WRITEBIN)) == NULL)
13671 {
13672 EMSG2(_(e_notcreate), *fname == NUL ? (char_u *)_("<empty>") : fname);
13673 ret = -1;
13674 }
13675 else
13676 {
13677 for (li = argvars[0].vval.v_list->lv_first; li != NULL;
13678 li = li->li_next)
13679 {
13680 for (s = get_tv_string(&li->li_tv); *s != NUL; ++s)
13681 {
13682 if (*s == '\n')
13683 c = putc(NUL, fd);
13684 else
13685 c = putc(*s, fd);
13686 if (c == EOF)
13687 {
13688 ret = -1;
13689 break;
13690 }
13691 }
13692 if (!binary || li->li_next != NULL)
13693 if (putc('\n', fd) == EOF)
13694 {
13695 ret = -1;
13696 break;
13697 }
13698 if (ret < 0)
13699 {
13700 EMSG(_(e_write));
13701 break;
13702 }
13703 }
13704 fclose(fd);
13705 }
13706
13707 rettv->vval.v_number = ret;
13708}
13709
13710/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000013711 * Translate a String variable into a position.
13712 */
13713 static pos_T *
13714var2fpos(varp, lnum)
Bram Moolenaar33570922005-01-25 22:26:29 +000013715 typval_T *varp;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013716 int lnum; /* TRUE when $ is last line */
13717{
13718 char_u *name;
13719 static pos_T pos;
13720 pos_T *pp;
13721
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013722 name = get_tv_string(varp);
Bram Moolenaar071d4272004-06-13 20:20:40 +000013723 if (name[0] == '.') /* cursor */
13724 return &curwin->w_cursor;
13725 if (name[0] == '\'') /* mark */
13726 {
13727 pp = getmark(name[1], FALSE);
13728 if (pp == NULL || pp == (pos_T *)-1 || pp->lnum <= 0)
13729 return NULL;
13730 return pp;
13731 }
13732 if (name[0] == '$') /* last column or line */
13733 {
13734 if (lnum)
13735 {
13736 pos.lnum = curbuf->b_ml.ml_line_count;
13737 pos.col = 0;
13738 }
13739 else
13740 {
13741 pos.lnum = curwin->w_cursor.lnum;
13742 pos.col = (colnr_T)STRLEN(ml_get_curline());
13743 }
13744 return &pos;
13745 }
13746 return NULL;
13747}
13748
13749/*
13750 * Get the length of an environment variable name.
13751 * Advance "arg" to the first character after the name.
13752 * Return 0 for error.
13753 */
13754 static int
13755get_env_len(arg)
13756 char_u **arg;
13757{
13758 char_u *p;
13759 int len;
13760
13761 for (p = *arg; vim_isIDc(*p); ++p)
13762 ;
13763 if (p == *arg) /* no name found */
13764 return 0;
13765
13766 len = (int)(p - *arg);
13767 *arg = p;
13768 return len;
13769}
13770
13771/*
13772 * Get the length of the name of a function or internal variable.
13773 * "arg" is advanced to the first non-white character after the name.
13774 * Return 0 if something is wrong.
13775 */
13776 static int
13777get_id_len(arg)
13778 char_u **arg;
13779{
13780 char_u *p;
13781 int len;
13782
13783 /* Find the end of the name. */
13784 for (p = *arg; eval_isnamec(*p); ++p)
13785 ;
13786 if (p == *arg) /* no name found */
13787 return 0;
13788
13789 len = (int)(p - *arg);
13790 *arg = skipwhite(p);
13791
13792 return len;
13793}
13794
13795/*
Bram Moolenaara7043832005-01-21 11:56:39 +000013796 * Get the length of the name of a variable or function.
13797 * Only the name is recognized, does not handle ".key" or "[idx]".
Bram Moolenaar071d4272004-06-13 20:20:40 +000013798 * "arg" is advanced to the first non-white character after the name.
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000013799 * Return -1 if curly braces expansion failed.
13800 * Return 0 if something else is wrong.
Bram Moolenaar071d4272004-06-13 20:20:40 +000013801 * If the name contains 'magic' {}'s, expand them and return the
13802 * expanded name in an allocated string via 'alias' - caller must free.
13803 */
13804 static int
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000013805get_name_len(arg, alias, evaluate, verbose)
Bram Moolenaar071d4272004-06-13 20:20:40 +000013806 char_u **arg;
13807 char_u **alias;
13808 int evaluate;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000013809 int verbose;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013810{
13811 int len;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013812 char_u *p;
13813 char_u *expr_start;
13814 char_u *expr_end;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013815
13816 *alias = NULL; /* default to no alias */
13817
13818 if ((*arg)[0] == K_SPECIAL && (*arg)[1] == KS_EXTRA
13819 && (*arg)[2] == (int)KE_SNR)
13820 {
13821 /* hard coded <SNR>, already translated */
13822 *arg += 3;
13823 return get_id_len(arg) + 3;
13824 }
13825 len = eval_fname_script(*arg);
13826 if (len > 0)
13827 {
13828 /* literal "<SID>", "s:" or "<SNR>" */
13829 *arg += len;
13830 }
13831
Bram Moolenaar071d4272004-06-13 20:20:40 +000013832 /*
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013833 * Find the end of the name; check for {} construction.
Bram Moolenaar071d4272004-06-13 20:20:40 +000013834 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013835 p = find_name_end(*arg, &expr_start, &expr_end, FALSE);
Bram Moolenaar071d4272004-06-13 20:20:40 +000013836 if (expr_start != NULL)
13837 {
13838 char_u *temp_string;
13839
13840 if (!evaluate)
13841 {
13842 len += (int)(p - *arg);
13843 *arg = skipwhite(p);
13844 return len;
13845 }
13846
13847 /*
13848 * Include any <SID> etc in the expanded string:
13849 * Thus the -len here.
13850 */
13851 temp_string = make_expanded_name(*arg - len, expr_start, expr_end, p);
13852 if (temp_string == NULL)
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000013853 return -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013854 *alias = temp_string;
13855 *arg = skipwhite(p);
13856 return (int)STRLEN(temp_string);
13857 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000013858
13859 len += get_id_len(arg);
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000013860 if (len == 0 && verbose)
Bram Moolenaar071d4272004-06-13 20:20:40 +000013861 EMSG2(_(e_invexpr2), *arg);
13862
13863 return len;
13864}
13865
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013866/*
13867 * Find the end of a variable or function name, taking care of magic braces.
13868 * If "expr_start" is not NULL then "expr_start" and "expr_end" are set to the
13869 * start and end of the first magic braces item.
13870 * Return a pointer to just after the name. Equal to "arg" if there is no
13871 * valid name.
13872 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000013873 static char_u *
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013874find_name_end(arg, expr_start, expr_end, incl_br)
Bram Moolenaar071d4272004-06-13 20:20:40 +000013875 char_u *arg;
13876 char_u **expr_start;
13877 char_u **expr_end;
Bram Moolenaar8c711452005-01-14 21:53:12 +000013878 int incl_br; /* Include [] indexes and .name */
Bram Moolenaar071d4272004-06-13 20:20:40 +000013879{
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013880 int mb_nest = 0;
13881 int br_nest = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013882 char_u *p;
13883
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013884 if (expr_start != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000013885 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013886 *expr_start = NULL;
13887 *expr_end = NULL;
13888 }
13889
13890 for (p = arg; *p != NUL
13891 && (eval_isnamec(*p)
Bram Moolenaare9a41262005-01-15 22:18:47 +000013892 || *p == '{'
Bram Moolenaar8c711452005-01-14 21:53:12 +000013893 || (incl_br && (*p == '[' || *p == '.'))
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013894 || mb_nest != 0
13895 || br_nest != 0); ++p)
13896 {
13897 if (mb_nest == 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +000013898 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013899 if (*p == '[')
13900 ++br_nest;
13901 else if (*p == ']')
13902 --br_nest;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013903 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013904 if (br_nest == 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +000013905 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013906 if (*p == '{')
13907 {
13908 mb_nest++;
13909 if (expr_start != NULL && *expr_start == NULL)
13910 *expr_start = p;
13911 }
13912 else if (*p == '}')
13913 {
13914 mb_nest--;
13915 if (expr_start != NULL && mb_nest == 0 && *expr_end == NULL)
13916 *expr_end = p;
13917 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000013918 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000013919 }
13920
13921 return p;
13922}
13923
13924/*
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000013925 * Expands out the 'magic' {}'s in a variable/function name.
13926 * Note that this can call itself recursively, to deal with
13927 * constructs like foo{bar}{baz}{bam}
13928 * The four pointer arguments point to "foo{expre}ss{ion}bar"
13929 * "in_start" ^
13930 * "expr_start" ^
13931 * "expr_end" ^
13932 * "in_end" ^
13933 *
13934 * Returns a new allocated string, which the caller must free.
13935 * Returns NULL for failure.
13936 */
13937 static char_u *
13938make_expanded_name(in_start, expr_start, expr_end, in_end)
13939 char_u *in_start;
13940 char_u *expr_start;
13941 char_u *expr_end;
13942 char_u *in_end;
13943{
13944 char_u c1;
13945 char_u *retval = NULL;
13946 char_u *temp_result;
13947 char_u *nextcmd = NULL;
13948
13949 if (expr_end == NULL || in_end == NULL)
13950 return NULL;
13951 *expr_start = NUL;
13952 *expr_end = NUL;
13953 c1 = *in_end;
13954 *in_end = NUL;
13955
13956 temp_result = eval_to_string(expr_start + 1, &nextcmd);
13957 if (temp_result != NULL && nextcmd == NULL)
13958 {
13959 retval = alloc((unsigned)(STRLEN(temp_result) + (expr_start - in_start)
13960 + (in_end - expr_end) + 1));
13961 if (retval != NULL)
13962 {
13963 STRCPY(retval, in_start);
13964 STRCAT(retval, temp_result);
13965 STRCAT(retval, expr_end + 1);
13966 }
13967 }
13968 vim_free(temp_result);
13969
13970 *in_end = c1; /* put char back for error messages */
13971 *expr_start = '{';
13972 *expr_end = '}';
13973
13974 if (retval != NULL)
13975 {
13976 temp_result = find_name_end(retval, &expr_start, &expr_end, FALSE);
13977 if (expr_start != NULL)
13978 {
13979 /* Further expansion! */
13980 temp_result = make_expanded_name(retval, expr_start,
13981 expr_end, temp_result);
13982 vim_free(retval);
13983 retval = temp_result;
13984 }
13985 }
13986
13987 return retval;
13988}
13989
13990/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000013991 * Return TRUE if character "c" can be used in a variable or function name.
Bram Moolenaare9a41262005-01-15 22:18:47 +000013992 * Does not include '{' or '}' for magic braces.
Bram Moolenaar071d4272004-06-13 20:20:40 +000013993 */
13994 static int
13995eval_isnamec(c)
13996 int c;
13997{
Bram Moolenaare9a41262005-01-15 22:18:47 +000013998 return (ASCII_ISALNUM(c) || c == '_' || c == ':');
Bram Moolenaar071d4272004-06-13 20:20:40 +000013999}
14000
14001/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000014002 * Set number v: variable to "val".
14003 */
14004 void
14005set_vim_var_nr(idx, val)
14006 int idx;
14007 long val;
14008{
Bram Moolenaare9a41262005-01-15 22:18:47 +000014009 vimvars[idx].vv_nr = val;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014010}
14011
14012/*
14013 * Get number v: variable value;
14014 */
14015 long
14016get_vim_var_nr(idx)
14017 int idx;
14018{
Bram Moolenaare9a41262005-01-15 22:18:47 +000014019 return vimvars[idx].vv_nr;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014020}
14021
14022/*
14023 * Set v:count, v:count1 and v:prevcount.
14024 */
14025 void
14026set_vcount(count, count1)
14027 long count;
14028 long count1;
14029{
Bram Moolenaare9a41262005-01-15 22:18:47 +000014030 vimvars[VV_PREVCOUNT].vv_nr = vimvars[VV_COUNT].vv_nr;
14031 vimvars[VV_COUNT].vv_nr = count;
14032 vimvars[VV_COUNT1].vv_nr = count1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014033}
14034
14035/*
14036 * Set string v: variable to a copy of "val".
14037 */
14038 void
14039set_vim_var_string(idx, val, len)
14040 int idx;
14041 char_u *val;
14042 int len; /* length of "val" to use or -1 (whole string) */
14043{
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000014044 /* Need to do this (at least) once, since we can't initialize a union.
14045 * Will always be invoked when "v:progname" is set. */
14046 vimvars[VV_VERSION].vv_nr = VIM_VERSION_100;
14047
Bram Moolenaare9a41262005-01-15 22:18:47 +000014048 vim_free(vimvars[idx].vv_str);
Bram Moolenaar071d4272004-06-13 20:20:40 +000014049 if (val == NULL)
Bram Moolenaare9a41262005-01-15 22:18:47 +000014050 vimvars[idx].vv_str = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014051 else if (len == -1)
Bram Moolenaare9a41262005-01-15 22:18:47 +000014052 vimvars[idx].vv_str = vim_strsave(val);
Bram Moolenaar071d4272004-06-13 20:20:40 +000014053 else
Bram Moolenaare9a41262005-01-15 22:18:47 +000014054 vimvars[idx].vv_str = vim_strnsave(val, len);
Bram Moolenaar071d4272004-06-13 20:20:40 +000014055}
14056
14057/*
14058 * Set v:register if needed.
14059 */
14060 void
14061set_reg_var(c)
14062 int c;
14063{
14064 char_u regname;
14065
14066 if (c == 0 || c == ' ')
14067 regname = '"';
14068 else
14069 regname = c;
14070 /* Avoid free/alloc when the value is already right. */
Bram Moolenaare9a41262005-01-15 22:18:47 +000014071 if (vimvars[VV_REG].vv_str == NULL || vimvars[VV_REG].vv_str[0] != c)
Bram Moolenaar071d4272004-06-13 20:20:40 +000014072 set_vim_var_string(VV_REG, &regname, 1);
14073}
14074
14075/*
14076 * Get or set v:exception. If "oldval" == NULL, return the current value.
14077 * Otherwise, restore the value to "oldval" and return NULL.
14078 * Must always be called in pairs to save and restore v:exception! Does not
14079 * take care of memory allocations.
14080 */
14081 char_u *
14082v_exception(oldval)
14083 char_u *oldval;
14084{
14085 if (oldval == NULL)
Bram Moolenaare9a41262005-01-15 22:18:47 +000014086 return vimvars[VV_EXCEPTION].vv_str;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014087
Bram Moolenaare9a41262005-01-15 22:18:47 +000014088 vimvars[VV_EXCEPTION].vv_str = oldval;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014089 return NULL;
14090}
14091
14092/*
14093 * Get or set v:throwpoint. If "oldval" == NULL, return the current value.
14094 * Otherwise, restore the value to "oldval" and return NULL.
14095 * Must always be called in pairs to save and restore v:throwpoint! Does not
14096 * take care of memory allocations.
14097 */
14098 char_u *
14099v_throwpoint(oldval)
14100 char_u *oldval;
14101{
14102 if (oldval == NULL)
Bram Moolenaare9a41262005-01-15 22:18:47 +000014103 return vimvars[VV_THROWPOINT].vv_str;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014104
Bram Moolenaare9a41262005-01-15 22:18:47 +000014105 vimvars[VV_THROWPOINT].vv_str = oldval;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014106 return NULL;
14107}
14108
14109#if defined(FEAT_AUTOCMD) || defined(PROTO)
14110/*
14111 * Set v:cmdarg.
14112 * If "eap" != NULL, use "eap" to generate the value and return the old value.
14113 * If "oldarg" != NULL, restore the value to "oldarg" and return NULL.
14114 * Must always be called in pairs!
14115 */
14116 char_u *
14117set_cmdarg(eap, oldarg)
14118 exarg_T *eap;
14119 char_u *oldarg;
14120{
14121 char_u *oldval;
14122 char_u *newval;
14123 unsigned len;
14124
Bram Moolenaare9a41262005-01-15 22:18:47 +000014125 oldval = vimvars[VV_CMDARG].vv_str;
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +000014126 if (eap == NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000014127 {
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +000014128 vim_free(oldval);
Bram Moolenaare9a41262005-01-15 22:18:47 +000014129 vimvars[VV_CMDARG].vv_str = oldarg;
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +000014130 return NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014131 }
14132
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +000014133 if (eap->force_bin == FORCE_BIN)
14134 len = 6;
14135 else if (eap->force_bin == FORCE_NOBIN)
14136 len = 8;
14137 else
14138 len = 0;
14139 if (eap->force_ff != 0)
14140 len += (unsigned)STRLEN(eap->cmd + eap->force_ff) + 6;
14141# ifdef FEAT_MBYTE
14142 if (eap->force_enc != 0)
14143 len += (unsigned)STRLEN(eap->cmd + eap->force_enc) + 7;
14144# endif
14145
14146 newval = alloc(len + 1);
14147 if (newval == NULL)
14148 return NULL;
14149
14150 if (eap->force_bin == FORCE_BIN)
14151 sprintf((char *)newval, " ++bin");
14152 else if (eap->force_bin == FORCE_NOBIN)
14153 sprintf((char *)newval, " ++nobin");
14154 else
14155 *newval = NUL;
14156 if (eap->force_ff != 0)
14157 sprintf((char *)newval + STRLEN(newval), " ++ff=%s",
14158 eap->cmd + eap->force_ff);
14159# ifdef FEAT_MBYTE
14160 if (eap->force_enc != 0)
14161 sprintf((char *)newval + STRLEN(newval), " ++enc=%s",
14162 eap->cmd + eap->force_enc);
14163# endif
Bram Moolenaare9a41262005-01-15 22:18:47 +000014164 vimvars[VV_CMDARG].vv_str = newval;
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +000014165 return oldval;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014166}
14167#endif
14168
14169/*
14170 * Get the value of internal variable "name".
14171 * Return OK or FAIL.
14172 */
14173 static int
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000014174get_var_tv(name, len, rettv, verbose)
Bram Moolenaar071d4272004-06-13 20:20:40 +000014175 char_u *name;
14176 int len; /* length of "name" */
Bram Moolenaar33570922005-01-25 22:26:29 +000014177 typval_T *rettv; /* NULL when only checking existence */
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000014178 int verbose; /* may give error message */
Bram Moolenaar071d4272004-06-13 20:20:40 +000014179{
14180 int ret = OK;
Bram Moolenaar33570922005-01-25 22:26:29 +000014181 typval_T *tv = NULL;
14182 typval_T atv;
14183 dictitem_T *v;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014184 int cc;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014185
14186 /* truncate the name, so that we can use strcmp() */
14187 cc = name[len];
14188 name[len] = NUL;
14189
14190 /*
14191 * Check for "b:changedtick".
14192 */
14193 if (STRCMP(name, "b:changedtick") == 0)
14194 {
Bram Moolenaare9a41262005-01-15 22:18:47 +000014195 atv.v_type = VAR_NUMBER;
14196 atv.vval.v_number = curbuf->b_changedtick;
14197 tv = &atv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014198 }
14199
14200 /*
Bram Moolenaar071d4272004-06-13 20:20:40 +000014201 * Check for user-defined variables.
14202 */
14203 else
14204 {
Bram Moolenaara7043832005-01-21 11:56:39 +000014205 v = find_var(name, NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +000014206 if (v != NULL)
Bram Moolenaar33570922005-01-25 22:26:29 +000014207 tv = &v->di_tv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014208 }
14209
Bram Moolenaare9a41262005-01-15 22:18:47 +000014210 if (tv == NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000014211 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000014212 if (rettv != NULL && verbose)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014213 EMSG2(_(e_undefvar), name);
Bram Moolenaar071d4272004-06-13 20:20:40 +000014214 ret = FAIL;
14215 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014216 else if (rettv != NULL)
Bram Moolenaare9a41262005-01-15 22:18:47 +000014217 copy_tv(tv, rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000014218
14219 name[len] = cc;
14220
14221 return ret;
14222}
14223
14224/*
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000014225 * Handle expr[expr], expr[expr:expr] subscript and .name lookup.
14226 * Also handle function call with Funcref variable: func(expr)
14227 * Can all be combined: dict.func(expr)[idx]['func'](expr)
14228 */
14229 static int
14230handle_subscript(arg, rettv, evaluate, verbose)
14231 char_u **arg;
14232 typval_T *rettv;
14233 int evaluate; /* do more than finding the end */
14234 int verbose; /* give error messages */
14235{
14236 int ret = OK;
14237 dict_T *selfdict = NULL;
14238 char_u *s;
14239 int len;
14240
14241 while (ret == OK
14242 && (**arg == '['
14243 || (**arg == '.' && rettv->v_type == VAR_DICT)
14244 || (**arg == '(' && rettv->v_type == VAR_FUNC))
14245 && !vim_iswhite(*(*arg - 1)))
14246 {
14247 if (**arg == '(')
14248 {
14249 s = rettv->vval.v_string;
14250
14251 /* Invoke the function. Recursive! */
14252 ret = get_func_tv(s, STRLEN(s), rettv, arg,
14253 curwin->w_cursor.lnum, curwin->w_cursor.lnum,
14254 &len, evaluate, selfdict);
14255
14256 /* Stop the expression evaluation when immediately aborting on
14257 * error, or when an interrupt occurred or an exception was thrown
14258 * but not caught. */
14259 if (aborting())
14260 {
14261 if (ret == OK)
14262 clear_tv(rettv);
14263 ret = FAIL;
14264 }
14265 dict_unref(selfdict);
14266 selfdict = NULL;
14267 }
14268 else /* **arg == '[' || **arg == '.' */
14269 {
14270 dict_unref(selfdict);
14271 if (rettv->v_type == VAR_DICT)
14272 {
14273 selfdict = rettv->vval.v_dict;
14274 if (selfdict != NULL)
14275 ++selfdict->dv_refcount;
14276 }
14277 else
14278 selfdict = NULL;
14279 if (eval_index(arg, rettv, evaluate, verbose) == FAIL)
14280 {
14281 clear_tv(rettv);
14282 ret = FAIL;
14283 }
14284 }
14285 }
14286 dict_unref(selfdict);
14287 return ret;
14288}
14289
14290/*
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014291 * Allocate memory for a variable type-value, and make it emtpy (0 or NULL
14292 * value).
14293 */
Bram Moolenaar33570922005-01-25 22:26:29 +000014294 static typval_T *
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014295alloc_tv()
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014296{
Bram Moolenaar33570922005-01-25 22:26:29 +000014297 return (typval_T *)alloc_clear((unsigned)sizeof(typval_T));
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014298}
14299
14300/*
14301 * Allocate memory for a variable type-value, and assign a string to it.
Bram Moolenaar071d4272004-06-13 20:20:40 +000014302 * The string "s" must have been allocated, it is consumed.
14303 * Return NULL for out of memory, the variable otherwise.
14304 */
Bram Moolenaar33570922005-01-25 22:26:29 +000014305 static typval_T *
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014306alloc_string_tv(s)
Bram Moolenaar071d4272004-06-13 20:20:40 +000014307 char_u *s;
14308{
Bram Moolenaar33570922005-01-25 22:26:29 +000014309 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014310
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014311 rettv = alloc_tv();
14312 if (rettv != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000014313 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014314 rettv->v_type = VAR_STRING;
14315 rettv->vval.v_string = s;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014316 }
14317 else
14318 vim_free(s);
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014319 return rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014320}
14321
14322/*
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014323 * Free the memory for a variable type-value.
Bram Moolenaar071d4272004-06-13 20:20:40 +000014324 */
14325 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014326free_tv(varp)
Bram Moolenaar33570922005-01-25 22:26:29 +000014327 typval_T *varp;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014328{
14329 if (varp != NULL)
14330 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014331 switch (varp->v_type)
14332 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014333 case VAR_FUNC:
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000014334 func_unref(varp->vval.v_string);
14335 /*FALLTHROUGH*/
14336 case VAR_STRING:
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014337 vim_free(varp->vval.v_string);
14338 break;
14339 case VAR_LIST:
14340 list_unref(varp->vval.v_list);
14341 break;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000014342 case VAR_DICT:
14343 dict_unref(varp->vval.v_dict);
14344 break;
Bram Moolenaar758711c2005-02-02 23:11:38 +000014345 case VAR_NUMBER:
14346 case VAR_UNKNOWN:
14347 break;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014348 default:
Bram Moolenaar758711c2005-02-02 23:11:38 +000014349 EMSG2(_(e_intern2), "free_tv()");
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014350 break;
14351 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000014352 vim_free(varp);
14353 }
14354}
14355
14356/*
14357 * Free the memory for a variable value and set the value to NULL or 0.
14358 */
14359 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014360clear_tv(varp)
Bram Moolenaar33570922005-01-25 22:26:29 +000014361 typval_T *varp;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014362{
14363 if (varp != NULL)
14364 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014365 switch (varp->v_type)
Bram Moolenaar071d4272004-06-13 20:20:40 +000014366 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014367 case VAR_FUNC:
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000014368 func_unref(varp->vval.v_string);
14369 /*FALLTHROUGH*/
14370 case VAR_STRING:
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014371 vim_free(varp->vval.v_string);
14372 varp->vval.v_string = NULL;
14373 break;
14374 case VAR_LIST:
14375 list_unref(varp->vval.v_list);
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000014376 varp->vval.v_list = NULL;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014377 break;
Bram Moolenaar8c711452005-01-14 21:53:12 +000014378 case VAR_DICT:
14379 dict_unref(varp->vval.v_dict);
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000014380 varp->vval.v_dict = NULL;
Bram Moolenaar8c711452005-01-14 21:53:12 +000014381 break;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014382 case VAR_NUMBER:
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014383 varp->vval.v_number = 0;
14384 break;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014385 case VAR_UNKNOWN:
14386 break;
14387 default:
14388 EMSG2(_(e_intern2), "clear_tv()");
Bram Moolenaar071d4272004-06-13 20:20:40 +000014389 }
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000014390 varp->v_lock = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014391 }
14392}
14393
14394/*
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014395 * Set the value of a variable to NULL without freeing items.
14396 */
14397 static void
14398init_tv(varp)
Bram Moolenaar33570922005-01-25 22:26:29 +000014399 typval_T *varp;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014400{
14401 if (varp != NULL)
Bram Moolenaar33570922005-01-25 22:26:29 +000014402 vim_memset(varp, 0, sizeof(typval_T));
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014403}
14404
14405/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000014406 * Get the number value of a variable.
14407 * If it is a String variable, uses vim_str2nr().
14408 */
14409 static long
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014410get_tv_number(varp)
Bram Moolenaar33570922005-01-25 22:26:29 +000014411 typval_T *varp;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014412{
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014413 long n = 0L;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014414
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014415 switch (varp->v_type)
Bram Moolenaar071d4272004-06-13 20:20:40 +000014416 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014417 case VAR_NUMBER:
14418 n = (long)(varp->vval.v_number);
14419 break;
14420 case VAR_FUNC:
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000014421 EMSG(_("E703: Using a Funcref as a number"));
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014422 break;
14423 case VAR_STRING:
14424 if (varp->vval.v_string != NULL)
14425 vim_str2nr(varp->vval.v_string, NULL, NULL,
14426 TRUE, TRUE, &n, NULL);
14427 break;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000014428 case VAR_LIST:
Bram Moolenaar758711c2005-02-02 23:11:38 +000014429 EMSG(_("E745: Using a List as a number"));
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000014430 break;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000014431 case VAR_DICT:
14432 EMSG(_("E728: Using a Dictionary as a number"));
14433 break;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014434 default:
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000014435 EMSG2(_(e_intern2), "get_tv_number()");
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014436 break;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014437 }
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014438 return n;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014439}
14440
14441/*
14442 * Get the lnum from the first argument. Also accepts ".", "$", etc.
14443 */
14444 static linenr_T
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014445get_tv_lnum(argvars)
Bram Moolenaar33570922005-01-25 22:26:29 +000014446 typval_T *argvars;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014447{
Bram Moolenaar33570922005-01-25 22:26:29 +000014448 typval_T rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014449 linenr_T lnum;
14450
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014451 lnum = get_tv_number(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +000014452 if (lnum == 0) /* no valid number, try using line() */
14453 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014454 rettv.v_type = VAR_NUMBER;
14455 f_line(argvars, &rettv);
14456 lnum = rettv.vval.v_number;
14457 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000014458 }
14459 return lnum;
14460}
14461
14462/*
14463 * Get the string value of a variable.
14464 * If it is a Number variable, the number is converted into a string.
Bram Moolenaara7043832005-01-21 11:56:39 +000014465 * get_tv_string() uses a single, static buffer. YOU CAN ONLY USE IT ONCE!
14466 * get_tv_string_buf() uses a given buffer.
Bram Moolenaar071d4272004-06-13 20:20:40 +000014467 * If the String variable has never been set, return an empty string.
14468 * Never returns NULL;
14469 */
14470 static char_u *
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014471get_tv_string(varp)
Bram Moolenaar33570922005-01-25 22:26:29 +000014472 typval_T *varp;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014473{
14474 static char_u mybuf[NUMBUFLEN];
14475
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014476 return get_tv_string_buf(varp, mybuf);
Bram Moolenaar071d4272004-06-13 20:20:40 +000014477}
14478
14479 static char_u *
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014480get_tv_string_buf(varp, buf)
Bram Moolenaar33570922005-01-25 22:26:29 +000014481 typval_T *varp;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014482 char_u *buf;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014483{
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014484 switch (varp->v_type)
Bram Moolenaar071d4272004-06-13 20:20:40 +000014485 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014486 case VAR_NUMBER:
14487 sprintf((char *)buf, "%ld", (long)varp->vval.v_number);
14488 return buf;
14489 case VAR_FUNC:
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000014490 EMSG(_("E729: using Funcref as a String"));
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014491 break;
14492 case VAR_LIST:
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000014493 EMSG(_("E730: using List as a String"));
Bram Moolenaar8c711452005-01-14 21:53:12 +000014494 break;
14495 case VAR_DICT:
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000014496 EMSG(_("E731: using Dictionary as a String"));
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014497 break;
14498 case VAR_STRING:
14499 if (varp->vval.v_string != NULL)
14500 return varp->vval.v_string;
14501 break;
14502 default:
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014503 EMSG2(_(e_intern2), "get_tv_string_buf()");
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014504 break;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014505 }
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014506 return (char_u *)"";
Bram Moolenaar071d4272004-06-13 20:20:40 +000014507}
14508
14509/*
14510 * Find variable "name" in the list of variables.
14511 * Return a pointer to it if found, NULL if not found.
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014512 * Careful: "a:0" variables don't have a name.
Bram Moolenaara7043832005-01-21 11:56:39 +000014513 * When "htp" is not NULL we are writing to the variable, set "htp" to the
Bram Moolenaar33570922005-01-25 22:26:29 +000014514 * hashtab_T used.
Bram Moolenaar071d4272004-06-13 20:20:40 +000014515 */
Bram Moolenaar33570922005-01-25 22:26:29 +000014516 static dictitem_T *
Bram Moolenaara7043832005-01-21 11:56:39 +000014517find_var(name, htp)
Bram Moolenaar071d4272004-06-13 20:20:40 +000014518 char_u *name;
Bram Moolenaar33570922005-01-25 22:26:29 +000014519 hashtab_T **htp;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014520{
Bram Moolenaar071d4272004-06-13 20:20:40 +000014521 char_u *varname;
Bram Moolenaar33570922005-01-25 22:26:29 +000014522 hashtab_T *ht;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014523
Bram Moolenaara7043832005-01-21 11:56:39 +000014524 ht = find_var_ht(name, &varname);
14525 if (htp != NULL)
14526 *htp = ht;
14527 if (ht == NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000014528 return NULL;
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000014529 return find_var_in_ht(ht, varname, htp != NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +000014530}
14531
14532/*
Bram Moolenaar33570922005-01-25 22:26:29 +000014533 * Find variable "varname" in hashtab "ht".
Bram Moolenaara7043832005-01-21 11:56:39 +000014534 * Returns NULL if not found.
Bram Moolenaar071d4272004-06-13 20:20:40 +000014535 */
Bram Moolenaar33570922005-01-25 22:26:29 +000014536 static dictitem_T *
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000014537find_var_in_ht(ht, varname, writing)
Bram Moolenaar33570922005-01-25 22:26:29 +000014538 hashtab_T *ht;
Bram Moolenaara7043832005-01-21 11:56:39 +000014539 char_u *varname;
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000014540 int writing;
Bram Moolenaara7043832005-01-21 11:56:39 +000014541{
Bram Moolenaar33570922005-01-25 22:26:29 +000014542 hashitem_T *hi;
14543
14544 if (*varname == NUL)
14545 {
14546 /* Must be something like "s:", otherwise "ht" would be NULL. */
14547 switch (varname[-2])
14548 {
14549 case 's': return &SCRIPT_SV(current_SID).sv_var;
14550 case 'g': return &globvars_var;
14551 case 'v': return &vimvars_var;
14552 case 'b': return &curbuf->b_bufvar;
14553 case 'w': return &curwin->w_winvar;
14554 case 'l': return &current_funccal->l_vars_var;
14555 case 'a': return &current_funccal->l_avars_var;
14556 }
14557 return NULL;
14558 }
Bram Moolenaara7043832005-01-21 11:56:39 +000014559
14560 hi = hash_find(ht, varname);
14561 if (HASHITEM_EMPTY(hi))
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000014562 {
14563 /* For global variables we may try auto-loading the script. If it
14564 * worked find the variable again. */
14565 if (ht == &globvarht && !writing
14566 && script_autoload(varname) && !aborting())
14567 hi = hash_find(ht, varname);
14568 if (HASHITEM_EMPTY(hi))
14569 return NULL;
14570 }
Bram Moolenaar33570922005-01-25 22:26:29 +000014571 return HI2DI(hi);
Bram Moolenaara7043832005-01-21 11:56:39 +000014572}
14573
14574/*
Bram Moolenaar33570922005-01-25 22:26:29 +000014575 * Find the hashtab used for a variable name.
Bram Moolenaara7043832005-01-21 11:56:39 +000014576 * Set "varname" to the start of name without ':'.
14577 */
Bram Moolenaar33570922005-01-25 22:26:29 +000014578 static hashtab_T *
Bram Moolenaara7043832005-01-21 11:56:39 +000014579find_var_ht(name, varname)
Bram Moolenaar071d4272004-06-13 20:20:40 +000014580 char_u *name;
14581 char_u **varname;
14582{
14583 if (name[1] != ':')
14584 {
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000014585 /* The name must not start with a colon. */
14586 if (name[0] == ':')
Bram Moolenaar071d4272004-06-13 20:20:40 +000014587 return NULL;
14588 *varname = name;
Bram Moolenaar532c7802005-01-27 14:44:31 +000014589
14590 /* "version" is "v:version" in all scopes */
14591 if (!HASHITEM_EMPTY(hash_find(&compat_hashtab, name)))
14592 return &compat_hashtab;
14593
Bram Moolenaar071d4272004-06-13 20:20:40 +000014594 if (current_funccal == NULL)
Bram Moolenaar33570922005-01-25 22:26:29 +000014595 return &globvarht; /* global variable */
14596 return &current_funccal->l_vars.dv_hashtab; /* l: variable */
Bram Moolenaar071d4272004-06-13 20:20:40 +000014597 }
14598 *varname = name + 2;
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000014599 if (*name == 'g') /* global variable */
14600 return &globvarht;
14601 /* There must be no ':' in the rest of the name, unless g: is used */
14602 if (vim_strchr(name + 2, ':') != NULL)
14603 return NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014604 if (*name == 'b') /* buffer variable */
Bram Moolenaar33570922005-01-25 22:26:29 +000014605 return &curbuf->b_vars.dv_hashtab;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014606 if (*name == 'w') /* window variable */
Bram Moolenaar33570922005-01-25 22:26:29 +000014607 return &curwin->w_vars.dv_hashtab;
Bram Moolenaar33570922005-01-25 22:26:29 +000014608 if (*name == 'v') /* v: variable */
14609 return &vimvarht;
14610 if (*name == 'a' && current_funccal != NULL) /* function argument */
14611 return &current_funccal->l_avars.dv_hashtab;
14612 if (*name == 'l' && current_funccal != NULL) /* local function variable */
14613 return &current_funccal->l_vars.dv_hashtab;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014614 if (*name == 's' /* script variable */
14615 && current_SID > 0 && current_SID <= ga_scripts.ga_len)
14616 return &SCRIPT_VARS(current_SID);
14617 return NULL;
14618}
14619
14620/*
14621 * Get the string value of a (global/local) variable.
14622 * Returns NULL when it doesn't exist.
14623 */
14624 char_u *
14625get_var_value(name)
14626 char_u *name;
14627{
Bram Moolenaar33570922005-01-25 22:26:29 +000014628 dictitem_T *v;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014629
Bram Moolenaara7043832005-01-21 11:56:39 +000014630 v = find_var(name, NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +000014631 if (v == NULL)
14632 return NULL;
Bram Moolenaar33570922005-01-25 22:26:29 +000014633 return get_tv_string(&v->di_tv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000014634}
14635
14636/*
Bram Moolenaar33570922005-01-25 22:26:29 +000014637 * Allocate a new hashtab for a sourced script. It will be used while
Bram Moolenaar071d4272004-06-13 20:20:40 +000014638 * sourcing this script and when executing functions defined in the script.
14639 */
14640 void
14641new_script_vars(id)
14642 scid_T id;
14643{
Bram Moolenaara7043832005-01-21 11:56:39 +000014644 int i;
Bram Moolenaar33570922005-01-25 22:26:29 +000014645 hashtab_T *ht;
14646 scriptvar_T *sv;
Bram Moolenaara7043832005-01-21 11:56:39 +000014647
Bram Moolenaar071d4272004-06-13 20:20:40 +000014648 if (ga_grow(&ga_scripts, (int)(id - ga_scripts.ga_len)) == OK)
14649 {
Bram Moolenaara7043832005-01-21 11:56:39 +000014650 /* Re-allocating ga_data means that an ht_array pointing to
14651 * ht_smallarray becomes invalid. We can recognize this: ht_mask is
Bram Moolenaar33570922005-01-25 22:26:29 +000014652 * at its init value. Also reset "v_dict", it's always the same. */
Bram Moolenaara7043832005-01-21 11:56:39 +000014653 for (i = 1; i <= ga_scripts.ga_len; ++i)
14654 {
14655 ht = &SCRIPT_VARS(i);
14656 if (ht->ht_mask == HT_INIT_SIZE - 1)
14657 ht->ht_array = ht->ht_smallarray;
Bram Moolenaar33570922005-01-25 22:26:29 +000014658 sv = &SCRIPT_SV(i);
14659 sv->sv_var.di_tv.vval.v_dict = &sv->sv_dict;
Bram Moolenaara7043832005-01-21 11:56:39 +000014660 }
14661
Bram Moolenaar071d4272004-06-13 20:20:40 +000014662 while (ga_scripts.ga_len < id)
14663 {
Bram Moolenaar33570922005-01-25 22:26:29 +000014664 sv = &SCRIPT_SV(ga_scripts.ga_len + 1);
14665 init_var_dict(&sv->sv_dict, &sv->sv_var);
Bram Moolenaar071d4272004-06-13 20:20:40 +000014666 ++ga_scripts.ga_len;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014667 }
14668 }
14669}
14670
14671/*
Bram Moolenaar33570922005-01-25 22:26:29 +000014672 * Initialize dictionary "dict" as a scope and set variable "dict_var" to
14673 * point to it.
Bram Moolenaar071d4272004-06-13 20:20:40 +000014674 */
14675 void
Bram Moolenaar33570922005-01-25 22:26:29 +000014676init_var_dict(dict, dict_var)
14677 dict_T *dict;
14678 dictitem_T *dict_var;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014679{
Bram Moolenaar33570922005-01-25 22:26:29 +000014680 hash_init(&dict->dv_hashtab);
14681 dict->dv_refcount = 99999;
14682 dict_var->di_tv.vval.v_dict = dict;
14683 dict_var->di_tv.v_type = VAR_DICT;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000014684 dict_var->di_tv.v_lock = VAR_FIXED;
Bram Moolenaar33570922005-01-25 22:26:29 +000014685 dict_var->di_flags = DI_FLAGS_RO | DI_FLAGS_FIX;
14686 dict_var->di_key[0] = NUL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014687}
14688
14689/*
14690 * Clean up a list of internal variables.
Bram Moolenaar33570922005-01-25 22:26:29 +000014691 * Frees all allocated variables and the value they contain.
14692 * Clears hashtab "ht", does not free it.
Bram Moolenaar071d4272004-06-13 20:20:40 +000014693 */
14694 void
Bram Moolenaara7043832005-01-21 11:56:39 +000014695vars_clear(ht)
Bram Moolenaar33570922005-01-25 22:26:29 +000014696 hashtab_T *ht;
14697{
14698 vars_clear_ext(ht, TRUE);
14699}
14700
14701/*
14702 * Like vars_clear(), but only free the value if "free_val" is TRUE.
14703 */
14704 static void
14705vars_clear_ext(ht, free_val)
14706 hashtab_T *ht;
14707 int free_val;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014708{
Bram Moolenaara7043832005-01-21 11:56:39 +000014709 int todo;
Bram Moolenaar33570922005-01-25 22:26:29 +000014710 hashitem_T *hi;
14711 dictitem_T *v;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014712
Bram Moolenaar33570922005-01-25 22:26:29 +000014713 hash_lock(ht);
Bram Moolenaara7043832005-01-21 11:56:39 +000014714 todo = ht->ht_used;
14715 for (hi = ht->ht_array; todo > 0; ++hi)
14716 {
14717 if (!HASHITEM_EMPTY(hi))
14718 {
14719 --todo;
14720
Bram Moolenaar33570922005-01-25 22:26:29 +000014721 /* Free the variable. Don't remove it from the hashtab,
Bram Moolenaara7043832005-01-21 11:56:39 +000014722 * ht_array might change then. hash_clear() takes care of it
14723 * later. */
Bram Moolenaar33570922005-01-25 22:26:29 +000014724 v = HI2DI(hi);
14725 if (free_val)
14726 clear_tv(&v->di_tv);
14727 if ((v->di_flags & DI_FLAGS_FIX) == 0)
14728 vim_free(v);
Bram Moolenaara7043832005-01-21 11:56:39 +000014729 }
14730 }
14731 hash_clear(ht);
Bram Moolenaar071d4272004-06-13 20:20:40 +000014732}
14733
Bram Moolenaara7043832005-01-21 11:56:39 +000014734/*
Bram Moolenaar33570922005-01-25 22:26:29 +000014735 * Delete a variable from hashtab "ht" at item "hi".
14736 * Clear the variable value and free the dictitem.
Bram Moolenaara7043832005-01-21 11:56:39 +000014737 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000014738 static void
Bram Moolenaara7043832005-01-21 11:56:39 +000014739delete_var(ht, hi)
Bram Moolenaar33570922005-01-25 22:26:29 +000014740 hashtab_T *ht;
14741 hashitem_T *hi;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014742{
Bram Moolenaar33570922005-01-25 22:26:29 +000014743 dictitem_T *di = HI2DI(hi);
Bram Moolenaara7043832005-01-21 11:56:39 +000014744
14745 hash_remove(ht, hi);
Bram Moolenaar33570922005-01-25 22:26:29 +000014746 clear_tv(&di->di_tv);
14747 vim_free(di);
Bram Moolenaar071d4272004-06-13 20:20:40 +000014748}
14749
14750/*
14751 * List the value of one internal variable.
14752 */
14753 static void
14754list_one_var(v, prefix)
Bram Moolenaar33570922005-01-25 22:26:29 +000014755 dictitem_T *v;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014756 char_u *prefix;
14757{
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014758 char_u *tofree;
14759 char_u *s;
Bram Moolenaar8a283e52005-01-06 23:28:25 +000014760 char_u numbuf[NUMBUFLEN];
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014761
Bram Moolenaar33570922005-01-25 22:26:29 +000014762 s = echo_string(&v->di_tv, &tofree, numbuf);
14763 list_one_var_a(prefix, v->di_key, v->di_tv.v_type,
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014764 s == NULL ? (char_u *)"" : s);
14765 vim_free(tofree);
Bram Moolenaar071d4272004-06-13 20:20:40 +000014766}
14767
Bram Moolenaar071d4272004-06-13 20:20:40 +000014768 static void
14769list_one_var_a(prefix, name, type, string)
14770 char_u *prefix;
14771 char_u *name;
14772 int type;
14773 char_u *string;
14774{
14775 msg_attr(prefix, 0); /* don't use msg(), it overwrites "v:statusmsg" */
14776 if (name != NULL) /* "a:" vars don't have a name stored */
14777 msg_puts(name);
14778 msg_putchar(' ');
14779 msg_advance(22);
14780 if (type == VAR_NUMBER)
14781 msg_putchar('#');
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014782 else if (type == VAR_FUNC)
14783 msg_putchar('*');
14784 else if (type == VAR_LIST)
14785 {
14786 msg_putchar('[');
14787 if (*string == '[')
14788 ++string;
14789 }
Bram Moolenaar8c711452005-01-14 21:53:12 +000014790 else if (type == VAR_DICT)
14791 {
14792 msg_putchar('{');
14793 if (*string == '{')
14794 ++string;
14795 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000014796 else
14797 msg_putchar(' ');
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014798
Bram Moolenaar071d4272004-06-13 20:20:40 +000014799 msg_outtrans(string);
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014800
14801 if (type == VAR_FUNC)
14802 msg_puts((char_u *)"()");
Bram Moolenaar071d4272004-06-13 20:20:40 +000014803}
14804
14805/*
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014806 * Set variable "name" to value in "tv".
Bram Moolenaar071d4272004-06-13 20:20:40 +000014807 * If the variable already exists, the value is updated.
14808 * Otherwise the variable is created.
14809 */
14810 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014811set_var(name, tv, copy)
Bram Moolenaar071d4272004-06-13 20:20:40 +000014812 char_u *name;
Bram Moolenaar33570922005-01-25 22:26:29 +000014813 typval_T *tv;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014814 int copy; /* make copy of value in "tv" */
Bram Moolenaar071d4272004-06-13 20:20:40 +000014815{
Bram Moolenaar33570922005-01-25 22:26:29 +000014816 dictitem_T *v;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014817 char_u *varname;
Bram Moolenaar33570922005-01-25 22:26:29 +000014818 hashtab_T *ht;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014819
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014820 if (tv->v_type == VAR_FUNC)
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014821 {
14822 if (!(vim_strchr((char_u *)"wbs", name[0]) != NULL && name[1] == ':')
14823 && !ASCII_ISUPPER((name[0] != NUL && name[1] == ':')
14824 ? name[2] : name[0]))
14825 {
Bram Moolenaare49b69a2005-01-08 16:11:57 +000014826 EMSG2(_("E704: Funcref variable name must start with a capital: %s"), name);
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014827 return;
14828 }
14829 if (function_exists(name))
14830 {
Bram Moolenaar81bf7082005-02-12 14:31:42 +000014831 EMSG2(_("705: Variable name conflicts with existing function: %s"),
14832 name);
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014833 return;
14834 }
14835 }
14836
Bram Moolenaara7043832005-01-21 11:56:39 +000014837 ht = find_var_ht(name, &varname);
Bram Moolenaar33570922005-01-25 22:26:29 +000014838 if (ht == NULL || *varname == NUL)
Bram Moolenaara7043832005-01-21 11:56:39 +000014839 {
14840 EMSG2(_("E461: Illegal variable name: %s"), name);
14841 return;
14842 }
14843
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000014844 v = find_var_in_ht(ht, varname, TRUE);
Bram Moolenaar33570922005-01-25 22:26:29 +000014845 if (v != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000014846 {
Bram Moolenaar33570922005-01-25 22:26:29 +000014847 /* existing variable, need to clear the value */
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000014848 if (var_check_ro(v->di_flags, name)
14849 || tv_check_lock(v->di_tv.v_lock, name))
Bram Moolenaar33570922005-01-25 22:26:29 +000014850 return;
14851 if (v->di_tv.v_type != tv->v_type
14852 && !((v->di_tv.v_type == VAR_STRING
14853 || v->di_tv.v_type == VAR_NUMBER)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014854 && (tv->v_type == VAR_STRING
14855 || tv->v_type == VAR_NUMBER)))
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014856 {
Bram Moolenaare49b69a2005-01-08 16:11:57 +000014857 EMSG2(_("E706: Variable type mismatch for: %s"), name);
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014858 return;
14859 }
Bram Moolenaar33570922005-01-25 22:26:29 +000014860
14861 /*
Bram Moolenaar758711c2005-02-02 23:11:38 +000014862 * Handle setting internal v: variables separately: we don't change
14863 * the type.
Bram Moolenaar33570922005-01-25 22:26:29 +000014864 */
14865 if (ht == &vimvarht)
14866 {
14867 if (v->di_tv.v_type == VAR_STRING)
14868 {
14869 vim_free(v->di_tv.vval.v_string);
14870 if (copy || tv->v_type != VAR_STRING)
14871 v->di_tv.vval.v_string = vim_strsave(get_tv_string(tv));
14872 else
14873 {
14874 /* Take over the string to avoid an extra alloc/free. */
14875 v->di_tv.vval.v_string = tv->vval.v_string;
14876 tv->vval.v_string = NULL;
14877 }
14878 }
14879 else if (v->di_tv.v_type != VAR_NUMBER)
14880 EMSG2(_(e_intern2), "set_var()");
14881 else
14882 v->di_tv.vval.v_number = get_tv_number(tv);
14883 return;
14884 }
14885
14886 clear_tv(&v->di_tv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000014887 }
14888 else /* add a new variable */
14889 {
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000014890 v = (dictitem_T *)alloc((unsigned)(sizeof(dictitem_T)
14891 + STRLEN(varname)));
Bram Moolenaara7043832005-01-21 11:56:39 +000014892 if (v == NULL)
14893 return;
Bram Moolenaar33570922005-01-25 22:26:29 +000014894 STRCPY(v->di_key, varname);
Bram Moolenaar33570922005-01-25 22:26:29 +000014895 if (hash_add(ht, DI2HIKEY(v)) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000014896 {
Bram Moolenaara7043832005-01-21 11:56:39 +000014897 vim_free(v);
Bram Moolenaar071d4272004-06-13 20:20:40 +000014898 return;
14899 }
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000014900 v->di_flags = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014901 }
Bram Moolenaara7043832005-01-21 11:56:39 +000014902
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014903 if (copy || tv->v_type == VAR_NUMBER)
Bram Moolenaar33570922005-01-25 22:26:29 +000014904 copy_tv(tv, &v->di_tv);
Bram Moolenaar1c2fda22005-01-02 11:43:19 +000014905 else
14906 {
Bram Moolenaar33570922005-01-25 22:26:29 +000014907 v->di_tv = *tv;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000014908 v->di_tv.v_lock = 0;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014909 init_tv(tv);
Bram Moolenaar1c2fda22005-01-02 11:43:19 +000014910 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000014911}
14912
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014913/*
Bram Moolenaar33570922005-01-25 22:26:29 +000014914 * Return TRUE if di_flags "flags" indicate read-only variable "name".
14915 * Also give an error message.
14916 */
14917 static int
14918var_check_ro(flags, name)
14919 int flags;
14920 char_u *name;
14921{
14922 if (flags & DI_FLAGS_RO)
14923 {
14924 EMSG2(_(e_readonlyvar), name);
14925 return TRUE;
14926 }
14927 if ((flags & DI_FLAGS_RO_SBX) && sandbox)
14928 {
14929 EMSG2(_(e_readonlysbx), name);
14930 return TRUE;
14931 }
14932 return FALSE;
14933}
14934
14935/*
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000014936 * Return TRUE if typeval "tv" is set to be locked (immutable).
14937 * Also give an error message, using "name".
14938 */
14939 static int
14940tv_check_lock(lock, name)
14941 int lock;
14942 char_u *name;
14943{
14944 if (lock & VAR_LOCKED)
14945 {
14946 EMSG2(_("E741: Value is locked: %s"),
14947 name == NULL ? (char_u *)_("Unknown") : name);
14948 return TRUE;
14949 }
14950 if (lock & VAR_FIXED)
14951 {
14952 EMSG2(_("E742: Cannot change value of %s"),
14953 name == NULL ? (char_u *)_("Unknown") : name);
14954 return TRUE;
14955 }
14956 return FALSE;
14957}
14958
14959/*
Bram Moolenaar33570922005-01-25 22:26:29 +000014960 * Copy the values from typval_T "from" to typval_T "to".
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014961 * When needed allocates string or increases reference count.
Bram Moolenaare9a41262005-01-15 22:18:47 +000014962 * Does not make a copy of a list or dict but copies the reference!
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014963 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000014964 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014965copy_tv(from, to)
Bram Moolenaar33570922005-01-25 22:26:29 +000014966 typval_T *from;
14967 typval_T *to;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014968{
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014969 to->v_type = from->v_type;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000014970 to->v_lock = 0;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014971 switch (from->v_type)
14972 {
14973 case VAR_NUMBER:
14974 to->vval.v_number = from->vval.v_number;
14975 break;
14976 case VAR_STRING:
14977 case VAR_FUNC:
14978 if (from->vval.v_string == NULL)
14979 to->vval.v_string = NULL;
14980 else
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000014981 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014982 to->vval.v_string = vim_strsave(from->vval.v_string);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000014983 if (from->v_type == VAR_FUNC)
14984 func_ref(to->vval.v_string);
14985 }
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014986 break;
14987 case VAR_LIST:
14988 if (from->vval.v_list == NULL)
14989 to->vval.v_list = NULL;
14990 else
14991 {
14992 to->vval.v_list = from->vval.v_list;
14993 ++to->vval.v_list->lv_refcount;
14994 }
14995 break;
Bram Moolenaar8c711452005-01-14 21:53:12 +000014996 case VAR_DICT:
14997 if (from->vval.v_dict == NULL)
14998 to->vval.v_dict = NULL;
14999 else
15000 {
15001 to->vval.v_dict = from->vval.v_dict;
15002 ++to->vval.v_dict->dv_refcount;
15003 }
15004 break;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000015005 default:
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015006 EMSG2(_(e_intern2), "copy_tv()");
Bram Moolenaar49cd9572005-01-03 21:06:01 +000015007 break;
15008 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000015009}
15010
15011/*
Bram Moolenaare9a41262005-01-15 22:18:47 +000015012 * Make a copy of an item.
15013 * Lists and Dictionaries are also copied. A deep copy if "deep" is set.
Bram Moolenaar81bf7082005-02-12 14:31:42 +000015014 * For deepcopy() "copyID" is zero for a full copy or the ID for when a
15015 * reference to an already copied list/dict can be used.
15016 * Returns FAIL or OK.
Bram Moolenaare9a41262005-01-15 22:18:47 +000015017 */
Bram Moolenaar81bf7082005-02-12 14:31:42 +000015018 static int
15019item_copy(from, to, deep, copyID)
Bram Moolenaar33570922005-01-25 22:26:29 +000015020 typval_T *from;
15021 typval_T *to;
Bram Moolenaare9a41262005-01-15 22:18:47 +000015022 int deep;
Bram Moolenaar81bf7082005-02-12 14:31:42 +000015023 int copyID;
Bram Moolenaare9a41262005-01-15 22:18:47 +000015024{
15025 static int recurse = 0;
Bram Moolenaar81bf7082005-02-12 14:31:42 +000015026 int ret = OK;
Bram Moolenaare9a41262005-01-15 22:18:47 +000015027
Bram Moolenaar33570922005-01-25 22:26:29 +000015028 if (recurse >= DICT_MAXNEST)
Bram Moolenaare9a41262005-01-15 22:18:47 +000015029 {
15030 EMSG(_("E698: variable nested too deep for making a copy"));
Bram Moolenaar81bf7082005-02-12 14:31:42 +000015031 return FAIL;
Bram Moolenaare9a41262005-01-15 22:18:47 +000015032 }
15033 ++recurse;
15034
15035 switch (from->v_type)
15036 {
15037 case VAR_NUMBER:
15038 case VAR_STRING:
15039 case VAR_FUNC:
15040 copy_tv(from, to);
15041 break;
15042 case VAR_LIST:
15043 to->v_type = VAR_LIST;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000015044 to->v_lock = 0;
Bram Moolenaar81bf7082005-02-12 14:31:42 +000015045 if (from->vval.v_list == NULL)
15046 to->vval.v_list = NULL;
15047 else if (copyID != 0 && from->vval.v_list->lv_copyID == copyID)
15048 {
15049 /* use the copy made earlier */
15050 to->vval.v_list = from->vval.v_list->lv_copylist;
15051 ++to->vval.v_list->lv_refcount;
15052 }
15053 else
15054 to->vval.v_list = list_copy(from->vval.v_list, deep, copyID);
15055 if (to->vval.v_list == NULL)
15056 ret = FAIL;
Bram Moolenaare9a41262005-01-15 22:18:47 +000015057 break;
15058 case VAR_DICT:
15059 to->v_type = VAR_DICT;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000015060 to->v_lock = 0;
Bram Moolenaar81bf7082005-02-12 14:31:42 +000015061 if (from->vval.v_dict == NULL)
15062 to->vval.v_dict = NULL;
15063 else if (copyID != 0 && from->vval.v_dict->dv_copyID == copyID)
15064 {
15065 /* use the copy made earlier */
15066 to->vval.v_dict = from->vval.v_dict->dv_copydict;
15067 ++to->vval.v_dict->dv_refcount;
15068 }
15069 else
15070 to->vval.v_dict = dict_copy(from->vval.v_dict, deep, copyID);
15071 if (to->vval.v_dict == NULL)
15072 ret = FAIL;
Bram Moolenaare9a41262005-01-15 22:18:47 +000015073 break;
15074 default:
15075 EMSG2(_(e_intern2), "item_copy()");
Bram Moolenaar81bf7082005-02-12 14:31:42 +000015076 ret = FAIL;
Bram Moolenaare9a41262005-01-15 22:18:47 +000015077 }
15078 --recurse;
Bram Moolenaar81bf7082005-02-12 14:31:42 +000015079 return ret;
Bram Moolenaare9a41262005-01-15 22:18:47 +000015080}
15081
15082/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000015083 * ":echo expr1 ..." print each argument separated with a space, add a
15084 * newline at the end.
15085 * ":echon expr1 ..." print each argument plain.
15086 */
15087 void
15088ex_echo(eap)
15089 exarg_T *eap;
15090{
15091 char_u *arg = eap->arg;
Bram Moolenaar33570922005-01-25 22:26:29 +000015092 typval_T rettv;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000015093 char_u *tofree;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015094 char_u *p;
15095 int needclr = TRUE;
15096 int atstart = TRUE;
Bram Moolenaar8a283e52005-01-06 23:28:25 +000015097 char_u numbuf[NUMBUFLEN];
Bram Moolenaar071d4272004-06-13 20:20:40 +000015098
15099 if (eap->skip)
15100 ++emsg_skip;
15101 while (*arg != NUL && *arg != '|' && *arg != '\n' && !got_int)
15102 {
15103 p = arg;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015104 if (eval1(&arg, &rettv, !eap->skip) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000015105 {
15106 /*
15107 * Report the invalid expression unless the expression evaluation
15108 * has been cancelled due to an aborting error, an interrupt, or an
15109 * exception.
15110 */
15111 if (!aborting())
15112 EMSG2(_(e_invexpr2), p);
15113 break;
15114 }
15115 if (!eap->skip)
15116 {
15117 if (atstart)
15118 {
15119 atstart = FALSE;
15120 /* Call msg_start() after eval1(), evaluating the expression
15121 * may cause a message to appear. */
15122 if (eap->cmdidx == CMD_echo)
15123 msg_start();
15124 }
15125 else if (eap->cmdidx == CMD_echo)
15126 msg_puts_attr((char_u *)" ", echo_attr);
Bram Moolenaar81bf7082005-02-12 14:31:42 +000015127 p = echo_string(&rettv, &tofree, numbuf);
15128 if (p != NULL)
15129 for ( ; *p != NUL && !got_int; ++p)
Bram Moolenaar071d4272004-06-13 20:20:40 +000015130 {
Bram Moolenaar81bf7082005-02-12 14:31:42 +000015131 if (*p == '\n' || *p == '\r' || *p == TAB)
Bram Moolenaar071d4272004-06-13 20:20:40 +000015132 {
Bram Moolenaar81bf7082005-02-12 14:31:42 +000015133 if (*p != TAB && needclr)
15134 {
15135 /* remove any text still there from the command */
15136 msg_clr_eos();
15137 needclr = FALSE;
15138 }
15139 msg_putchar_attr(*p, echo_attr);
Bram Moolenaar071d4272004-06-13 20:20:40 +000015140 }
15141 else
Bram Moolenaar81bf7082005-02-12 14:31:42 +000015142 {
15143#ifdef FEAT_MBYTE
15144 if (has_mbyte)
15145 {
15146 int i = (*mb_ptr2len_check)(p);
15147
15148 (void)msg_outtrans_len_attr(p, i, echo_attr);
15149 p += i - 1;
15150 }
15151 else
Bram Moolenaar071d4272004-06-13 20:20:40 +000015152#endif
Bram Moolenaar81bf7082005-02-12 14:31:42 +000015153 (void)msg_outtrans_len_attr(p, 1, echo_attr);
15154 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000015155 }
Bram Moolenaar49cd9572005-01-03 21:06:01 +000015156 vim_free(tofree);
Bram Moolenaar071d4272004-06-13 20:20:40 +000015157 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015158 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000015159 arg = skipwhite(arg);
15160 }
15161 eap->nextcmd = check_nextcmd(arg);
15162
15163 if (eap->skip)
15164 --emsg_skip;
15165 else
15166 {
15167 /* remove text that may still be there from the command */
15168 if (needclr)
15169 msg_clr_eos();
15170 if (eap->cmdidx == CMD_echo)
15171 msg_end();
15172 }
15173}
15174
15175/*
15176 * ":echohl {name}".
15177 */
15178 void
15179ex_echohl(eap)
15180 exarg_T *eap;
15181{
15182 int id;
15183
15184 id = syn_name2id(eap->arg);
15185 if (id == 0)
15186 echo_attr = 0;
15187 else
15188 echo_attr = syn_id2attr(id);
15189}
15190
15191/*
15192 * ":execute expr1 ..." execute the result of an expression.
15193 * ":echomsg expr1 ..." Print a message
15194 * ":echoerr expr1 ..." Print an error
15195 * Each gets spaces around each argument and a newline at the end for
15196 * echo commands
15197 */
15198 void
15199ex_execute(eap)
15200 exarg_T *eap;
15201{
15202 char_u *arg = eap->arg;
Bram Moolenaar33570922005-01-25 22:26:29 +000015203 typval_T rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015204 int ret = OK;
15205 char_u *p;
15206 garray_T ga;
15207 int len;
15208 int save_did_emsg;
15209
15210 ga_init2(&ga, 1, 80);
15211
15212 if (eap->skip)
15213 ++emsg_skip;
15214 while (*arg != NUL && *arg != '|' && *arg != '\n')
15215 {
15216 p = arg;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015217 if (eval1(&arg, &rettv, !eap->skip) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000015218 {
15219 /*
15220 * Report the invalid expression unless the expression evaluation
15221 * has been cancelled due to an aborting error, an interrupt, or an
15222 * exception.
15223 */
15224 if (!aborting())
15225 EMSG2(_(e_invexpr2), p);
15226 ret = FAIL;
15227 break;
15228 }
15229
15230 if (!eap->skip)
15231 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015232 p = get_tv_string(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000015233 len = (int)STRLEN(p);
15234 if (ga_grow(&ga, len + 2) == FAIL)
15235 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015236 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000015237 ret = FAIL;
15238 break;
15239 }
15240 if (ga.ga_len)
Bram Moolenaar071d4272004-06-13 20:20:40 +000015241 ((char_u *)(ga.ga_data))[ga.ga_len++] = ' ';
Bram Moolenaar071d4272004-06-13 20:20:40 +000015242 STRCPY((char_u *)(ga.ga_data) + ga.ga_len, p);
Bram Moolenaar071d4272004-06-13 20:20:40 +000015243 ga.ga_len += len;
15244 }
15245
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015246 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000015247 arg = skipwhite(arg);
15248 }
15249
15250 if (ret != FAIL && ga.ga_data != NULL)
15251 {
15252 if (eap->cmdidx == CMD_echomsg)
15253 MSG_ATTR(ga.ga_data, echo_attr);
15254 else if (eap->cmdidx == CMD_echoerr)
15255 {
15256 /* We don't want to abort following commands, restore did_emsg. */
15257 save_did_emsg = did_emsg;
15258 EMSG((char_u *)ga.ga_data);
15259 if (!force_abort)
15260 did_emsg = save_did_emsg;
15261 }
15262 else if (eap->cmdidx == CMD_execute)
15263 do_cmdline((char_u *)ga.ga_data,
15264 eap->getline, eap->cookie, DOCMD_NOWAIT|DOCMD_VERBOSE);
15265 }
15266
15267 ga_clear(&ga);
15268
15269 if (eap->skip)
15270 --emsg_skip;
15271
15272 eap->nextcmd = check_nextcmd(arg);
15273}
15274
15275/*
15276 * Skip over the name of an option: "&option", "&g:option" or "&l:option".
15277 * "arg" points to the "&" or '+' when called, to "option" when returning.
15278 * Returns NULL when no option name found. Otherwise pointer to the char
15279 * after the option name.
15280 */
15281 static char_u *
15282find_option_end(arg, opt_flags)
15283 char_u **arg;
15284 int *opt_flags;
15285{
15286 char_u *p = *arg;
15287
15288 ++p;
15289 if (*p == 'g' && p[1] == ':')
15290 {
15291 *opt_flags = OPT_GLOBAL;
15292 p += 2;
15293 }
15294 else if (*p == 'l' && p[1] == ':')
15295 {
15296 *opt_flags = OPT_LOCAL;
15297 p += 2;
15298 }
15299 else
15300 *opt_flags = 0;
15301
15302 if (!ASCII_ISALPHA(*p))
15303 return NULL;
15304 *arg = p;
15305
15306 if (p[0] == 't' && p[1] == '_' && p[2] != NUL && p[3] != NUL)
15307 p += 4; /* termcap option */
15308 else
15309 while (ASCII_ISALPHA(*p))
15310 ++p;
15311 return p;
15312}
15313
15314/*
15315 * ":function"
15316 */
15317 void
15318ex_function(eap)
15319 exarg_T *eap;
15320{
15321 char_u *theline;
15322 int j;
15323 int c;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015324 int saved_did_emsg;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015325 char_u *name = NULL;
15326 char_u *p;
15327 char_u *arg;
15328 garray_T newargs;
15329 garray_T newlines;
15330 int varargs = FALSE;
15331 int mustend = FALSE;
15332 int flags = 0;
15333 ufunc_T *fp;
15334 int indent;
15335 int nesting;
15336 char_u *skip_until = NULL;
Bram Moolenaar33570922005-01-25 22:26:29 +000015337 dictitem_T *v;
15338 funcdict_T fudi;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000015339 static int func_nr = 0; /* number for nameless function */
15340 int paren;
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000015341 hashtab_T *ht;
15342 int todo;
15343 hashitem_T *hi;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015344
15345 /*
15346 * ":function" without argument: list functions.
15347 */
15348 if (ends_excmd(*eap->arg))
15349 {
15350 if (!eap->skip)
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000015351 {
Bram Moolenaar038eb0e2005-02-27 22:43:26 +000015352 todo = func_hashtab.ht_used;
15353 for (hi = func_hashtab.ht_array; todo > 0 && !got_int; ++hi)
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000015354 {
15355 if (!HASHITEM_EMPTY(hi))
15356 {
15357 --todo;
15358 fp = HI2UF(hi);
15359 if (!isdigit(*fp->uf_name))
15360 list_func_head(fp, FALSE);
15361 }
15362 }
15363 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000015364 eap->nextcmd = check_nextcmd(eap->arg);
15365 return;
15366 }
15367
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000015368 /*
15369 * Get the function name. There are these situations:
15370 * func normal function name
15371 * "name" == func, "fudi.fd_dict" == NULL
15372 * dict.func new dictionary entry
15373 * "name" == NULL, "fudi.fd_dict" set,
15374 * "fudi.fd_di" == NULL, "fudi.fd_newkey" == func
15375 * dict.func existing dict entry with a Funcref
15376 * "name" == fname, "fudi.fd_dict" set,
15377 * "fudi.fd_di" set, "fudi.fd_newkey" == NULL
15378 * dict.func existing dict entry that's not a Funcref
15379 * "name" == NULL, "fudi.fd_dict" set,
15380 * "fudi.fd_di" set, "fudi.fd_newkey" == NULL
15381 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000015382 p = eap->arg;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000015383 name = trans_function_name(&p, eap->skip, 0, &fudi);
15384 paren = (vim_strchr(p, '(') != NULL);
15385 if (name == NULL && (fudi.fd_dict == NULL || !paren) && !eap->skip)
Bram Moolenaar071d4272004-06-13 20:20:40 +000015386 {
15387 /*
15388 * Return on an invalid expression in braces, unless the expression
15389 * evaluation has been cancelled due to an aborting error, an
15390 * interrupt, or an exception.
15391 */
15392 if (!aborting())
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000015393 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000015394 if (!eap->skip && fudi.fd_newkey != NULL)
15395 EMSG2(_(e_dictkey), fudi.fd_newkey);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000015396 vim_free(fudi.fd_newkey);
Bram Moolenaar071d4272004-06-13 20:20:40 +000015397 return;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000015398 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000015399 else
15400 eap->skip = TRUE;
15401 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000015402 /* An error in a function call during evaluation of an expression in magic
15403 * braces should not cause the function not to be defined. */
15404 saved_did_emsg = did_emsg;
15405 did_emsg = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015406
15407 /*
15408 * ":function func" with only function name: list function.
15409 */
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000015410 if (!paren)
Bram Moolenaar071d4272004-06-13 20:20:40 +000015411 {
15412 if (!ends_excmd(*skipwhite(p)))
15413 {
15414 EMSG(_(e_trailing));
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000015415 goto ret_free;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015416 }
15417 eap->nextcmd = check_nextcmd(p);
15418 if (eap->nextcmd != NULL)
15419 *p = NUL;
15420 if (!eap->skip && !got_int)
15421 {
15422 fp = find_func(name);
15423 if (fp != NULL)
15424 {
15425 list_func_head(fp, TRUE);
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000015426 for (j = 0; j < fp->uf_lines.ga_len && !got_int; ++j)
Bram Moolenaar071d4272004-06-13 20:20:40 +000015427 {
15428 msg_putchar('\n');
15429 msg_outnum((long)(j + 1));
15430 if (j < 9)
15431 msg_putchar(' ');
15432 if (j < 99)
15433 msg_putchar(' ');
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000015434 msg_prt_line(FUNCLINE(fp, j), FALSE);
Bram Moolenaar071d4272004-06-13 20:20:40 +000015435 out_flush(); /* show a line at a time */
15436 ui_breakcheck();
15437 }
15438 if (!got_int)
15439 {
15440 msg_putchar('\n');
15441 msg_puts((char_u *)" endfunction");
15442 }
15443 }
15444 else
Bram Moolenaar81bf7082005-02-12 14:31:42 +000015445 emsg_funcname("E123: Undefined function: %s", name);
Bram Moolenaar071d4272004-06-13 20:20:40 +000015446 }
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000015447 goto ret_free;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015448 }
15449
15450 /*
15451 * ":function name(arg1, arg2)" Define function.
15452 */
15453 p = skipwhite(p);
15454 if (*p != '(')
15455 {
15456 if (!eap->skip)
15457 {
15458 EMSG2(_("E124: Missing '(': %s"), eap->arg);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000015459 goto ret_free;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015460 }
15461 /* attempt to continue by skipping some text */
15462 if (vim_strchr(p, '(') != NULL)
15463 p = vim_strchr(p, '(');
15464 }
15465 p = skipwhite(p + 1);
15466
15467 ga_init2(&newargs, (int)sizeof(char_u *), 3);
15468 ga_init2(&newlines, (int)sizeof(char_u *), 3);
15469
15470 /*
15471 * Isolate the arguments: "arg1, arg2, ...)"
15472 */
15473 while (*p != ')')
15474 {
15475 if (p[0] == '.' && p[1] == '.' && p[2] == '.')
15476 {
15477 varargs = TRUE;
15478 p += 3;
15479 mustend = TRUE;
15480 }
15481 else
15482 {
15483 arg = p;
15484 while (ASCII_ISALNUM(*p) || *p == '_')
15485 ++p;
15486 if (arg == p || isdigit(*arg)
15487 || (p - arg == 9 && STRNCMP(arg, "firstline", 9) == 0)
15488 || (p - arg == 8 && STRNCMP(arg, "lastline", 8) == 0))
15489 {
15490 if (!eap->skip)
15491 EMSG2(_("E125: Illegal argument: %s"), arg);
15492 break;
15493 }
15494 if (ga_grow(&newargs, 1) == FAIL)
15495 goto erret;
15496 c = *p;
15497 *p = NUL;
15498 arg = vim_strsave(arg);
15499 if (arg == NULL)
15500 goto erret;
15501 ((char_u **)(newargs.ga_data))[newargs.ga_len] = arg;
15502 *p = c;
15503 newargs.ga_len++;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015504 if (*p == ',')
15505 ++p;
15506 else
15507 mustend = TRUE;
15508 }
15509 p = skipwhite(p);
15510 if (mustend && *p != ')')
15511 {
15512 if (!eap->skip)
15513 EMSG2(_(e_invarg2), eap->arg);
15514 break;
15515 }
15516 }
15517 ++p; /* skip the ')' */
15518
Bram Moolenaare9a41262005-01-15 22:18:47 +000015519 /* find extra arguments "range", "dict" and "abort" */
Bram Moolenaar071d4272004-06-13 20:20:40 +000015520 for (;;)
15521 {
15522 p = skipwhite(p);
15523 if (STRNCMP(p, "range", 5) == 0)
15524 {
15525 flags |= FC_RANGE;
15526 p += 5;
15527 }
Bram Moolenaare9a41262005-01-15 22:18:47 +000015528 else if (STRNCMP(p, "dict", 4) == 0)
15529 {
15530 flags |= FC_DICT;
15531 p += 4;
15532 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000015533 else if (STRNCMP(p, "abort", 5) == 0)
15534 {
15535 flags |= FC_ABORT;
15536 p += 5;
15537 }
15538 else
15539 break;
15540 }
15541
15542 if (*p != NUL && *p != '"' && *p != '\n' && !eap->skip && !did_emsg)
15543 EMSG(_(e_trailing));
15544
15545 /*
15546 * Read the body of the function, until ":endfunction" is found.
15547 */
15548 if (KeyTyped)
15549 {
15550 /* Check if the function already exists, don't let the user type the
15551 * whole function before telling him it doesn't work! For a script we
15552 * need to skip the body to be able to find what follows. */
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000015553 if (!eap->skip && !eap->forceit)
15554 {
15555 if (fudi.fd_dict != NULL && fudi.fd_newkey == NULL)
15556 EMSG(_(e_funcdict));
15557 else if (name != NULL && find_func(name) != NULL)
Bram Moolenaar81bf7082005-02-12 14:31:42 +000015558 emsg_funcname(e_funcexts, name);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000015559 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000015560
15561 msg_putchar('\n'); /* don't overwrite the function name */
15562 cmdline_row = msg_row;
15563 }
15564
15565 indent = 2;
15566 nesting = 0;
15567 for (;;)
15568 {
15569 msg_scroll = TRUE;
15570 need_wait_return = FALSE;
15571 if (eap->getline == NULL)
15572 theline = getcmdline(':', 0L, indent);
15573 else
15574 theline = eap->getline(':', eap->cookie, indent);
15575 if (KeyTyped)
15576 lines_left = Rows - 1;
15577 if (theline == NULL)
15578 {
15579 EMSG(_("E126: Missing :endfunction"));
15580 goto erret;
15581 }
15582
15583 if (skip_until != NULL)
15584 {
15585 /* between ":append" and "." and between ":python <<EOF" and "EOF"
15586 * don't check for ":endfunc". */
15587 if (STRCMP(theline, skip_until) == 0)
15588 {
15589 vim_free(skip_until);
15590 skip_until = NULL;
15591 }
15592 }
15593 else
15594 {
15595 /* skip ':' and blanks*/
15596 for (p = theline; vim_iswhite(*p) || *p == ':'; ++p)
15597 ;
15598
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000015599 /* Check for "endfunction". */
15600 if (checkforcmd(&p, "endfunction", 4) && nesting-- == 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +000015601 {
15602 vim_free(theline);
15603 break;
15604 }
15605
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000015606 /* Increase indent inside "if", "while", "for" and "try", decrease
Bram Moolenaar071d4272004-06-13 20:20:40 +000015607 * at "end". */
15608 if (indent > 2 && STRNCMP(p, "end", 3) == 0)
15609 indent -= 2;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000015610 else if (STRNCMP(p, "if", 2) == 0
15611 || STRNCMP(p, "wh", 2) == 0
15612 || STRNCMP(p, "for", 3) == 0
Bram Moolenaar071d4272004-06-13 20:20:40 +000015613 || STRNCMP(p, "try", 3) == 0)
15614 indent += 2;
15615
15616 /* Check for defining a function inside this function. */
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000015617 if (checkforcmd(&p, "function", 2))
Bram Moolenaar071d4272004-06-13 20:20:40 +000015618 {
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000015619 if (*p == '!')
15620 p = skipwhite(p + 1);
Bram Moolenaar071d4272004-06-13 20:20:40 +000015621 p += eval_fname_script(p);
15622 if (ASCII_ISALPHA(*p))
15623 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000015624 vim_free(trans_function_name(&p, TRUE, 0, NULL));
Bram Moolenaar071d4272004-06-13 20:20:40 +000015625 if (*skipwhite(p) == '(')
15626 {
15627 ++nesting;
15628 indent += 2;
15629 }
15630 }
15631 }
15632
15633 /* Check for ":append" or ":insert". */
15634 p = skip_range(p, NULL);
15635 if ((p[0] == 'a' && (!ASCII_ISALPHA(p[1]) || p[1] == 'p'))
15636 || (p[0] == 'i'
15637 && (!ASCII_ISALPHA(p[1]) || (p[1] == 'n'
15638 && (!ASCII_ISALPHA(p[2]) || (p[2] == 's'))))))
15639 skip_until = vim_strsave((char_u *)".");
15640
15641 /* Check for ":python <<EOF", ":tcl <<EOF", etc. */
15642 arg = skipwhite(skiptowhite(p));
15643 if (arg[0] == '<' && arg[1] =='<'
15644 && ((p[0] == 'p' && p[1] == 'y'
15645 && (!ASCII_ISALPHA(p[2]) || p[2] == 't'))
15646 || (p[0] == 'p' && p[1] == 'e'
15647 && (!ASCII_ISALPHA(p[2]) || p[2] == 'r'))
15648 || (p[0] == 't' && p[1] == 'c'
15649 && (!ASCII_ISALPHA(p[2]) || p[2] == 'l'))
15650 || (p[0] == 'r' && p[1] == 'u' && p[2] == 'b'
15651 && (!ASCII_ISALPHA(p[3]) || p[3] == 'y'))
Bram Moolenaar325b7a22004-07-05 15:58:32 +000015652 || (p[0] == 'm' && p[1] == 'z'
15653 && (!ASCII_ISALPHA(p[2]) || p[2] == 's'))
Bram Moolenaar071d4272004-06-13 20:20:40 +000015654 ))
15655 {
15656 /* ":python <<" continues until a dot, like ":append" */
15657 p = skipwhite(arg + 2);
15658 if (*p == NUL)
15659 skip_until = vim_strsave((char_u *)".");
15660 else
15661 skip_until = vim_strsave(p);
15662 }
15663 }
15664
15665 /* Add the line to the function. */
15666 if (ga_grow(&newlines, 1) == FAIL)
15667 goto erret;
15668 ((char_u **)(newlines.ga_data))[newlines.ga_len] = theline;
15669 newlines.ga_len++;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015670 }
15671
15672 /* Don't define the function when skipping commands or when an error was
15673 * detected. */
15674 if (eap->skip || did_emsg)
15675 goto erret;
15676
15677 /*
15678 * If there are no errors, add the function
15679 */
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000015680 if (fudi.fd_dict == NULL)
Bram Moolenaar49cd9572005-01-03 21:06:01 +000015681 {
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000015682 v = find_var(name, &ht);
Bram Moolenaar33570922005-01-25 22:26:29 +000015683 if (v != NULL && v->di_tv.v_type == VAR_FUNC)
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000015684 {
Bram Moolenaar81bf7082005-02-12 14:31:42 +000015685 emsg_funcname("E707: Function name conflicts with variable: %s",
15686 name);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000015687 goto erret;
15688 }
Bram Moolenaar49cd9572005-01-03 21:06:01 +000015689
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000015690 fp = find_func(name);
15691 if (fp != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000015692 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000015693 if (!eap->forceit)
15694 {
Bram Moolenaar81bf7082005-02-12 14:31:42 +000015695 emsg_funcname(e_funcexts, name);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000015696 goto erret;
15697 }
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000015698 if (fp->uf_calls > 0)
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000015699 {
Bram Moolenaar81bf7082005-02-12 14:31:42 +000015700 emsg_funcname("E127: Cannot redefine function %s: It is in use",
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000015701 name);
15702 goto erret;
15703 }
15704 /* redefine existing function */
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000015705 ga_clear_strings(&(fp->uf_args));
15706 ga_clear_strings(&(fp->uf_lines));
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000015707 vim_free(name);
15708 name = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015709 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000015710 }
15711 else
15712 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000015713 char numbuf[20];
15714
15715 fp = NULL;
15716 if (fudi.fd_newkey == NULL && !eap->forceit)
15717 {
15718 EMSG(_(e_funcdict));
15719 goto erret;
15720 }
Bram Moolenaar758711c2005-02-02 23:11:38 +000015721 if (fudi.fd_di == NULL)
15722 {
15723 /* Can't add a function to a locked dictionary */
15724 if (tv_check_lock(fudi.fd_dict->dv_lock, eap->arg))
15725 goto erret;
15726 }
15727 /* Can't change an existing function if it is locked */
15728 else if (tv_check_lock(fudi.fd_di->di_tv.v_lock, eap->arg))
15729 goto erret;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000015730
15731 /* Give the function a sequential number. Can only be used with a
15732 * Funcref! */
15733 vim_free(name);
15734 sprintf(numbuf, "%d", ++func_nr);
15735 name = vim_strsave((char_u *)numbuf);
15736 if (name == NULL)
15737 goto erret;
15738 }
15739
15740 if (fp == NULL)
15741 {
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000015742 if (fudi.fd_dict == NULL && vim_strchr(name, ':') != NULL)
15743 {
15744 int slen, plen;
15745 char_u *scriptname;
15746
15747 /* Check that the autoload name matches the script name. */
15748 j = FAIL;
15749 if (sourcing_name != NULL)
15750 {
15751 scriptname = autoload_name(name);
15752 if (scriptname != NULL)
15753 {
15754 p = vim_strchr(scriptname, '/');
15755 plen = STRLEN(p);
15756 slen = STRLEN(sourcing_name);
15757 if (slen > plen && fnamecmp(p,
15758 sourcing_name + slen - plen) == 0)
15759 j = OK;
15760 vim_free(scriptname);
15761 }
15762 }
15763 if (j == FAIL)
15764 {
15765 EMSG2(_("E746: Function name does not match script file name: %s"), name);
15766 goto erret;
15767 }
15768 }
15769
15770 fp = (ufunc_T *)alloc((unsigned)(sizeof(ufunc_T) + STRLEN(name)));
Bram Moolenaar071d4272004-06-13 20:20:40 +000015771 if (fp == NULL)
15772 goto erret;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000015773
15774 if (fudi.fd_dict != NULL)
15775 {
15776 if (fudi.fd_di == NULL)
15777 {
15778 /* add new dict entry */
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000015779 fudi.fd_di = dictitem_alloc(fudi.fd_newkey);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000015780 if (fudi.fd_di == NULL)
15781 {
15782 vim_free(fp);
15783 goto erret;
15784 }
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000015785 if (dict_add(fudi.fd_dict, fudi.fd_di) == FAIL)
15786 {
15787 vim_free(fudi.fd_di);
15788 goto erret;
15789 }
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000015790 }
15791 else
15792 /* overwrite existing dict entry */
15793 clear_tv(&fudi.fd_di->di_tv);
15794 fudi.fd_di->di_tv.v_type = VAR_FUNC;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000015795 fudi.fd_di->di_tv.v_lock = 0;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000015796 fudi.fd_di->di_tv.vval.v_string = vim_strsave(name);
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000015797 fp->uf_refcount = 1;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000015798 }
15799
Bram Moolenaar071d4272004-06-13 20:20:40 +000015800 /* insert the new function in the function list */
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000015801 STRCPY(fp->uf_name, name);
15802 hash_add(&func_hashtab, UF2HIKEY(fp));
Bram Moolenaar071d4272004-06-13 20:20:40 +000015803 }
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000015804 fp->uf_args = newargs;
15805 fp->uf_lines = newlines;
Bram Moolenaar05159a02005-02-26 23:04:13 +000015806#ifdef FEAT_PROFILE
15807 fp->uf_tml_count = NULL;
15808 fp->uf_tml_total = NULL;
15809 fp->uf_tml_self = NULL;
15810 fp->uf_profiling = FALSE;
15811 if (prof_def_func())
15812 func_do_profile(fp);
15813#endif
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000015814 fp->uf_varargs = varargs;
15815 fp->uf_flags = flags;
15816 fp->uf_calls = 0;
15817 fp->uf_script_ID = current_SID;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000015818 goto ret_free;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015819
15820erret:
Bram Moolenaar071d4272004-06-13 20:20:40 +000015821 ga_clear_strings(&newargs);
15822 ga_clear_strings(&newlines);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000015823ret_free:
15824 vim_free(skip_until);
15825 vim_free(fudi.fd_newkey);
Bram Moolenaar071d4272004-06-13 20:20:40 +000015826 vim_free(name);
Bram Moolenaar071d4272004-06-13 20:20:40 +000015827 did_emsg |= saved_did_emsg;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015828}
15829
15830/*
15831 * Get a function name, translating "<SID>" and "<SNR>".
Bram Moolenaara7043832005-01-21 11:56:39 +000015832 * Also handles a Funcref in a List or Dictionary.
Bram Moolenaar071d4272004-06-13 20:20:40 +000015833 * Returns the function name in allocated memory, or NULL for failure.
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000015834 * flags:
15835 * TFN_INT: internal function name OK
15836 * TFN_QUIET: be quiet
Bram Moolenaar071d4272004-06-13 20:20:40 +000015837 * Advances "pp" to just after the function name (if no error).
15838 */
15839 static char_u *
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000015840trans_function_name(pp, skip, flags, fdp)
Bram Moolenaar071d4272004-06-13 20:20:40 +000015841 char_u **pp;
15842 int skip; /* only find the end, don't evaluate */
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000015843 int flags;
Bram Moolenaar33570922005-01-25 22:26:29 +000015844 funcdict_T *fdp; /* return: info about dictionary used */
Bram Moolenaar071d4272004-06-13 20:20:40 +000015845{
Bram Moolenaar7480b5c2005-01-16 22:07:38 +000015846 char_u *name = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015847 char_u *start;
15848 char_u *end;
15849 int lead;
15850 char_u sid_buf[20];
Bram Moolenaar071d4272004-06-13 20:20:40 +000015851 int len;
Bram Moolenaar33570922005-01-25 22:26:29 +000015852 lval_T lv;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000015853
15854 if (fdp != NULL)
Bram Moolenaar33570922005-01-25 22:26:29 +000015855 vim_memset(fdp, 0, sizeof(funcdict_T));
Bram Moolenaar071d4272004-06-13 20:20:40 +000015856 start = *pp;
Bram Moolenaara7043832005-01-21 11:56:39 +000015857
15858 /* Check for hard coded <SNR>: already translated function ID (from a user
15859 * command). */
15860 if ((*pp)[0] == K_SPECIAL && (*pp)[1] == KS_EXTRA
15861 && (*pp)[2] == (int)KE_SNR)
15862 {
15863 *pp += 3;
15864 len = get_id_len(pp) + 3;
15865 return vim_strnsave(start, len);
15866 }
15867
15868 /* A name starting with "<SID>" or "<SNR>" is local to a script. But
15869 * don't skip over "s:", get_lval() needs it for "s:dict.func". */
Bram Moolenaar071d4272004-06-13 20:20:40 +000015870 lead = eval_fname_script(start);
Bram Moolenaara7043832005-01-21 11:56:39 +000015871 if (lead > 2)
Bram Moolenaar071d4272004-06-13 20:20:40 +000015872 start += lead;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +000015873
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000015874 end = get_lval(start, NULL, &lv, FALSE, skip, flags & TFN_QUIET);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +000015875 if (end == start)
15876 {
15877 if (!skip)
15878 EMSG(_("E129: Function name required"));
15879 goto theend;
15880 }
Bram Moolenaara7043832005-01-21 11:56:39 +000015881 if (end == NULL || (lv.ll_tv != NULL && (lead > 2 || lv.ll_range)))
Bram Moolenaar7480b5c2005-01-16 22:07:38 +000015882 {
15883 /*
15884 * Report an invalid expression in braces, unless the expression
15885 * evaluation has been cancelled due to an aborting error, an
15886 * interrupt, or an exception.
15887 */
15888 if (!aborting())
15889 {
15890 if (end != NULL)
15891 EMSG2(_(e_invarg2), start);
15892 }
15893 else
15894 *pp = find_name_end(start, NULL, NULL, TRUE);
15895 goto theend;
15896 }
15897
15898 if (lv.ll_tv != NULL)
15899 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000015900 if (fdp != NULL)
15901 {
15902 fdp->fd_dict = lv.ll_dict;
15903 fdp->fd_newkey = lv.ll_newkey;
15904 lv.ll_newkey = NULL;
15905 fdp->fd_di = lv.ll_di;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000015906 }
Bram Moolenaar7480b5c2005-01-16 22:07:38 +000015907 if (lv.ll_tv->v_type == VAR_FUNC && lv.ll_tv->vval.v_string != NULL)
15908 {
15909 name = vim_strsave(lv.ll_tv->vval.v_string);
15910 *pp = end;
15911 }
15912 else
15913 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000015914 if (!skip && !(flags & TFN_QUIET) && (fdp == NULL
15915 || lv.ll_dict == NULL || fdp->fd_newkey == NULL))
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000015916 EMSG(_(e_funcref));
15917 else
15918 *pp = end;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +000015919 name = NULL;
15920 }
15921 goto theend;
15922 }
15923
15924 if (lv.ll_name == NULL)
15925 {
15926 /* Error found, but continue after the function name. */
15927 *pp = end;
15928 goto theend;
15929 }
15930
15931 if (lv.ll_exp_name != NULL)
15932 len = STRLEN(lv.ll_exp_name);
15933 else
Bram Moolenaara7043832005-01-21 11:56:39 +000015934 {
15935 if (lead == 2) /* skip over "s:" */
15936 lv.ll_name += 2;
15937 len = (int)(end - lv.ll_name);
15938 }
Bram Moolenaar7480b5c2005-01-16 22:07:38 +000015939
15940 /*
15941 * Copy the function name to allocated memory.
15942 * Accept <SID>name() inside a script, translate into <SNR>123_name().
15943 * Accept <SNR>123_name() outside a script.
15944 */
15945 if (skip)
15946 lead = 0; /* do nothing */
15947 else if (lead > 0)
15948 {
15949 lead = 3;
15950 if (eval_fname_sid(*pp)) /* If it's "<SID>" */
15951 {
15952 if (current_SID <= 0)
15953 {
15954 EMSG(_(e_usingsid));
15955 goto theend;
15956 }
15957 sprintf((char *)sid_buf, "%ld_", (long)current_SID);
15958 lead += (int)STRLEN(sid_buf);
15959 }
15960 }
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +000015961 else if (!(flags & TFN_INT) && builtin_function(lv.ll_name))
Bram Moolenaar7480b5c2005-01-16 22:07:38 +000015962 {
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +000015963 EMSG2(_("E128: Function name must start with a capital or contain a colon: %s"), lv.ll_name);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +000015964 goto theend;
15965 }
15966 name = alloc((unsigned)(len + lead + 1));
15967 if (name != NULL)
15968 {
15969 if (lead > 0)
15970 {
15971 name[0] = K_SPECIAL;
15972 name[1] = KS_EXTRA;
15973 name[2] = (int)KE_SNR;
Bram Moolenaara7043832005-01-21 11:56:39 +000015974 if (lead > 3) /* If it's "<SID>" */
Bram Moolenaar7480b5c2005-01-16 22:07:38 +000015975 STRCPY(name + 3, sid_buf);
15976 }
15977 mch_memmove(name + lead, lv.ll_name, (size_t)len);
15978 name[len + lead] = NUL;
15979 }
15980 *pp = end;
15981
15982theend:
15983 clear_lval(&lv);
15984 return name;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015985}
15986
15987/*
15988 * Return 5 if "p" starts with "<SID>" or "<SNR>" (ignoring case).
15989 * Return 2 if "p" starts with "s:".
15990 * Return 0 otherwise.
15991 */
15992 static int
15993eval_fname_script(p)
15994 char_u *p;
15995{
15996 if (p[0] == '<' && (STRNICMP(p + 1, "SID>", 4) == 0
15997 || STRNICMP(p + 1, "SNR>", 4) == 0))
15998 return 5;
15999 if (p[0] == 's' && p[1] == ':')
16000 return 2;
16001 return 0;
16002}
16003
16004/*
16005 * Return TRUE if "p" starts with "<SID>" or "s:".
16006 * Only works if eval_fname_script() returned non-zero for "p"!
16007 */
16008 static int
16009eval_fname_sid(p)
16010 char_u *p;
16011{
16012 return (*p == 's' || TOUPPER_ASC(p[2]) == 'I');
16013}
16014
16015/*
16016 * List the head of the function: "name(arg1, arg2)".
16017 */
16018 static void
16019list_func_head(fp, indent)
16020 ufunc_T *fp;
16021 int indent;
16022{
16023 int j;
16024
16025 msg_start();
16026 if (indent)
16027 MSG_PUTS(" ");
16028 MSG_PUTS("function ");
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000016029 if (fp->uf_name[0] == K_SPECIAL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000016030 {
16031 MSG_PUTS_ATTR("<SNR>", hl_attr(HLF_8));
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000016032 msg_puts(fp->uf_name + 3);
Bram Moolenaar071d4272004-06-13 20:20:40 +000016033 }
16034 else
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000016035 msg_puts(fp->uf_name);
Bram Moolenaar071d4272004-06-13 20:20:40 +000016036 msg_putchar('(');
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000016037 for (j = 0; j < fp->uf_args.ga_len; ++j)
Bram Moolenaar071d4272004-06-13 20:20:40 +000016038 {
16039 if (j)
16040 MSG_PUTS(", ");
16041 msg_puts(FUNCARG(fp, j));
16042 }
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000016043 if (fp->uf_varargs)
Bram Moolenaar071d4272004-06-13 20:20:40 +000016044 {
16045 if (j)
16046 MSG_PUTS(", ");
16047 MSG_PUTS("...");
16048 }
16049 msg_putchar(')');
16050}
16051
16052/*
16053 * Find a function by name, return pointer to it in ufuncs.
16054 * Return NULL for unknown function.
16055 */
16056 static ufunc_T *
16057find_func(name)
16058 char_u *name;
16059{
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000016060 hashitem_T *hi;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016061
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000016062 hi = hash_find(&func_hashtab, name);
16063 if (!HASHITEM_EMPTY(hi))
16064 return HI2UF(hi);
16065 return NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016066}
16067
Bram Moolenaar49cd9572005-01-03 21:06:01 +000016068/*
16069 * Return TRUE if a function "name" exists.
16070 */
16071 static int
16072function_exists(name)
16073 char_u *name;
16074{
16075 char_u *p = name;
16076 int n = FALSE;
16077
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000016078 p = trans_function_name(&p, FALSE, TFN_INT|TFN_QUIET, NULL);
Bram Moolenaar49cd9572005-01-03 21:06:01 +000016079 if (p != NULL)
16080 {
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +000016081 if (builtin_function(p))
Bram Moolenaar49cd9572005-01-03 21:06:01 +000016082 n = (find_internal_func(p) >= 0);
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +000016083 else
16084 n = (find_func(p) != NULL);
Bram Moolenaar49cd9572005-01-03 21:06:01 +000016085 vim_free(p);
16086 }
16087 return n;
16088}
16089
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +000016090/*
16091 * Return TRUE if "name" looks like a builtin function name: starts with a
16092 * lower case letter and doesn't contain a ':'.
16093 */
16094 static int
16095builtin_function(name)
16096 char_u *name;
16097{
16098 return ASCII_ISLOWER(name[0]) && vim_strchr(name, ':') == NULL;
16099}
16100
Bram Moolenaar05159a02005-02-26 23:04:13 +000016101#if defined(FEAT_PROFILE) || defined(PROTO)
16102/*
16103 * Start profiling function "fp".
16104 */
16105 static void
16106func_do_profile(fp)
16107 ufunc_T *fp;
16108{
16109 fp->uf_tm_count = 0;
16110 profile_zero(&fp->uf_tm_self);
16111 profile_zero(&fp->uf_tm_total);
16112 if (fp->uf_tml_count == NULL)
16113 fp->uf_tml_count = (int *)alloc_clear((unsigned)
16114 (sizeof(int) * fp->uf_lines.ga_len));
16115 if (fp->uf_tml_total == NULL)
16116 fp->uf_tml_total = (proftime_T *)alloc_clear((unsigned)
16117 (sizeof(proftime_T) * fp->uf_lines.ga_len));
16118 if (fp->uf_tml_self == NULL)
16119 fp->uf_tml_self = (proftime_T *)alloc_clear((unsigned)
16120 (sizeof(proftime_T) * fp->uf_lines.ga_len));
16121 fp->uf_tml_idx = -1;
16122 if (fp->uf_tml_count == NULL || fp->uf_tml_total == NULL
16123 || fp->uf_tml_self == NULL)
16124 return; /* out of memory */
16125
16126 fp->uf_profiling = TRUE;
16127}
16128
16129/*
16130 * Dump the profiling results for all functions in file "fd".
16131 */
16132 void
16133func_dump_profile(fd)
16134 FILE *fd;
16135{
16136 hashitem_T *hi;
16137 int todo;
16138 ufunc_T *fp;
16139 int i;
Bram Moolenaar73830342005-02-28 22:48:19 +000016140 ufunc_T **sorttab;
16141 int st_len = 0;
Bram Moolenaar05159a02005-02-26 23:04:13 +000016142
16143 todo = func_hashtab.ht_used;
Bram Moolenaar73830342005-02-28 22:48:19 +000016144 sorttab = (ufunc_T **)alloc((unsigned)(sizeof(ufunc_T) * todo));
16145
Bram Moolenaar05159a02005-02-26 23:04:13 +000016146 for (hi = func_hashtab.ht_array; todo > 0; ++hi)
16147 {
16148 if (!HASHITEM_EMPTY(hi))
16149 {
16150 --todo;
16151 fp = HI2UF(hi);
16152 if (fp->uf_profiling)
16153 {
Bram Moolenaar73830342005-02-28 22:48:19 +000016154 if (sorttab != NULL)
16155 sorttab[st_len++] = fp;
16156
Bram Moolenaar05159a02005-02-26 23:04:13 +000016157 if (fp->uf_name[0] == K_SPECIAL)
16158 fprintf(fd, "FUNCTION <SNR>%s()\n", fp->uf_name + 3);
16159 else
16160 fprintf(fd, "FUNCTION %s()\n", fp->uf_name);
16161 if (fp->uf_tm_count == 1)
16162 fprintf(fd, "Called 1 time\n");
16163 else
16164 fprintf(fd, "Called %d times\n", fp->uf_tm_count);
16165 fprintf(fd, "Total time: %s\n", profile_msg(&fp->uf_tm_total));
16166 fprintf(fd, " Self time: %s\n", profile_msg(&fp->uf_tm_self));
16167 fprintf(fd, "\n");
16168 fprintf(fd, "count total (s) self (s)\n");
16169
16170 for (i = 0; i < fp->uf_lines.ga_len; ++i)
16171 {
Bram Moolenaar73830342005-02-28 22:48:19 +000016172 prof_func_line(fd, fp->uf_tml_count[i],
16173 &fp->uf_tml_total[i], &fp->uf_tml_self[i], TRUE);
Bram Moolenaar05159a02005-02-26 23:04:13 +000016174 fprintf(fd, "%s\n", FUNCLINE(fp, i));
16175 }
16176 fprintf(fd, "\n");
16177 }
16178 }
16179 }
Bram Moolenaar73830342005-02-28 22:48:19 +000016180
16181 if (sorttab != NULL && st_len > 0)
16182 {
16183 qsort((void *)sorttab, (size_t)st_len, sizeof(ufunc_T *),
16184 prof_total_cmp);
16185 prof_sort_list(fd, sorttab, st_len, "TOTAL", FALSE);
16186 qsort((void *)sorttab, (size_t)st_len, sizeof(ufunc_T *),
16187 prof_self_cmp);
16188 prof_sort_list(fd, sorttab, st_len, "SELF", TRUE);
16189 }
Bram Moolenaar05159a02005-02-26 23:04:13 +000016190}
Bram Moolenaar73830342005-02-28 22:48:19 +000016191
16192 static void
16193prof_sort_list(fd, sorttab, st_len, title, prefer_self)
16194 FILE *fd;
16195 ufunc_T **sorttab;
16196 int st_len;
16197 char *title;
16198 int prefer_self; /* when equal print only self time */
16199{
16200 int i;
16201 ufunc_T *fp;
16202
16203 fprintf(fd, "FUNCTIONS SORTED ON %s TIME\n", title);
16204 fprintf(fd, "count total (s) self (s) function\n");
16205 for (i = 0; i < 20 && i < st_len; ++i)
16206 {
16207 fp = sorttab[i];
16208 prof_func_line(fd, fp->uf_tm_count, &fp->uf_tm_total, &fp->uf_tm_self,
16209 prefer_self);
16210 if (fp->uf_name[0] == K_SPECIAL)
16211 fprintf(fd, " <SNR>%s()\n", fp->uf_name + 3);
16212 else
16213 fprintf(fd, " %s()\n", fp->uf_name);
16214 }
16215 fprintf(fd, "\n");
16216}
16217
16218/*
16219 * Print the count and times for one function or function line.
16220 */
16221 static void
16222prof_func_line(fd, count, total, self, prefer_self)
16223 FILE *fd;
16224 int count;
16225 proftime_T *total;
16226 proftime_T *self;
16227 int prefer_self; /* when equal print only self time */
16228{
16229 if (count > 0)
16230 {
16231 fprintf(fd, "%5d ", count);
16232 if (prefer_self && profile_equal(total, self))
16233 fprintf(fd, " ");
16234 else
16235 fprintf(fd, "%s ", profile_msg(total));
16236 if (!prefer_self && profile_equal(total, self))
16237 fprintf(fd, " ");
16238 else
16239 fprintf(fd, "%s ", profile_msg(self));
16240 }
16241 else
16242 fprintf(fd, " ");
16243}
16244
16245/*
16246 * Compare function for total time sorting.
16247 */
16248 static int
16249#ifdef __BORLANDC__
16250_RTLENTRYF
16251#endif
16252prof_total_cmp(s1, s2)
16253 const void *s1;
16254 const void *s2;
16255{
16256 ufunc_T *p1, *p2;
16257
16258 p1 = *(ufunc_T **)s1;
16259 p2 = *(ufunc_T **)s2;
16260 return profile_cmp(&p1->uf_tm_total, &p2->uf_tm_total);
16261}
16262
16263/*
16264 * Compare function for self time sorting.
16265 */
16266 static int
16267#ifdef __BORLANDC__
16268_RTLENTRYF
16269#endif
16270prof_self_cmp(s1, s2)
16271 const void *s1;
16272 const void *s2;
16273{
16274 ufunc_T *p1, *p2;
16275
16276 p1 = *(ufunc_T **)s1;
16277 p2 = *(ufunc_T **)s2;
16278 return profile_cmp(&p1->uf_tm_self, &p2->uf_tm_self);
16279}
16280
Bram Moolenaar05159a02005-02-26 23:04:13 +000016281#endif
16282
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +000016283/*
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000016284 * If "name" has a package name try autoloading the script for it.
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +000016285 * Return TRUE if a package was loaded.
16286 */
16287 static int
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000016288script_autoload(name)
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +000016289 char_u *name;
16290{
16291 char_u *p;
16292 char_u *scriptname;
16293 int ret = FALSE;
16294
16295 /* If there is no colon after name[1] there is no package name. */
16296 p = vim_strchr(name, ':');
16297 if (p == NULL || p <= name + 2)
16298 return FALSE;
16299
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000016300 /* Try loading the package from $VIMRUNTIME/autoload/<name>.vim */
16301 scriptname = autoload_name(name);
16302 if (cmd_runtime(scriptname, FALSE) == OK)
16303 ret = TRUE;
16304
16305 vim_free(scriptname);
16306 return ret;
16307}
16308
16309/*
16310 * Return the autoload script name for a function or variable name.
16311 * Returns NULL when out of memory.
16312 */
16313 static char_u *
16314autoload_name(name)
16315 char_u *name;
16316{
16317 char_u *p;
16318 char_u *scriptname;
16319
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +000016320 /* Get the script file name: replace ':' with '/', append ".vim". */
16321 scriptname = alloc((unsigned)(STRLEN(name) + 14));
16322 if (scriptname == NULL)
16323 return FALSE;
16324 STRCPY(scriptname, "autoload/");
16325 STRCAT(scriptname, name);
16326 *vim_strrchr(scriptname, ':') = NUL;
16327 STRCAT(scriptname, ".vim");
16328 while ((p = vim_strchr(scriptname, ':')) != NULL)
16329 *p = '/';
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000016330 return scriptname;
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +000016331}
16332
Bram Moolenaar071d4272004-06-13 20:20:40 +000016333#if defined(FEAT_CMDL_COMPL) || defined(PROTO)
16334
16335/*
16336 * Function given to ExpandGeneric() to obtain the list of user defined
16337 * function names.
16338 */
16339 char_u *
16340get_user_func_name(xp, idx)
16341 expand_T *xp;
16342 int idx;
16343{
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000016344 static long_u done;
16345 static hashitem_T *hi;
16346 ufunc_T *fp;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016347
16348 if (idx == 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +000016349 {
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000016350 done = 0;
16351 hi = func_hashtab.ht_array;
16352 }
16353 if (done < func_hashtab.ht_used)
16354 {
16355 if (done++ > 0)
16356 ++hi;
16357 while (HASHITEM_EMPTY(hi))
16358 ++hi;
16359 fp = HI2UF(hi);
16360
16361 if (STRLEN(fp->uf_name) + 4 >= IOSIZE)
16362 return fp->uf_name; /* prevents overflow */
Bram Moolenaar071d4272004-06-13 20:20:40 +000016363
16364 cat_func_name(IObuff, fp);
16365 if (xp->xp_context != EXPAND_USER_FUNC)
16366 {
16367 STRCAT(IObuff, "(");
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000016368 if (!fp->uf_varargs && fp->uf_args.ga_len == 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +000016369 STRCAT(IObuff, ")");
16370 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000016371 return IObuff;
16372 }
16373 return NULL;
16374}
16375
16376#endif /* FEAT_CMDL_COMPL */
16377
16378/*
16379 * Copy the function name of "fp" to buffer "buf".
16380 * "buf" must be able to hold the function name plus three bytes.
16381 * Takes care of script-local function names.
16382 */
16383 static void
16384cat_func_name(buf, fp)
16385 char_u *buf;
16386 ufunc_T *fp;
16387{
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000016388 if (fp->uf_name[0] == K_SPECIAL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000016389 {
16390 STRCPY(buf, "<SNR>");
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000016391 STRCAT(buf, fp->uf_name + 3);
Bram Moolenaar071d4272004-06-13 20:20:40 +000016392 }
16393 else
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000016394 STRCPY(buf, fp->uf_name);
Bram Moolenaar071d4272004-06-13 20:20:40 +000016395}
16396
16397/*
16398 * ":delfunction {name}"
16399 */
16400 void
16401ex_delfunction(eap)
16402 exarg_T *eap;
16403{
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000016404 ufunc_T *fp = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016405 char_u *p;
16406 char_u *name;
Bram Moolenaar33570922005-01-25 22:26:29 +000016407 funcdict_T fudi;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016408
16409 p = eap->arg;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000016410 name = trans_function_name(&p, eap->skip, 0, &fudi);
16411 vim_free(fudi.fd_newkey);
Bram Moolenaar071d4272004-06-13 20:20:40 +000016412 if (name == NULL)
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000016413 {
16414 if (fudi.fd_dict != NULL && !eap->skip)
16415 EMSG(_(e_funcref));
Bram Moolenaar071d4272004-06-13 20:20:40 +000016416 return;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000016417 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000016418 if (!ends_excmd(*skipwhite(p)))
16419 {
16420 vim_free(name);
16421 EMSG(_(e_trailing));
16422 return;
16423 }
16424 eap->nextcmd = check_nextcmd(p);
16425 if (eap->nextcmd != NULL)
16426 *p = NUL;
16427
16428 if (!eap->skip)
16429 fp = find_func(name);
16430 vim_free(name);
16431
16432 if (!eap->skip)
16433 {
16434 if (fp == NULL)
16435 {
Bram Moolenaar05159a02005-02-26 23:04:13 +000016436 EMSG2(_(e_nofunc), eap->arg);
Bram Moolenaar071d4272004-06-13 20:20:40 +000016437 return;
16438 }
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000016439 if (fp->uf_calls > 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +000016440 {
16441 EMSG2(_("E131: Cannot delete function %s: It is in use"), eap->arg);
16442 return;
16443 }
16444
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000016445 if (fudi.fd_dict != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000016446 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000016447 /* Delete the dict item that refers to the function, it will
16448 * invoke func_unref() and possibly delete the function. */
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000016449 dictitem_remove(fudi.fd_dict, fudi.fd_di);
Bram Moolenaar071d4272004-06-13 20:20:40 +000016450 }
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000016451 else
16452 func_free(fp);
16453 }
16454}
16455
16456/*
16457 * Free a function and remove it from the list of functions.
16458 */
16459 static void
16460func_free(fp)
16461 ufunc_T *fp;
16462{
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000016463 hashitem_T *hi;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000016464
16465 /* clear this function */
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000016466 ga_clear_strings(&(fp->uf_args));
16467 ga_clear_strings(&(fp->uf_lines));
Bram Moolenaar05159a02005-02-26 23:04:13 +000016468#ifdef FEAT_PROFILE
16469 vim_free(fp->uf_tml_count);
16470 vim_free(fp->uf_tml_total);
16471 vim_free(fp->uf_tml_self);
16472#endif
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000016473
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000016474 /* remove the function from the function hashtable */
16475 hi = hash_find(&func_hashtab, UF2HIKEY(fp));
16476 if (HASHITEM_EMPTY(hi))
16477 EMSG2(_(e_intern2), "func_free()");
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000016478 else
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000016479 hash_remove(&func_hashtab, hi);
16480
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000016481 vim_free(fp);
16482}
16483
16484/*
16485 * Unreference a Function: decrement the reference count and free it when it
16486 * becomes zero. Only for numbered functions.
16487 */
16488 static void
16489func_unref(name)
16490 char_u *name;
16491{
16492 ufunc_T *fp;
16493
16494 if (name != NULL && isdigit(*name))
16495 {
16496 fp = find_func(name);
16497 if (fp == NULL)
16498 EMSG2(_(e_intern2), "func_unref()");
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000016499 else if (--fp->uf_refcount <= 0)
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000016500 {
16501 /* Only delete it when it's not being used. Otherwise it's done
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000016502 * when "uf_calls" becomes zero. */
16503 if (fp->uf_calls == 0)
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000016504 func_free(fp);
16505 }
16506 }
16507}
16508
16509/*
16510 * Count a reference to a Function.
16511 */
16512 static void
16513func_ref(name)
16514 char_u *name;
16515{
16516 ufunc_T *fp;
16517
16518 if (name != NULL && isdigit(*name))
16519 {
16520 fp = find_func(name);
16521 if (fp == NULL)
16522 EMSG2(_(e_intern2), "func_ref()");
16523 else
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000016524 ++fp->uf_refcount;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016525 }
16526}
16527
16528/*
16529 * Call a user function.
16530 */
16531 static void
Bram Moolenaare9a41262005-01-15 22:18:47 +000016532call_user_func(fp, argcount, argvars, rettv, firstline, lastline, selfdict)
Bram Moolenaar071d4272004-06-13 20:20:40 +000016533 ufunc_T *fp; /* pointer to function */
16534 int argcount; /* nr of args */
Bram Moolenaar33570922005-01-25 22:26:29 +000016535 typval_T *argvars; /* arguments */
16536 typval_T *rettv; /* return value */
Bram Moolenaar071d4272004-06-13 20:20:40 +000016537 linenr_T firstline; /* first line of range */
16538 linenr_T lastline; /* last line of range */
Bram Moolenaar33570922005-01-25 22:26:29 +000016539 dict_T *selfdict; /* Dictionary for "self" */
Bram Moolenaar071d4272004-06-13 20:20:40 +000016540{
Bram Moolenaar33570922005-01-25 22:26:29 +000016541 char_u *save_sourcing_name;
16542 linenr_T save_sourcing_lnum;
16543 scid_T save_current_SID;
16544 funccall_T fc;
16545 funccall_T *save_fcp = current_funccal;
16546 int save_did_emsg;
16547 static int depth = 0;
16548 dictitem_T *v;
16549 int fixvar_idx = 0; /* index in fixvar[] */
16550 int i;
16551 int ai;
16552 char_u numbuf[NUMBUFLEN];
16553 char_u *name;
Bram Moolenaar05159a02005-02-26 23:04:13 +000016554#ifdef FEAT_PROFILE
16555 proftime_T wait_start;
16556#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000016557
16558 /* If depth of calling is getting too high, don't execute the function */
16559 if (depth >= p_mfd)
16560 {
16561 EMSG(_("E132: Function call depth is higher than 'maxfuncdepth'"));
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016562 rettv->v_type = VAR_NUMBER;
16563 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016564 return;
16565 }
16566 ++depth;
16567
16568 line_breakcheck(); /* check for CTRL-C hit */
16569
Bram Moolenaar33570922005-01-25 22:26:29 +000016570 current_funccal = &fc;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016571 fc.func = fp;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016572 fc.rettv = rettv;
16573 rettv->vval.v_number = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016574 fc.linenr = 0;
16575 fc.returned = FALSE;
16576 fc.level = ex_nesting_level;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016577 /* Check if this function has a breakpoint. */
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000016578 fc.breakpoint = dbg_find_breakpoint(FALSE, fp->uf_name, (linenr_T)0);
Bram Moolenaar071d4272004-06-13 20:20:40 +000016579 fc.dbg_tick = debug_tick;
16580
Bram Moolenaar33570922005-01-25 22:26:29 +000016581 /*
16582 * Note about using fc.fixvar[]: This is an array of FIXVAR_CNT variables
16583 * with names up to VAR_SHORT_LEN long. This avoids having to alloc/free
16584 * each argument variable and saves a lot of time.
16585 */
16586 /*
16587 * Init l: variables.
16588 */
16589 init_var_dict(&fc.l_vars, &fc.l_vars_var);
Bram Moolenaara7043832005-01-21 11:56:39 +000016590 if (selfdict != NULL)
Bram Moolenaare9a41262005-01-15 22:18:47 +000016591 {
Bram Moolenaar33570922005-01-25 22:26:29 +000016592 /* Set l:self to "selfdict". */
16593 v = &fc.fixvar[fixvar_idx++].var;
16594 STRCPY(v->di_key, "self");
16595 v->di_flags = DI_FLAGS_RO + DI_FLAGS_FIX;
16596 hash_add(&fc.l_vars.dv_hashtab, DI2HIKEY(v));
16597 v->di_tv.v_type = VAR_DICT;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000016598 v->di_tv.v_lock = 0;
Bram Moolenaar33570922005-01-25 22:26:29 +000016599 v->di_tv.vval.v_dict = selfdict;
16600 ++selfdict->dv_refcount;
16601 }
Bram Moolenaare9a41262005-01-15 22:18:47 +000016602
Bram Moolenaar33570922005-01-25 22:26:29 +000016603 /*
16604 * Init a: variables.
16605 * Set a:0 to "argcount".
16606 * Set a:000 to a list with room for the "..." arguments.
16607 */
16608 init_var_dict(&fc.l_avars, &fc.l_avars_var);
16609 add_nr_var(&fc.l_avars, &fc.fixvar[fixvar_idx++].var, "0",
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000016610 (varnumber_T)(argcount - fp->uf_args.ga_len));
Bram Moolenaar33570922005-01-25 22:26:29 +000016611 v = &fc.fixvar[fixvar_idx++].var;
16612 STRCPY(v->di_key, "000");
16613 v->di_flags = DI_FLAGS_RO | DI_FLAGS_FIX;
16614 hash_add(&fc.l_avars.dv_hashtab, DI2HIKEY(v));
16615 v->di_tv.v_type = VAR_LIST;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000016616 v->di_tv.v_lock = VAR_FIXED;
Bram Moolenaar33570922005-01-25 22:26:29 +000016617 v->di_tv.vval.v_list = &fc.l_varlist;
16618 vim_memset(&fc.l_varlist, 0, sizeof(list_T));
16619 fc.l_varlist.lv_refcount = 99999;
16620
16621 /*
16622 * Set a:firstline to "firstline" and a:lastline to "lastline".
16623 * Set a:name to named arguments.
16624 * Set a:N to the "..." arguments.
16625 */
16626 add_nr_var(&fc.l_avars, &fc.fixvar[fixvar_idx++].var, "firstline",
16627 (varnumber_T)firstline);
16628 add_nr_var(&fc.l_avars, &fc.fixvar[fixvar_idx++].var, "lastline",
16629 (varnumber_T)lastline);
16630 for (i = 0; i < argcount; ++i)
16631 {
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000016632 ai = i - fp->uf_args.ga_len;
Bram Moolenaar33570922005-01-25 22:26:29 +000016633 if (ai < 0)
16634 /* named argument a:name */
16635 name = FUNCARG(fp, i);
16636 else
Bram Moolenaare9a41262005-01-15 22:18:47 +000016637 {
Bram Moolenaar33570922005-01-25 22:26:29 +000016638 /* "..." argument a:1, a:2, etc. */
16639 sprintf((char *)numbuf, "%d", ai + 1);
16640 name = numbuf;
16641 }
16642 if (fixvar_idx < FIXVAR_CNT && STRLEN(name) <= VAR_SHORT_LEN)
16643 {
16644 v = &fc.fixvar[fixvar_idx++].var;
16645 v->di_flags = DI_FLAGS_RO | DI_FLAGS_FIX;
16646 }
16647 else
16648 {
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000016649 v = (dictitem_T *)alloc((unsigned)(sizeof(dictitem_T)
16650 + STRLEN(name)));
Bram Moolenaar33570922005-01-25 22:26:29 +000016651 if (v == NULL)
16652 break;
16653 v->di_flags = DI_FLAGS_RO;
16654 }
16655 STRCPY(v->di_key, name);
16656 hash_add(&fc.l_avars.dv_hashtab, DI2HIKEY(v));
16657
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000016658 /* Note: the values are copied directly to avoid alloc/free.
16659 * "argvars" must have VAR_FIXED for v_lock. */
Bram Moolenaar33570922005-01-25 22:26:29 +000016660 v->di_tv = argvars[i];
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000016661 v->di_tv.v_lock = VAR_FIXED;
Bram Moolenaar33570922005-01-25 22:26:29 +000016662
16663 if (ai >= 0 && ai < MAX_FUNC_ARGS)
16664 {
16665 list_append(&fc.l_varlist, &fc.l_listitems[ai]);
16666 fc.l_listitems[ai].li_tv = argvars[i];
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000016667 fc.l_listitems[ai].li_tv.v_lock = VAR_FIXED;
Bram Moolenaare9a41262005-01-15 22:18:47 +000016668 }
16669 }
16670
Bram Moolenaar071d4272004-06-13 20:20:40 +000016671 /* Don't redraw while executing the function. */
16672 ++RedrawingDisabled;
16673 save_sourcing_name = sourcing_name;
16674 save_sourcing_lnum = sourcing_lnum;
16675 sourcing_lnum = 1;
16676 sourcing_name = alloc((unsigned)((save_sourcing_name == NULL ? 0
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000016677 : STRLEN(save_sourcing_name)) + STRLEN(fp->uf_name) + 13));
Bram Moolenaar071d4272004-06-13 20:20:40 +000016678 if (sourcing_name != NULL)
16679 {
16680 if (save_sourcing_name != NULL
16681 && STRNCMP(save_sourcing_name, "function ", 9) == 0)
16682 sprintf((char *)sourcing_name, "%s..", save_sourcing_name);
16683 else
16684 STRCPY(sourcing_name, "function ");
16685 cat_func_name(sourcing_name + STRLEN(sourcing_name), fp);
16686
16687 if (p_verbose >= 12)
16688 {
16689 ++no_wait_return;
16690 msg_scroll = TRUE; /* always scroll up, don't overwrite */
16691 msg_str((char_u *)_("calling %s"), sourcing_name);
16692 if (p_verbose >= 14)
16693 {
Bram Moolenaar071d4272004-06-13 20:20:40 +000016694 char_u buf[MSG_BUF_LEN];
Bram Moolenaar758711c2005-02-02 23:11:38 +000016695 char_u numbuf[NUMBUFLEN];
16696 char_u *tofree;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016697
16698 msg_puts((char_u *)"(");
16699 for (i = 0; i < argcount; ++i)
16700 {
16701 if (i > 0)
16702 msg_puts((char_u *)", ");
Bram Moolenaar49cd9572005-01-03 21:06:01 +000016703 if (argvars[i].v_type == VAR_NUMBER)
16704 msg_outnum((long)argvars[i].vval.v_number);
Bram Moolenaar071d4272004-06-13 20:20:40 +000016705 else
16706 {
Bram Moolenaar758711c2005-02-02 23:11:38 +000016707 trunc_string(tv2string(&argvars[i], &tofree, numbuf),
Bram Moolenaar071d4272004-06-13 20:20:40 +000016708 buf, MSG_BUF_LEN);
Bram Moolenaar071d4272004-06-13 20:20:40 +000016709 msg_puts(buf);
Bram Moolenaar758711c2005-02-02 23:11:38 +000016710 vim_free(tofree);
Bram Moolenaar071d4272004-06-13 20:20:40 +000016711 }
16712 }
16713 msg_puts((char_u *)")");
16714 }
16715 msg_puts((char_u *)"\n"); /* don't overwrite this either */
16716 cmdline_row = msg_row;
16717 --no_wait_return;
16718 }
16719 }
Bram Moolenaar05159a02005-02-26 23:04:13 +000016720#ifdef FEAT_PROFILE
16721 if (do_profiling)
16722 {
16723 if (!fp->uf_profiling && has_profiling(FALSE, fp->uf_name, NULL))
16724 func_do_profile(fp);
16725 if (fp->uf_profiling
16726 || (save_fcp != NULL && &save_fcp->func->uf_profiling))
16727 {
16728 ++fp->uf_tm_count;
16729 profile_start(&fp->uf_tm_start);
16730 profile_zero(&fp->uf_tm_children);
16731 }
16732 script_prof_save(&wait_start);
16733 }
16734#endif
16735
Bram Moolenaar071d4272004-06-13 20:20:40 +000016736 save_current_SID = current_SID;
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000016737 current_SID = fp->uf_script_ID;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016738 save_did_emsg = did_emsg;
16739 did_emsg = FALSE;
16740
16741 /* call do_cmdline() to execute the lines */
16742 do_cmdline(NULL, get_func_line, (void *)&fc,
16743 DOCMD_NOWAIT|DOCMD_VERBOSE|DOCMD_REPEAT);
16744
16745 --RedrawingDisabled;
16746
16747 /* when the function was aborted because of an error, return -1 */
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000016748 if ((did_emsg && (fp->uf_flags & FC_ABORT)) || rettv->v_type == VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +000016749 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016750 clear_tv(rettv);
16751 rettv->v_type = VAR_NUMBER;
16752 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016753 }
16754
Bram Moolenaar05159a02005-02-26 23:04:13 +000016755#ifdef FEAT_PROFILE
16756 if (fp->uf_profiling || (save_fcp != NULL && &save_fcp->func->uf_profiling))
16757 {
16758 profile_end(&fp->uf_tm_start);
16759 profile_sub_wait(&wait_start, &fp->uf_tm_start);
16760 profile_add(&fp->uf_tm_total, &fp->uf_tm_start);
16761 profile_add(&fp->uf_tm_self, &fp->uf_tm_start);
16762 profile_sub(&fp->uf_tm_self, &fp->uf_tm_children);
16763 if (save_fcp != NULL && &save_fcp->func->uf_profiling)
16764 {
16765 profile_add(&save_fcp->func->uf_tm_children, &fp->uf_tm_start);
16766 profile_add(&save_fcp->func->uf_tml_children, &fp->uf_tm_start);
16767 }
16768 }
16769#endif
16770
Bram Moolenaar071d4272004-06-13 20:20:40 +000016771 /* when being verbose, mention the return value */
16772 if (p_verbose >= 12)
16773 {
Bram Moolenaar758711c2005-02-02 23:11:38 +000016774 char_u *sn;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016775
16776 ++no_wait_return;
16777 msg_scroll = TRUE; /* always scroll up, don't overwrite */
16778
16779 /* Make sure the output fits in IObuff. */
16780 sn = sourcing_name;
16781 if (STRLEN(sourcing_name) > IOSIZE / 2 - 50)
16782 sn = sourcing_name + STRLEN(sourcing_name) - (IOSIZE / 2 - 50);
16783
16784 if (aborting())
16785 smsg((char_u *)_("%s aborted"), sn);
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016786 else if (fc.rettv->v_type == VAR_NUMBER)
Bram Moolenaar071d4272004-06-13 20:20:40 +000016787 smsg((char_u *)_("%s returning #%ld"), sn,
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016788 (long)fc.rettv->vval.v_number);
Bram Moolenaar758711c2005-02-02 23:11:38 +000016789 else
Bram Moolenaar071d4272004-06-13 20:20:40 +000016790 {
Bram Moolenaar758711c2005-02-02 23:11:38 +000016791 char_u buf[MSG_BUF_LEN];
16792 char_u numbuf[NUMBUFLEN];
16793 char_u *tofree;
16794
16795 trunc_string(tv2string(fc.rettv, &tofree, numbuf),
16796 buf, MSG_BUF_LEN);
16797 smsg((char_u *)_("%s returning %s"), sn, buf);
16798 vim_free(tofree);
Bram Moolenaar071d4272004-06-13 20:20:40 +000016799 }
16800 msg_puts((char_u *)"\n"); /* don't overwrite this either */
16801 cmdline_row = msg_row;
16802 --no_wait_return;
16803 }
16804
16805 vim_free(sourcing_name);
16806 sourcing_name = save_sourcing_name;
16807 sourcing_lnum = save_sourcing_lnum;
16808 current_SID = save_current_SID;
Bram Moolenaar05159a02005-02-26 23:04:13 +000016809#ifdef FEAT_PROFILE
16810 if (do_profiling)
16811 script_prof_restore(&wait_start);
16812#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000016813
16814 if (p_verbose >= 12 && sourcing_name != NULL)
16815 {
16816 ++no_wait_return;
16817 msg_scroll = TRUE; /* always scroll up, don't overwrite */
16818 msg_str((char_u *)_("continuing in %s"), sourcing_name);
16819 msg_puts((char_u *)"\n"); /* don't overwrite this either */
16820 cmdline_row = msg_row;
16821 --no_wait_return;
16822 }
16823
16824 did_emsg |= save_did_emsg;
16825 current_funccal = save_fcp;
16826
Bram Moolenaar33570922005-01-25 22:26:29 +000016827 /* The a: variables typevals were not alloced, only free the allocated
16828 * variables. */
16829 vars_clear_ext(&fc.l_avars.dv_hashtab, FALSE);
16830
16831 vars_clear(&fc.l_vars.dv_hashtab); /* free all l: variables */
Bram Moolenaar071d4272004-06-13 20:20:40 +000016832 --depth;
16833}
16834
16835/*
Bram Moolenaar33570922005-01-25 22:26:29 +000016836 * Add a number variable "name" to dict "dp" with value "nr".
16837 */
16838 static void
16839add_nr_var(dp, v, name, nr)
16840 dict_T *dp;
16841 dictitem_T *v;
16842 char *name;
16843 varnumber_T nr;
16844{
16845 STRCPY(v->di_key, name);
16846 v->di_flags = DI_FLAGS_RO | DI_FLAGS_FIX;
16847 hash_add(&dp->dv_hashtab, DI2HIKEY(v));
16848 v->di_tv.v_type = VAR_NUMBER;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000016849 v->di_tv.v_lock = VAR_FIXED;
Bram Moolenaar33570922005-01-25 22:26:29 +000016850 v->di_tv.vval.v_number = nr;
16851}
16852
16853/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000016854 * ":return [expr]"
16855 */
16856 void
16857ex_return(eap)
16858 exarg_T *eap;
16859{
16860 char_u *arg = eap->arg;
Bram Moolenaar33570922005-01-25 22:26:29 +000016861 typval_T rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016862 int returning = FALSE;
16863
16864 if (current_funccal == NULL)
16865 {
16866 EMSG(_("E133: :return not inside a function"));
16867 return;
16868 }
16869
16870 if (eap->skip)
16871 ++emsg_skip;
16872
16873 eap->nextcmd = NULL;
16874 if ((*arg != NUL && *arg != '|' && *arg != '\n')
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016875 && eval0(arg, &rettv, &eap->nextcmd, !eap->skip) != FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000016876 {
16877 if (!eap->skip)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016878 returning = do_return(eap, FALSE, TRUE, &rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000016879 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016880 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000016881 }
16882 /* It's safer to return also on error. */
16883 else if (!eap->skip)
16884 {
16885 /*
16886 * Return unless the expression evaluation has been cancelled due to an
16887 * aborting error, an interrupt, or an exception.
16888 */
16889 if (!aborting())
16890 returning = do_return(eap, FALSE, TRUE, NULL);
16891 }
16892
16893 /* When skipping or the return gets pending, advance to the next command
16894 * in this line (!returning). Otherwise, ignore the rest of the line.
16895 * Following lines will be ignored by get_func_line(). */
16896 if (returning)
16897 eap->nextcmd = NULL;
16898 else if (eap->nextcmd == NULL) /* no argument */
16899 eap->nextcmd = check_nextcmd(arg);
16900
16901 if (eap->skip)
16902 --emsg_skip;
16903}
16904
16905/*
16906 * Return from a function. Possibly makes the return pending. Also called
16907 * for a pending return at the ":endtry" or after returning from an extra
16908 * do_cmdline(). "reanimate" is used in the latter case. "is_cmd" is set
Bram Moolenaar33570922005-01-25 22:26:29 +000016909 * when called due to a ":return" command. "rettv" may point to a typval_T
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016910 * with the return rettv. Returns TRUE when the return can be carried out,
Bram Moolenaar071d4272004-06-13 20:20:40 +000016911 * FALSE when the return gets pending.
16912 */
16913 int
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016914do_return(eap, reanimate, is_cmd, rettv)
Bram Moolenaar071d4272004-06-13 20:20:40 +000016915 exarg_T *eap;
16916 int reanimate;
16917 int is_cmd;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016918 void *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016919{
16920 int idx;
16921 struct condstack *cstack = eap->cstack;
16922
16923 if (reanimate)
16924 /* Undo the return. */
16925 current_funccal->returned = FALSE;
16926
16927 /*
16928 * Cleanup (and inactivate) conditionals, but stop when a try conditional
16929 * not in its finally clause (which then is to be executed next) is found.
16930 * In this case, make the ":return" pending for execution at the ":endtry".
16931 * Otherwise, return normally.
16932 */
16933 idx = cleanup_conditionals(eap->cstack, 0, TRUE);
16934 if (idx >= 0)
16935 {
16936 cstack->cs_pending[idx] = CSTP_RETURN;
16937
16938 if (!is_cmd && !reanimate)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016939 /* A pending return again gets pending. "rettv" points to an
16940 * allocated variable with the rettv of the original ":return"'s
Bram Moolenaar071d4272004-06-13 20:20:40 +000016941 * argument if present or is NULL else. */
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016942 cstack->cs_rettv[idx] = rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016943 else
16944 {
16945 /* When undoing a return in order to make it pending, get the stored
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016946 * return rettv. */
Bram Moolenaar071d4272004-06-13 20:20:40 +000016947 if (reanimate)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016948 rettv = current_funccal->rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016949
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016950 if (rettv != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000016951 {
16952 /* Store the value of the pending return. */
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016953 if ((cstack->cs_rettv[idx] = alloc_tv()) != NULL)
Bram Moolenaar33570922005-01-25 22:26:29 +000016954 *(typval_T *)cstack->cs_rettv[idx] = *(typval_T *)rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016955 else
16956 EMSG(_(e_outofmem));
16957 }
16958 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016959 cstack->cs_rettv[idx] = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016960
16961 if (reanimate)
16962 {
16963 /* The pending return value could be overwritten by a ":return"
16964 * without argument in a finally clause; reset the default
16965 * return value. */
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016966 current_funccal->rettv->v_type = VAR_NUMBER;
16967 current_funccal->rettv->vval.v_number = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016968 }
16969 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016970 report_make_pending(CSTP_RETURN, rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000016971 }
16972 else
16973 {
16974 current_funccal->returned = TRUE;
16975
16976 /* If the return is carried out now, store the return value. For
16977 * a return immediately after reanimation, the value is already
16978 * there. */
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016979 if (!reanimate && rettv != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000016980 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016981 clear_tv(current_funccal->rettv);
Bram Moolenaar33570922005-01-25 22:26:29 +000016982 *current_funccal->rettv = *(typval_T *)rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016983 if (!is_cmd)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016984 vim_free(rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000016985 }
16986 }
16987
16988 return idx < 0;
16989}
16990
16991/*
16992 * Free the variable with a pending return value.
16993 */
16994 void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016995discard_pending_return(rettv)
16996 void *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016997{
Bram Moolenaar33570922005-01-25 22:26:29 +000016998 free_tv((typval_T *)rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000016999}
17000
17001/*
Bram Moolenaarc70646c2005-01-04 21:52:38 +000017002 * Generate a return command for producing the value of "rettv". The result
Bram Moolenaar071d4272004-06-13 20:20:40 +000017003 * is an allocated string. Used by report_pending() for verbose messages.
17004 */
17005 char_u *
Bram Moolenaarc70646c2005-01-04 21:52:38 +000017006get_return_cmd(rettv)
17007 void *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017008{
Bram Moolenaar81bf7082005-02-12 14:31:42 +000017009 char_u *s = NULL;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000017010 char_u *tofree = NULL;
Bram Moolenaar8a283e52005-01-06 23:28:25 +000017011 char_u numbuf[NUMBUFLEN];
Bram Moolenaar071d4272004-06-13 20:20:40 +000017012
Bram Moolenaar81bf7082005-02-12 14:31:42 +000017013 if (rettv != NULL)
Bram Moolenaar33570922005-01-25 22:26:29 +000017014 s = echo_string((typval_T *)rettv, &tofree, numbuf);
Bram Moolenaar81bf7082005-02-12 14:31:42 +000017015 if (s == NULL)
17016 s = (char_u *)"";
Bram Moolenaarc70646c2005-01-04 21:52:38 +000017017
17018 STRCPY(IObuff, ":return ");
17019 STRNCPY(IObuff + 8, s, IOSIZE - 8);
17020 if (STRLEN(s) + 8 >= IOSIZE)
17021 STRCPY(IObuff + IOSIZE - 4, "...");
17022 vim_free(tofree);
17023 return vim_strsave(IObuff);
Bram Moolenaar071d4272004-06-13 20:20:40 +000017024}
17025
17026/*
17027 * Get next function line.
17028 * Called by do_cmdline() to get the next line.
17029 * Returns allocated string, or NULL for end of function.
17030 */
17031/* ARGSUSED */
17032 char_u *
17033get_func_line(c, cookie, indent)
17034 int c; /* not used */
17035 void *cookie;
17036 int indent; /* not used */
17037{
Bram Moolenaar33570922005-01-25 22:26:29 +000017038 funccall_T *fcp = (funccall_T *)cookie;
Bram Moolenaar05159a02005-02-26 23:04:13 +000017039 ufunc_T *fp = fcp->func;
17040 char_u *retval;
17041 garray_T *gap; /* growarray with function lines */
Bram Moolenaar071d4272004-06-13 20:20:40 +000017042
17043 /* If breakpoints have been added/deleted need to check for it. */
17044 if (fcp->dbg_tick != debug_tick)
17045 {
Bram Moolenaar05159a02005-02-26 23:04:13 +000017046 fcp->breakpoint = dbg_find_breakpoint(FALSE, fp->uf_name,
Bram Moolenaar071d4272004-06-13 20:20:40 +000017047 sourcing_lnum);
17048 fcp->dbg_tick = debug_tick;
17049 }
Bram Moolenaar05159a02005-02-26 23:04:13 +000017050#ifdef FEAT_PROFILE
17051 if (do_profiling)
17052 func_line_end(cookie);
17053#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000017054
Bram Moolenaar05159a02005-02-26 23:04:13 +000017055 gap = &fp->uf_lines;
17056 if ((fp->uf_flags & FC_ABORT) && did_emsg && !aborted_in_try())
Bram Moolenaar071d4272004-06-13 20:20:40 +000017057 retval = NULL;
17058 else if (fcp->returned || fcp->linenr >= gap->ga_len)
17059 retval = NULL;
17060 else
17061 {
17062 retval = vim_strsave(((char_u **)(gap->ga_data))[fcp->linenr++]);
17063 sourcing_lnum = fcp->linenr;
Bram Moolenaar05159a02005-02-26 23:04:13 +000017064#ifdef FEAT_PROFILE
17065 if (do_profiling)
17066 func_line_start(cookie);
17067#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000017068 }
17069
17070 /* Did we encounter a breakpoint? */
17071 if (fcp->breakpoint != 0 && fcp->breakpoint <= sourcing_lnum)
17072 {
Bram Moolenaar05159a02005-02-26 23:04:13 +000017073 dbg_breakpoint(fp->uf_name, sourcing_lnum);
Bram Moolenaar071d4272004-06-13 20:20:40 +000017074 /* Find next breakpoint. */
Bram Moolenaar05159a02005-02-26 23:04:13 +000017075 fcp->breakpoint = dbg_find_breakpoint(FALSE, fp->uf_name,
Bram Moolenaar071d4272004-06-13 20:20:40 +000017076 sourcing_lnum);
17077 fcp->dbg_tick = debug_tick;
17078 }
17079
17080 return retval;
17081}
17082
Bram Moolenaar05159a02005-02-26 23:04:13 +000017083#if defined(FEAT_PROFILE) || defined(PROTO)
17084/*
17085 * Called when starting to read a function line.
17086 * "sourcing_lnum" must be correct!
17087 * When skipping lines it may not actually be executed, but we won't find out
17088 * until later and we need to store the time now.
17089 */
17090 void
17091func_line_start(cookie)
17092 void *cookie;
17093{
17094 funccall_T *fcp = (funccall_T *)cookie;
17095 ufunc_T *fp = fcp->func;
17096
17097 if (fp->uf_profiling && sourcing_lnum >= 1
17098 && sourcing_lnum <= fp->uf_lines.ga_len)
17099 {
17100 fp->uf_tml_idx = sourcing_lnum - 1;
17101 fp->uf_tml_execed = FALSE;
17102 profile_start(&fp->uf_tml_start);
17103 profile_zero(&fp->uf_tml_children);
17104 profile_get_wait(&fp->uf_tml_wait);
17105 }
17106}
17107
17108/*
17109 * Called when actually executing a function line.
17110 */
17111 void
17112func_line_exec(cookie)
17113 void *cookie;
17114{
17115 funccall_T *fcp = (funccall_T *)cookie;
17116 ufunc_T *fp = fcp->func;
17117
17118 if (fp->uf_profiling && fp->uf_tml_idx >= 0)
17119 fp->uf_tml_execed = TRUE;
17120}
17121
17122/*
17123 * Called when done with a function line.
17124 */
17125 void
17126func_line_end(cookie)
17127 void *cookie;
17128{
17129 funccall_T *fcp = (funccall_T *)cookie;
17130 ufunc_T *fp = fcp->func;
17131
17132 if (fp->uf_profiling && fp->uf_tml_idx >= 0)
17133 {
17134 if (fp->uf_tml_execed)
17135 {
17136 ++fp->uf_tml_count[fp->uf_tml_idx];
17137 profile_end(&fp->uf_tml_start);
17138 profile_sub_wait(&fp->uf_tml_wait, &fp->uf_tml_start);
17139 profile_add(&fp->uf_tml_self[fp->uf_tml_idx], &fp->uf_tml_start);
17140 profile_add(&fp->uf_tml_total[fp->uf_tml_idx], &fp->uf_tml_start);
17141 profile_sub(&fp->uf_tml_self[fp->uf_tml_idx], &fp->uf_tml_children);
17142 }
17143 fp->uf_tml_idx = -1;
17144 }
17145}
17146#endif
17147
Bram Moolenaar071d4272004-06-13 20:20:40 +000017148/*
17149 * Return TRUE if the currently active function should be ended, because a
17150 * return was encountered or an error occured. Used inside a ":while".
17151 */
17152 int
17153func_has_ended(cookie)
17154 void *cookie;
17155{
Bram Moolenaar33570922005-01-25 22:26:29 +000017156 funccall_T *fcp = (funccall_T *)cookie;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017157
17158 /* Ignore the "abort" flag if the abortion behavior has been changed due to
17159 * an error inside a try conditional. */
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000017160 return (((fcp->func->uf_flags & FC_ABORT) && did_emsg && !aborted_in_try())
Bram Moolenaar071d4272004-06-13 20:20:40 +000017161 || fcp->returned);
17162}
17163
17164/*
17165 * return TRUE if cookie indicates a function which "abort"s on errors.
17166 */
17167 int
17168func_has_abort(cookie)
17169 void *cookie;
17170{
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000017171 return ((funccall_T *)cookie)->func->uf_flags & FC_ABORT;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017172}
17173
17174#if defined(FEAT_VIMINFO) || defined(FEAT_SESSION)
17175typedef enum
17176{
17177 VAR_FLAVOUR_DEFAULT,
17178 VAR_FLAVOUR_SESSION,
17179 VAR_FLAVOUR_VIMINFO
17180} var_flavour_T;
17181
17182static var_flavour_T var_flavour __ARGS((char_u *varname));
17183
17184 static var_flavour_T
17185var_flavour(varname)
17186 char_u *varname;
17187{
17188 char_u *p = varname;
17189
17190 if (ASCII_ISUPPER(*p))
17191 {
17192 while (*(++p))
17193 if (ASCII_ISLOWER(*p))
17194 return VAR_FLAVOUR_SESSION;
17195 return VAR_FLAVOUR_VIMINFO;
17196 }
17197 else
17198 return VAR_FLAVOUR_DEFAULT;
17199}
17200#endif
17201
17202#if defined(FEAT_VIMINFO) || defined(PROTO)
17203/*
17204 * Restore global vars that start with a capital from the viminfo file
17205 */
17206 int
17207read_viminfo_varlist(virp, writing)
17208 vir_T *virp;
17209 int writing;
17210{
17211 char_u *tab;
17212 int is_string = FALSE;
Bram Moolenaar33570922005-01-25 22:26:29 +000017213 typval_T tv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017214
17215 if (!writing && (find_viminfo_parameter('!') != NULL))
17216 {
17217 tab = vim_strchr(virp->vir_line + 1, '\t');
17218 if (tab != NULL)
17219 {
17220 *tab++ = '\0'; /* isolate the variable name */
17221 if (*tab == 'S') /* string var */
17222 is_string = TRUE;
17223
17224 tab = vim_strchr(tab, '\t');
17225 if (tab != NULL)
17226 {
Bram Moolenaar071d4272004-06-13 20:20:40 +000017227 if (is_string)
17228 {
Bram Moolenaar3d60ec22005-01-05 22:19:46 +000017229 tv.v_type = VAR_STRING;
17230 tv.vval.v_string = viminfo_readstring(virp,
Bram Moolenaar071d4272004-06-13 20:20:40 +000017231 (int)(tab - virp->vir_line + 1), TRUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +000017232 }
17233 else
17234 {
Bram Moolenaar3d60ec22005-01-05 22:19:46 +000017235 tv.v_type = VAR_NUMBER;
17236 tv.vval.v_number = atol((char *)tab + 1);
Bram Moolenaar071d4272004-06-13 20:20:40 +000017237 }
Bram Moolenaar3d60ec22005-01-05 22:19:46 +000017238 set_var(virp->vir_line + 1, &tv, FALSE);
17239 if (is_string)
17240 vim_free(tv.vval.v_string);
Bram Moolenaar071d4272004-06-13 20:20:40 +000017241 }
17242 }
17243 }
17244
17245 return viminfo_readline(virp);
17246}
17247
17248/*
17249 * Write global vars that start with a capital to the viminfo file
17250 */
17251 void
17252write_viminfo_varlist(fp)
17253 FILE *fp;
17254{
Bram Moolenaar33570922005-01-25 22:26:29 +000017255 hashitem_T *hi;
17256 dictitem_T *this_var;
Bram Moolenaara7043832005-01-21 11:56:39 +000017257 int todo;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000017258 char *s;
Bram Moolenaar81bf7082005-02-12 14:31:42 +000017259 char_u *p;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000017260 char_u *tofree;
Bram Moolenaar8a283e52005-01-06 23:28:25 +000017261 char_u numbuf[NUMBUFLEN];
Bram Moolenaar071d4272004-06-13 20:20:40 +000017262
17263 if (find_viminfo_parameter('!') == NULL)
17264 return;
17265
17266 fprintf(fp, _("\n# global variables:\n"));
Bram Moolenaara7043832005-01-21 11:56:39 +000017267
Bram Moolenaar33570922005-01-25 22:26:29 +000017268 todo = globvarht.ht_used;
17269 for (hi = globvarht.ht_array; todo > 0; ++hi)
Bram Moolenaar071d4272004-06-13 20:20:40 +000017270 {
Bram Moolenaara7043832005-01-21 11:56:39 +000017271 if (!HASHITEM_EMPTY(hi))
Bram Moolenaar071d4272004-06-13 20:20:40 +000017272 {
Bram Moolenaara7043832005-01-21 11:56:39 +000017273 --todo;
Bram Moolenaar33570922005-01-25 22:26:29 +000017274 this_var = HI2DI(hi);
17275 if (var_flavour(this_var->di_key) == VAR_FLAVOUR_VIMINFO)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000017276 {
Bram Moolenaar33570922005-01-25 22:26:29 +000017277 switch (this_var->di_tv.v_type)
Bram Moolenaara7043832005-01-21 11:56:39 +000017278 {
17279 case VAR_STRING: s = "STR"; break;
17280 case VAR_NUMBER: s = "NUM"; break;
17281 default: continue;
17282 }
Bram Moolenaar33570922005-01-25 22:26:29 +000017283 fprintf(fp, "!%s\t%s\t", this_var->di_key, s);
Bram Moolenaar81bf7082005-02-12 14:31:42 +000017284 p = echo_string(&this_var->di_tv, &tofree, numbuf);
17285 if (p != NULL)
17286 viminfo_writestring(fp, p);
Bram Moolenaara7043832005-01-21 11:56:39 +000017287 vim_free(tofree);
17288 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000017289 }
17290 }
17291}
17292#endif
17293
17294#if defined(FEAT_SESSION) || defined(PROTO)
17295 int
17296store_session_globals(fd)
17297 FILE *fd;
17298{
Bram Moolenaar33570922005-01-25 22:26:29 +000017299 hashitem_T *hi;
17300 dictitem_T *this_var;
Bram Moolenaara7043832005-01-21 11:56:39 +000017301 int todo;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017302 char_u *p, *t;
17303
Bram Moolenaar33570922005-01-25 22:26:29 +000017304 todo = globvarht.ht_used;
17305 for (hi = globvarht.ht_array; todo > 0; ++hi)
Bram Moolenaar071d4272004-06-13 20:20:40 +000017306 {
Bram Moolenaara7043832005-01-21 11:56:39 +000017307 if (!HASHITEM_EMPTY(hi))
Bram Moolenaar071d4272004-06-13 20:20:40 +000017308 {
Bram Moolenaara7043832005-01-21 11:56:39 +000017309 --todo;
Bram Moolenaar33570922005-01-25 22:26:29 +000017310 this_var = HI2DI(hi);
17311 if ((this_var->di_tv.v_type == VAR_NUMBER
17312 || this_var->di_tv.v_type == VAR_STRING)
17313 && var_flavour(this_var->di_key) == VAR_FLAVOUR_SESSION)
Bram Moolenaar3d60ec22005-01-05 22:19:46 +000017314 {
Bram Moolenaara7043832005-01-21 11:56:39 +000017315 /* Escape special characters with a backslash. Turn a LF and
17316 * CR into \n and \r. */
Bram Moolenaar33570922005-01-25 22:26:29 +000017317 p = vim_strsave_escaped(get_tv_string(&this_var->di_tv),
Bram Moolenaara7043832005-01-21 11:56:39 +000017318 (char_u *)"\\\"\n\r");
17319 if (p == NULL) /* out of memory */
17320 break;
17321 for (t = p; *t != NUL; ++t)
17322 if (*t == '\n')
17323 *t = 'n';
17324 else if (*t == '\r')
17325 *t = 'r';
17326 if ((fprintf(fd, "let %s = %c%s%c",
Bram Moolenaar33570922005-01-25 22:26:29 +000017327 this_var->di_key,
17328 (this_var->di_tv.v_type == VAR_STRING) ? '"'
17329 : ' ',
17330 p,
17331 (this_var->di_tv.v_type == VAR_STRING) ? '"'
17332 : ' ') < 0)
Bram Moolenaara7043832005-01-21 11:56:39 +000017333 || put_eol(fd) == FAIL)
17334 {
17335 vim_free(p);
17336 return FAIL;
17337 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000017338 vim_free(p);
17339 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000017340 }
17341 }
17342 return OK;
17343}
17344#endif
17345
17346#endif /* FEAT_EVAL */
17347
17348#if defined(FEAT_MODIFY_FNAME) || defined(FEAT_EVAL) || defined(PROTO)
17349
17350
17351#ifdef WIN3264
17352/*
17353 * Functions for ":8" filename modifier: get 8.3 version of a filename.
17354 */
17355static int get_short_pathname __ARGS((char_u **fnamep, char_u **bufp, int *fnamelen));
17356static int shortpath_for_invalid_fname __ARGS((char_u **fname, char_u **bufp, int *fnamelen));
17357static int shortpath_for_partial __ARGS((char_u **fnamep, char_u **bufp, int *fnamelen));
17358
17359/*
17360 * Get the short pathname of a file.
17361 * Returns 1 on success. *fnamelen is 0 for nonexistant path.
17362 */
17363 static int
17364get_short_pathname(fnamep, bufp, fnamelen)
17365 char_u **fnamep;
17366 char_u **bufp;
17367 int *fnamelen;
17368{
17369 int l,len;
17370 char_u *newbuf;
17371
17372 len = *fnamelen;
17373
17374 l = GetShortPathName(*fnamep, *fnamep, len);
17375 if (l > len - 1)
17376 {
17377 /* If that doesn't work (not enough space), then save the string
17378 * and try again with a new buffer big enough
17379 */
17380 newbuf = vim_strnsave(*fnamep, l);
17381 if (newbuf == NULL)
17382 return 0;
17383
17384 vim_free(*bufp);
17385 *fnamep = *bufp = newbuf;
17386
17387 l = GetShortPathName(*fnamep,*fnamep,l+1);
17388
17389 /* Really should always succeed, as the buffer is big enough */
17390 }
17391
17392 *fnamelen = l;
17393 return 1;
17394}
17395
17396/*
17397 * Create a short path name. Returns the length of the buffer it needs.
17398 * Doesn't copy over the end of the buffer passed in.
17399 */
17400 static int
17401shortpath_for_invalid_fname(fname, bufp, fnamelen)
17402 char_u **fname;
17403 char_u **bufp;
17404 int *fnamelen;
17405{
17406 char_u *s, *p, *pbuf2, *pbuf3;
17407 char_u ch;
17408 int l,len,len2,plen,slen;
17409
17410 /* Make a copy */
17411 len2 = *fnamelen;
17412 pbuf2 = vim_strnsave(*fname, len2);
17413 pbuf3 = NULL;
17414
17415 s = pbuf2 + len2 - 1; /* Find the end */
17416 slen = 1;
17417 plen = len2;
17418
17419 l = 0;
Bram Moolenaar1cd871b2004-12-19 22:46:22 +000017420 if (after_pathsep(pbuf2, s + 1))
Bram Moolenaar071d4272004-06-13 20:20:40 +000017421 {
17422 --s;
17423 ++slen;
17424 --plen;
17425 }
17426
17427 do
17428 {
17429 /* Go back one path-seperator */
Bram Moolenaar1cd871b2004-12-19 22:46:22 +000017430 while (s > pbuf2 && !after_pathsep(pbuf2, s + 1))
Bram Moolenaar071d4272004-06-13 20:20:40 +000017431 {
17432 --s;
17433 ++slen;
17434 --plen;
17435 }
17436 if (s <= pbuf2)
17437 break;
17438
17439 /* Remeber the character that is about to be blatted */
17440 ch = *s;
17441 *s = 0; /* get_short_pathname requires a null-terminated string */
17442
17443 /* Try it in situ */
17444 p = pbuf2;
17445 if (!get_short_pathname(&p, &pbuf3, &plen))
17446 {
17447 vim_free(pbuf2);
17448 return -1;
17449 }
17450 *s = ch; /* Preserve the string */
17451 } while (plen == 0);
17452
17453 if (plen > 0)
17454 {
17455 /* Remeber the length of the new string. */
17456 *fnamelen = len = plen + slen;
17457 vim_free(*bufp);
17458 if (len > len2)
17459 {
17460 /* If there's not enough space in the currently allocated string,
17461 * then copy it to a buffer big enough.
17462 */
17463 *fname= *bufp = vim_strnsave(p, len);
17464 if (*fname == NULL)
17465 return -1;
17466 }
17467 else
17468 {
17469 /* Transfer pbuf2 to being the main buffer (it's big enough) */
17470 *fname = *bufp = pbuf2;
17471 if (p != pbuf2)
17472 strncpy(*fname, p, plen);
17473 pbuf2 = NULL;
17474 }
17475 /* Concat the next bit */
17476 strncpy(*fname + plen, s, slen);
17477 (*fname)[len] = '\0';
17478 }
17479 vim_free(pbuf3);
17480 vim_free(pbuf2);
17481 return 0;
17482}
17483
17484/*
17485 * Get a pathname for a partial path.
17486 */
17487 static int
17488shortpath_for_partial(fnamep, bufp, fnamelen)
17489 char_u **fnamep;
17490 char_u **bufp;
17491 int *fnamelen;
17492{
17493 int sepcount, len, tflen;
17494 char_u *p;
17495 char_u *pbuf, *tfname;
17496 int hasTilde;
17497
17498 /* Count up the path seperators from the RHS.. so we know which part
17499 * of the path to return.
17500 */
17501 sepcount = 0;
Bram Moolenaar1cd871b2004-12-19 22:46:22 +000017502 for (p = *fnamep; p < *fnamep + *fnamelen; mb_ptr_adv(p))
Bram Moolenaar071d4272004-06-13 20:20:40 +000017503 if (vim_ispathsep(*p))
17504 ++sepcount;
17505
17506 /* Need full path first (use expand_env() to remove a "~/") */
17507 hasTilde = (**fnamep == '~');
17508 if (hasTilde)
17509 pbuf = tfname = expand_env_save(*fnamep);
17510 else
17511 pbuf = tfname = FullName_save(*fnamep, FALSE);
17512
17513 len = tflen = STRLEN(tfname);
17514
17515 if (!get_short_pathname(&tfname, &pbuf, &len))
17516 return -1;
17517
17518 if (len == 0)
17519 {
17520 /* Don't have a valid filename, so shorten the rest of the
17521 * path if we can. This CAN give us invalid 8.3 filenames, but
17522 * there's not a lot of point in guessing what it might be.
17523 */
17524 len = tflen;
17525 if (shortpath_for_invalid_fname(&tfname, &pbuf, &len) == -1)
17526 return -1;
17527 }
17528
17529 /* Count the paths backward to find the beginning of the desired string. */
17530 for (p = tfname + len - 1; p >= tfname; --p)
Bram Moolenaar1cd871b2004-12-19 22:46:22 +000017531 {
17532#ifdef FEAT_MBYTE
17533 if (has_mbyte)
17534 p -= mb_head_off(tfname, p);
17535#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000017536 if (vim_ispathsep(*p))
17537 {
17538 if (sepcount == 0 || (hasTilde && sepcount == 1))
17539 break;
17540 else
17541 sepcount --;
17542 }
Bram Moolenaar1cd871b2004-12-19 22:46:22 +000017543 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000017544 if (hasTilde)
17545 {
17546 --p;
17547 if (p >= tfname)
17548 *p = '~';
17549 else
17550 return -1;
17551 }
17552 else
17553 ++p;
17554
17555 /* Copy in the string - p indexes into tfname - allocated at pbuf */
17556 vim_free(*bufp);
17557 *fnamelen = (int)STRLEN(p);
17558 *bufp = pbuf;
17559 *fnamep = p;
17560
17561 return 0;
17562}
17563#endif /* WIN3264 */
17564
17565/*
17566 * Adjust a filename, according to a string of modifiers.
17567 * *fnamep must be NUL terminated when called. When returning, the length is
17568 * determined by *fnamelen.
17569 * Returns valid flags.
17570 * When there is an error, *fnamep is set to NULL.
17571 */
17572 int
17573modify_fname(src, usedlen, fnamep, bufp, fnamelen)
17574 char_u *src; /* string with modifiers */
17575 int *usedlen; /* characters after src that are used */
17576 char_u **fnamep; /* file name so far */
17577 char_u **bufp; /* buffer for allocated file name or NULL */
17578 int *fnamelen; /* length of fnamep */
17579{
17580 int valid = 0;
17581 char_u *tail;
17582 char_u *s, *p, *pbuf;
17583 char_u dirname[MAXPATHL];
17584 int c;
17585 int has_fullname = 0;
17586#ifdef WIN3264
17587 int has_shortname = 0;
17588#endif
17589
17590repeat:
17591 /* ":p" - full path/file_name */
17592 if (src[*usedlen] == ':' && src[*usedlen + 1] == 'p')
17593 {
17594 has_fullname = 1;
17595
17596 valid |= VALID_PATH;
17597 *usedlen += 2;
17598
17599 /* Expand "~/path" for all systems and "~user/path" for Unix and VMS */
17600 if ((*fnamep)[0] == '~'
17601#if !defined(UNIX) && !(defined(VMS) && defined(USER_HOME))
17602 && ((*fnamep)[1] == '/'
17603# ifdef BACKSLASH_IN_FILENAME
17604 || (*fnamep)[1] == '\\'
17605# endif
17606 || (*fnamep)[1] == NUL)
17607
17608#endif
17609 )
17610 {
17611 *fnamep = expand_env_save(*fnamep);
17612 vim_free(*bufp); /* free any allocated file name */
17613 *bufp = *fnamep;
17614 if (*fnamep == NULL)
17615 return -1;
17616 }
17617
17618 /* When "/." or "/.." is used: force expansion to get rid of it. */
Bram Moolenaar1cd871b2004-12-19 22:46:22 +000017619 for (p = *fnamep; *p != NUL; mb_ptr_adv(p))
Bram Moolenaar071d4272004-06-13 20:20:40 +000017620 {
17621 if (vim_ispathsep(*p)
17622 && p[1] == '.'
17623 && (p[2] == NUL
17624 || vim_ispathsep(p[2])
17625 || (p[2] == '.'
17626 && (p[3] == NUL || vim_ispathsep(p[3])))))
17627 break;
17628 }
17629
17630 /* FullName_save() is slow, don't use it when not needed. */
17631 if (*p != NUL || !vim_isAbsName(*fnamep))
17632 {
17633 *fnamep = FullName_save(*fnamep, *p != NUL);
17634 vim_free(*bufp); /* free any allocated file name */
17635 *bufp = *fnamep;
17636 if (*fnamep == NULL)
17637 return -1;
17638 }
17639
17640 /* Append a path separator to a directory. */
17641 if (mch_isdir(*fnamep))
17642 {
17643 /* Make room for one or two extra characters. */
17644 *fnamep = vim_strnsave(*fnamep, (int)STRLEN(*fnamep) + 2);
17645 vim_free(*bufp); /* free any allocated file name */
17646 *bufp = *fnamep;
17647 if (*fnamep == NULL)
17648 return -1;
17649 add_pathsep(*fnamep);
17650 }
17651 }
17652
17653 /* ":." - path relative to the current directory */
17654 /* ":~" - path relative to the home directory */
17655 /* ":8" - shortname path - postponed till after */
17656 while (src[*usedlen] == ':'
17657 && ((c = src[*usedlen + 1]) == '.' || c == '~' || c == '8'))
17658 {
17659 *usedlen += 2;
17660 if (c == '8')
17661 {
17662#ifdef WIN3264
17663 has_shortname = 1; /* Postpone this. */
17664#endif
17665 continue;
17666 }
17667 pbuf = NULL;
17668 /* Need full path first (use expand_env() to remove a "~/") */
17669 if (!has_fullname)
17670 {
17671 if (c == '.' && **fnamep == '~')
17672 p = pbuf = expand_env_save(*fnamep);
17673 else
17674 p = pbuf = FullName_save(*fnamep, FALSE);
17675 }
17676 else
17677 p = *fnamep;
17678
17679 has_fullname = 0;
17680
17681 if (p != NULL)
17682 {
17683 if (c == '.')
17684 {
17685 mch_dirname(dirname, MAXPATHL);
17686 s = shorten_fname(p, dirname);
17687 if (s != NULL)
17688 {
17689 *fnamep = s;
17690 if (pbuf != NULL)
17691 {
17692 vim_free(*bufp); /* free any allocated file name */
17693 *bufp = pbuf;
17694 pbuf = NULL;
17695 }
17696 }
17697 }
17698 else
17699 {
17700 home_replace(NULL, p, dirname, MAXPATHL, TRUE);
17701 /* Only replace it when it starts with '~' */
17702 if (*dirname == '~')
17703 {
17704 s = vim_strsave(dirname);
17705 if (s != NULL)
17706 {
17707 *fnamep = s;
17708 vim_free(*bufp);
17709 *bufp = s;
17710 }
17711 }
17712 }
17713 vim_free(pbuf);
17714 }
17715 }
17716
17717 tail = gettail(*fnamep);
17718 *fnamelen = (int)STRLEN(*fnamep);
17719
17720 /* ":h" - head, remove "/file_name", can be repeated */
17721 /* Don't remove the first "/" or "c:\" */
17722 while (src[*usedlen] == ':' && src[*usedlen + 1] == 'h')
17723 {
17724 valid |= VALID_HEAD;
17725 *usedlen += 2;
17726 s = get_past_head(*fnamep);
Bram Moolenaar1cd871b2004-12-19 22:46:22 +000017727 while (tail > s && after_pathsep(s, tail))
Bram Moolenaar071d4272004-06-13 20:20:40 +000017728 --tail;
17729 *fnamelen = (int)(tail - *fnamep);
17730#ifdef VMS
17731 if (*fnamelen > 0)
17732 *fnamelen += 1; /* the path separator is part of the path */
17733#endif
Bram Moolenaar1cd871b2004-12-19 22:46:22 +000017734 while (tail > s && !after_pathsep(s, tail))
17735 mb_ptr_back(*fnamep, tail);
Bram Moolenaar071d4272004-06-13 20:20:40 +000017736 }
17737
17738 /* ":8" - shortname */
17739 if (src[*usedlen] == ':' && src[*usedlen + 1] == '8')
17740 {
17741 *usedlen += 2;
17742#ifdef WIN3264
17743 has_shortname = 1;
17744#endif
17745 }
17746
17747#ifdef WIN3264
17748 /* Check shortname after we have done 'heads' and before we do 'tails'
17749 */
17750 if (has_shortname)
17751 {
17752 pbuf = NULL;
17753 /* Copy the string if it is shortened by :h */
17754 if (*fnamelen < (int)STRLEN(*fnamep))
17755 {
17756 p = vim_strnsave(*fnamep, *fnamelen);
17757 if (p == 0)
17758 return -1;
17759 vim_free(*bufp);
17760 *bufp = *fnamep = p;
17761 }
17762
17763 /* Split into two implementations - makes it easier. First is where
17764 * there isn't a full name already, second is where there is.
17765 */
17766 if (!has_fullname && !vim_isAbsName(*fnamep))
17767 {
17768 if (shortpath_for_partial(fnamep, bufp, fnamelen) == -1)
17769 return -1;
17770 }
17771 else
17772 {
17773 int l;
17774
17775 /* Simple case, already have the full-name
17776 * Nearly always shorter, so try first time. */
17777 l = *fnamelen;
17778 if (!get_short_pathname(fnamep, bufp, &l))
17779 return -1;
17780
17781 if (l == 0)
17782 {
17783 /* Couldn't find the filename.. search the paths.
17784 */
17785 l = *fnamelen;
17786 if (shortpath_for_invalid_fname(fnamep, bufp, &l ) == -1)
17787 return -1;
17788 }
17789 *fnamelen = l;
17790 }
17791 }
17792#endif /* WIN3264 */
17793
17794 /* ":t" - tail, just the basename */
17795 if (src[*usedlen] == ':' && src[*usedlen + 1] == 't')
17796 {
17797 *usedlen += 2;
17798 *fnamelen -= (int)(tail - *fnamep);
17799 *fnamep = tail;
17800 }
17801
17802 /* ":e" - extension, can be repeated */
17803 /* ":r" - root, without extension, can be repeated */
17804 while (src[*usedlen] == ':'
17805 && (src[*usedlen + 1] == 'e' || src[*usedlen + 1] == 'r'))
17806 {
17807 /* find a '.' in the tail:
17808 * - for second :e: before the current fname
17809 * - otherwise: The last '.'
17810 */
17811 if (src[*usedlen + 1] == 'e' && *fnamep > tail)
17812 s = *fnamep - 2;
17813 else
17814 s = *fnamep + *fnamelen - 1;
17815 for ( ; s > tail; --s)
17816 if (s[0] == '.')
17817 break;
17818 if (src[*usedlen + 1] == 'e') /* :e */
17819 {
17820 if (s > tail)
17821 {
17822 *fnamelen += (int)(*fnamep - (s + 1));
17823 *fnamep = s + 1;
17824#ifdef VMS
17825 /* cut version from the extension */
17826 s = *fnamep + *fnamelen - 1;
17827 for ( ; s > *fnamep; --s)
17828 if (s[0] == ';')
17829 break;
17830 if (s > *fnamep)
17831 *fnamelen = s - *fnamep;
17832#endif
17833 }
17834 else if (*fnamep <= tail)
17835 *fnamelen = 0;
17836 }
17837 else /* :r */
17838 {
17839 if (s > tail) /* remove one extension */
17840 *fnamelen = (int)(s - *fnamep);
17841 }
17842 *usedlen += 2;
17843 }
17844
17845 /* ":s?pat?foo?" - substitute */
17846 /* ":gs?pat?foo?" - global substitute */
17847 if (src[*usedlen] == ':'
17848 && (src[*usedlen + 1] == 's'
17849 || (src[*usedlen + 1] == 'g' && src[*usedlen + 2] == 's')))
17850 {
17851 char_u *str;
17852 char_u *pat;
17853 char_u *sub;
17854 int sep;
17855 char_u *flags;
17856 int didit = FALSE;
17857
17858 flags = (char_u *)"";
17859 s = src + *usedlen + 2;
17860 if (src[*usedlen + 1] == 'g')
17861 {
17862 flags = (char_u *)"g";
17863 ++s;
17864 }
17865
17866 sep = *s++;
17867 if (sep)
17868 {
17869 /* find end of pattern */
17870 p = vim_strchr(s, sep);
17871 if (p != NULL)
17872 {
17873 pat = vim_strnsave(s, (int)(p - s));
17874 if (pat != NULL)
17875 {
17876 s = p + 1;
17877 /* find end of substitution */
17878 p = vim_strchr(s, sep);
17879 if (p != NULL)
17880 {
17881 sub = vim_strnsave(s, (int)(p - s));
17882 str = vim_strnsave(*fnamep, *fnamelen);
17883 if (sub != NULL && str != NULL)
17884 {
17885 *usedlen = (int)(p + 1 - src);
17886 s = do_string_sub(str, pat, sub, flags);
17887 if (s != NULL)
17888 {
17889 *fnamep = s;
17890 *fnamelen = (int)STRLEN(s);
17891 vim_free(*bufp);
17892 *bufp = s;
17893 didit = TRUE;
17894 }
17895 }
17896 vim_free(sub);
17897 vim_free(str);
17898 }
17899 vim_free(pat);
17900 }
17901 }
17902 /* after using ":s", repeat all the modifiers */
17903 if (didit)
17904 goto repeat;
17905 }
17906 }
17907
17908 return valid;
17909}
17910
17911/*
17912 * Perform a substitution on "str" with pattern "pat" and substitute "sub".
17913 * "flags" can be "g" to do a global substitute.
17914 * Returns an allocated string, NULL for error.
17915 */
17916 char_u *
17917do_string_sub(str, pat, sub, flags)
17918 char_u *str;
17919 char_u *pat;
17920 char_u *sub;
17921 char_u *flags;
17922{
17923 int sublen;
17924 regmatch_T regmatch;
17925 int i;
17926 int do_all;
17927 char_u *tail;
17928 garray_T ga;
17929 char_u *ret;
17930 char_u *save_cpo;
17931
17932 /* Make 'cpoptions' empty, so that the 'l' flag doesn't work here */
17933 save_cpo = p_cpo;
17934 p_cpo = (char_u *)"";
17935
17936 ga_init2(&ga, 1, 200);
17937
17938 do_all = (flags[0] == 'g');
17939
17940 regmatch.rm_ic = p_ic;
17941 regmatch.regprog = vim_regcomp(pat, RE_MAGIC + RE_STRING);
17942 if (regmatch.regprog != NULL)
17943 {
17944 tail = str;
17945 while (vim_regexec_nl(&regmatch, str, (colnr_T)(tail - str)))
17946 {
17947 /*
17948 * Get some space for a temporary buffer to do the substitution
17949 * into. It will contain:
17950 * - The text up to where the match is.
17951 * - The substituted text.
17952 * - The text after the match.
17953 */
17954 sublen = vim_regsub(&regmatch, sub, tail, FALSE, TRUE, FALSE);
17955 if (ga_grow(&ga, (int)(STRLEN(tail) + sublen -
17956 (regmatch.endp[0] - regmatch.startp[0]))) == FAIL)
17957 {
17958 ga_clear(&ga);
17959 break;
17960 }
17961
17962 /* copy the text up to where the match is */
17963 i = (int)(regmatch.startp[0] - tail);
17964 mch_memmove((char_u *)ga.ga_data + ga.ga_len, tail, (size_t)i);
17965 /* add the substituted text */
17966 (void)vim_regsub(&regmatch, sub, (char_u *)ga.ga_data
17967 + ga.ga_len + i, TRUE, TRUE, FALSE);
17968 ga.ga_len += i + sublen - 1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017969 /* avoid getting stuck on a match with an empty string */
17970 if (tail == regmatch.endp[0])
17971 {
17972 if (*tail == NUL)
17973 break;
17974 *((char_u *)ga.ga_data + ga.ga_len) = *tail++;
17975 ++ga.ga_len;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017976 }
17977 else
17978 {
17979 tail = regmatch.endp[0];
17980 if (*tail == NUL)
17981 break;
17982 }
17983 if (!do_all)
17984 break;
17985 }
17986
17987 if (ga.ga_data != NULL)
17988 STRCPY((char *)ga.ga_data + ga.ga_len, tail);
17989
17990 vim_free(regmatch.regprog);
17991 }
17992
17993 ret = vim_strsave(ga.ga_data == NULL ? str : (char_u *)ga.ga_data);
17994 ga_clear(&ga);
17995 p_cpo = save_cpo;
17996
17997 return ret;
17998}
17999
18000#endif /* defined(FEAT_MODIFY_FNAME) || defined(FEAT_EVAL) */