blob: 04772225c797b1ef3c7fd3e756d79a7687140f4b [file] [log] [blame]
Bram Moolenaar071d4272004-06-13 20:20:40 +00001/* vi:set ts=8 sts=4 sw=4:
2 *
3 * VIM - Vi IMproved by Bram Moolenaar
4 *
5 * Do ":help uganda" in Vim to read copying and usage conditions.
6 * Do ":help credits" in Vim to see a list of people who contributed.
7 * See README.txt for an overview of the Vim source code.
8 */
9
10/*
11 * eval.c: Expression evaluation.
12 */
13#if defined(MSDOS) || defined(MSWIN)
14# include <io.h> /* for mch_open(), must be before vim.h */
15#endif
16
17#include "vim.h"
18
19#ifdef AMIGA
20# include <time.h> /* for strftime() */
21#endif
22
23#ifdef MACOS
24# include <time.h> /* for time_t */
25#endif
26
27#ifdef HAVE_FCNTL_H
28# include <fcntl.h>
29#endif
30
31#if defined(FEAT_EVAL) || defined(PROTO)
32
Bram Moolenaar33570922005-01-25 22:26:29 +000033#define DICT_MAXNEST 100 /* maximum nesting of lists and dicts */
Bram Moolenaar071d4272004-06-13 20:20:40 +000034
35/*
Bram Moolenaar33570922005-01-25 22:26:29 +000036 * In a hashtab item "hi_key" points to "di_key" in a dictitem.
37 * This avoids adding a pointer to the hashtab item.
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000038 * DI2HIKEY() converts a dictitem pointer to a hashitem key pointer.
39 * HIKEY2DI() converts a hashitem key pointer to a dictitem pointer.
40 * HI2DI() converts a hashitem pointer to a dictitem pointer.
41 */
Bram Moolenaar33570922005-01-25 22:26:29 +000042static dictitem_T dumdi;
Bram Moolenaara7043832005-01-21 11:56:39 +000043#define DI2HIKEY(di) ((di)->di_key)
Bram Moolenaar33570922005-01-25 22:26:29 +000044#define HIKEY2DI(p) ((dictitem_T *)(p - (dumdi.di_key - (char_u *)&dumdi)))
Bram Moolenaara7043832005-01-21 11:56:39 +000045#define HI2DI(hi) HIKEY2DI((hi)->hi_key)
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000046
47/*
Bram Moolenaar7480b5c2005-01-16 22:07:38 +000048 * Structure returned by get_lval() and used by set_var_lval().
49 * For a plain name:
50 * "name" points to the variable name.
51 * "exp_name" is NULL.
52 * "tv" is NULL
53 * For a magic braces name:
54 * "name" points to the expanded variable name.
55 * "exp_name" is non-NULL, to be freed later.
56 * "tv" is NULL
57 * For an index in a list:
58 * "name" points to the (expanded) variable name.
59 * "exp_name" NULL or non-NULL, to be freed later.
60 * "tv" points to the (first) list item value
61 * "li" points to the (first) list item
62 * "range", "n1", "n2" and "empty2" indicate what items are used.
63 * For an existing Dict item:
64 * "name" points to the (expanded) variable name.
65 * "exp_name" NULL or non-NULL, to be freed later.
66 * "tv" points to the dict item value
67 * "newkey" is NULL
68 * For a non-existing Dict item:
69 * "name" points to the (expanded) variable name.
70 * "exp_name" NULL or non-NULL, to be freed later.
Bram Moolenaar33570922005-01-25 22:26:29 +000071 * "tv" points to the Dictionary typval_T
Bram Moolenaar7480b5c2005-01-16 22:07:38 +000072 * "newkey" is the key for the new item.
73 */
74typedef struct lval_S
75{
76 char_u *ll_name; /* start of variable name (can be NULL) */
77 char_u *ll_exp_name; /* NULL or expanded name in allocated memory. */
Bram Moolenaar33570922005-01-25 22:26:29 +000078 typval_T *ll_tv; /* Typeval of item being used. If "newkey"
Bram Moolenaar7480b5c2005-01-16 22:07:38 +000079 isn't NULL it's the Dict to which to add
80 the item. */
Bram Moolenaar33570922005-01-25 22:26:29 +000081 listitem_T *ll_li; /* The list item or NULL. */
82 list_T *ll_list; /* The list or NULL. */
Bram Moolenaar7480b5c2005-01-16 22:07:38 +000083 int ll_range; /* TRUE when a [i:j] range was used */
84 long ll_n1; /* First index for list */
85 long ll_n2; /* Second index for list range */
86 int ll_empty2; /* Second index is empty: [i:] */
Bram Moolenaar33570922005-01-25 22:26:29 +000087 dict_T *ll_dict; /* The Dictionary or NULL */
88 dictitem_T *ll_di; /* The dictitem or NULL */
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000089 char_u *ll_newkey; /* New key for Dict in alloc. mem or NULL. */
Bram Moolenaar33570922005-01-25 22:26:29 +000090} lval_T;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +000091
Bram Moolenaar8c711452005-01-14 21:53:12 +000092
Bram Moolenaarc70646c2005-01-04 21:52:38 +000093static char *e_letunexp = N_("E18: Unexpected characters in :let");
Bram Moolenaare49b69a2005-01-08 16:11:57 +000094static char *e_listidx = N_("E684: list index out of range: %ld");
Bram Moolenaarc70646c2005-01-04 21:52:38 +000095static char *e_undefvar = N_("E121: Undefined variable: %s");
96static char *e_missbrac = N_("E111: Missing ']'");
Bram Moolenaar8c711452005-01-14 21:53:12 +000097static char *e_listarg = N_("E686: Argument of %s must be a List");
Bram Moolenaar13fcaaf2005-04-15 21:13:42 +000098static char *e_listdictarg = N_("E712: Argument of %s must be a List or Dictionary");
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000099static char *e_emptykey = N_("E713: Cannot use empty key for Dictionary");
Bram Moolenaar9ef486d2005-01-17 22:23:00 +0000100static char *e_listreq = N_("E714: List required");
101static char *e_dictreq = N_("E715: Dictionary required");
Bram Moolenaar8c711452005-01-14 21:53:12 +0000102static char *e_toomanyarg = N_("E118: Too many arguments for function: %s");
Bram Moolenaar9ef486d2005-01-17 22:23:00 +0000103static char *e_dictkey = N_("E716: Key not present in Dictionary: %s");
104static char *e_funcexts = N_("E122: Function %s already exists, add ! to replace it");
105static char *e_funcdict = N_("E717: Dictionary entry already exists");
106static char *e_funcref = N_("E718: Funcref required");
107static char *e_dictrange = N_("E719: Cannot use [:] with a Dictionary");
108static char *e_letwrong = N_("E734: Wrong variable type for %s=");
Bram Moolenaar05159a02005-02-26 23:04:13 +0000109static char *e_nofunc = N_("E130: Unknown function: %s");
Bram Moolenaar92124a32005-06-17 22:03:40 +0000110static char *e_illvar = N_("E461: Illegal variable name: %s");
Bram Moolenaar49cd9572005-01-03 21:06:01 +0000111/*
Bram Moolenaar33570922005-01-25 22:26:29 +0000112 * All user-defined global variables are stored in dictionary "globvardict".
113 * "globvars_var" is the variable that is used for "g:".
Bram Moolenaar071d4272004-06-13 20:20:40 +0000114 */
Bram Moolenaar33570922005-01-25 22:26:29 +0000115static dict_T globvardict;
116static dictitem_T globvars_var;
117#define globvarht globvardict.dv_hashtab
Bram Moolenaar071d4272004-06-13 20:20:40 +0000118
119/*
Bram Moolenaar532c7802005-01-27 14:44:31 +0000120 * Old Vim variables such as "v:version" are also available without the "v:".
121 * Also in functions. We need a special hashtable for them.
122 */
Bram Moolenaar4debb442005-06-01 21:57:40 +0000123static hashtab_T compat_hashtab;
Bram Moolenaar532c7802005-01-27 14:44:31 +0000124
125/*
Bram Moolenaard9fba312005-06-26 22:34:35 +0000126 * When recursively copying lists and dicts we need to remember which ones we
127 * have done to avoid endless recursiveness. This unique ID is used for that.
128 */
129static int current_copyID = 0;
130
131/*
Bram Moolenaar33570922005-01-25 22:26:29 +0000132 * Array to hold the hashtab with variables local to each sourced script.
133 * Each item holds a variable (nameless) that points to the dict_T.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000134 */
Bram Moolenaar33570922005-01-25 22:26:29 +0000135typedef struct
136{
137 dictitem_T sv_var;
138 dict_T sv_dict;
139} scriptvar_T;
140
141static garray_T ga_scripts = {0, 0, sizeof(scriptvar_T), 4, NULL};
142#define SCRIPT_SV(id) (((scriptvar_T *)ga_scripts.ga_data)[(id) - 1])
143#define SCRIPT_VARS(id) (SCRIPT_SV(id).sv_dict.dv_hashtab)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000144
145static int echo_attr = 0; /* attributes used for ":echo" */
146
Bram Moolenaar9ef486d2005-01-17 22:23:00 +0000147/* Values for trans_function_name() argument: */
148#define TFN_INT 1 /* internal function name OK */
149#define TFN_QUIET 2 /* no error messages */
150
Bram Moolenaar071d4272004-06-13 20:20:40 +0000151/*
152 * Structure to hold info for a user function.
153 */
154typedef struct ufunc ufunc_T;
155
156struct ufunc
157{
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000158 int uf_varargs; /* variable nr of arguments */
159 int uf_flags;
160 int uf_calls; /* nr of active calls */
161 garray_T uf_args; /* arguments */
162 garray_T uf_lines; /* function lines */
Bram Moolenaar05159a02005-02-26 23:04:13 +0000163#ifdef FEAT_PROFILE
164 int uf_profiling; /* TRUE when func is being profiled */
165 /* profiling the function as a whole */
166 int uf_tm_count; /* nr of calls */
167 proftime_T uf_tm_total; /* time spend in function + children */
168 proftime_T uf_tm_self; /* time spend in function itself */
169 proftime_T uf_tm_start; /* time at function call */
170 proftime_T uf_tm_children; /* time spent in children this call */
171 /* profiling the function per line */
172 int *uf_tml_count; /* nr of times line was executed */
173 proftime_T *uf_tml_total; /* time spend in a line + children */
174 proftime_T *uf_tml_self; /* time spend in a line itself */
175 proftime_T uf_tml_start; /* start time for current line */
176 proftime_T uf_tml_children; /* time spent in children for this line */
177 proftime_T uf_tml_wait; /* start wait time for current line */
178 int uf_tml_idx; /* index of line being timed; -1 if none */
179 int uf_tml_execed; /* line being timed was executed */
180#endif
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000181 scid_T uf_script_ID; /* ID of script where function was defined,
Bram Moolenaar071d4272004-06-13 20:20:40 +0000182 used for s: variables */
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000183 int uf_refcount; /* for numbered function: reference count */
184 char_u uf_name[1]; /* name of function (actually longer); can
185 start with <SNR>123_ (<SNR> is K_SPECIAL
186 KS_EXTRA KE_SNR) */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000187};
188
189/* function flags */
190#define FC_ABORT 1 /* abort function on error */
191#define FC_RANGE 2 /* function accepts range */
Bram Moolenaare9a41262005-01-15 22:18:47 +0000192#define FC_DICT 4 /* Dict function, uses "self" */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000193
Bram Moolenaard9fba312005-06-26 22:34:35 +0000194#define DEL_REFCOUNT 999999 /* list/dict is being deleted */
195
Bram Moolenaar071d4272004-06-13 20:20:40 +0000196/*
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +0000197 * All user-defined functions are found in this hashtable.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000198 */
Bram Moolenaar4debb442005-06-01 21:57:40 +0000199static hashtab_T func_hashtab;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000200
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +0000201/* list heads for garbage collection */
202static dict_T *first_dict = NULL; /* list of all dicts */
203static list_T *first_list = NULL; /* list of all lists */
204
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000205/* From user function to hashitem and back. */
206static ufunc_T dumuf;
207#define UF2HIKEY(fp) ((fp)->uf_name)
208#define HIKEY2UF(p) ((ufunc_T *)(p - (dumuf.uf_name - (char_u *)&dumuf)))
209#define HI2UF(hi) HIKEY2UF((hi)->hi_key)
210
211#define FUNCARG(fp, j) ((char_u **)(fp->uf_args.ga_data))[j]
212#define FUNCLINE(fp, j) ((char_u **)(fp->uf_lines.ga_data))[j]
Bram Moolenaar071d4272004-06-13 20:20:40 +0000213
Bram Moolenaar33570922005-01-25 22:26:29 +0000214#define MAX_FUNC_ARGS 20 /* maximum number of function arguments */
215#define VAR_SHORT_LEN 20 /* short variable name length */
216#define FIXVAR_CNT 12 /* number of fixed variables */
217
Bram Moolenaar071d4272004-06-13 20:20:40 +0000218/* structure to hold info for a function that is currently being executed. */
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +0000219typedef struct funccall_S funccall_T;
220
221struct funccall_S
Bram Moolenaar071d4272004-06-13 20:20:40 +0000222{
223 ufunc_T *func; /* function being called */
224 int linenr; /* next line to be executed */
225 int returned; /* ":return" used */
Bram Moolenaar33570922005-01-25 22:26:29 +0000226 struct /* fixed variables for arguments */
227 {
228 dictitem_T var; /* variable (without room for name) */
229 char_u room[VAR_SHORT_LEN]; /* room for the name */
230 } fixvar[FIXVAR_CNT];
231 dict_T l_vars; /* l: local function variables */
232 dictitem_T l_vars_var; /* variable for l: scope */
233 dict_T l_avars; /* a: argument variables */
234 dictitem_T l_avars_var; /* variable for a: scope */
235 list_T l_varlist; /* list for a:000 */
236 listitem_T l_listitems[MAX_FUNC_ARGS]; /* listitems for a:000 */
237 typval_T *rettv; /* return value */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000238 linenr_T breakpoint; /* next line with breakpoint or zero */
239 int dbg_tick; /* debug_tick when breakpoint was set */
240 int level; /* top nesting level of executed function */
Bram Moolenaar05159a02005-02-26 23:04:13 +0000241#ifdef FEAT_PROFILE
242 proftime_T prof_child; /* time spent in a child */
243#endif
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +0000244 funccall_T *caller; /* calling function or NULL */
245};
Bram Moolenaar071d4272004-06-13 20:20:40 +0000246
247/*
Bram Moolenaar3d60ec22005-01-05 22:19:46 +0000248 * Info used by a ":for" loop.
249 */
Bram Moolenaar33570922005-01-25 22:26:29 +0000250typedef struct
Bram Moolenaar3d60ec22005-01-05 22:19:46 +0000251{
252 int fi_semicolon; /* TRUE if ending in '; var]' */
253 int fi_varcount; /* nr of variables in the list */
Bram Moolenaar33570922005-01-25 22:26:29 +0000254 listwatch_T fi_lw; /* keep an eye on the item used. */
255 list_T *fi_list; /* list being used */
256} forinfo_T;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +0000257
Bram Moolenaar3d60ec22005-01-05 22:19:46 +0000258/*
Bram Moolenaar9ef486d2005-01-17 22:23:00 +0000259 * Struct used by trans_function_name()
260 */
261typedef struct
262{
Bram Moolenaar33570922005-01-25 22:26:29 +0000263 dict_T *fd_dict; /* Dictionary used */
Bram Moolenaar532c7802005-01-27 14:44:31 +0000264 char_u *fd_newkey; /* new key in "dict" in allocated memory */
Bram Moolenaar33570922005-01-25 22:26:29 +0000265 dictitem_T *fd_di; /* Dictionary item used */
266} funcdict_T;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +0000267
Bram Moolenaara7043832005-01-21 11:56:39 +0000268
269/*
Bram Moolenaar33570922005-01-25 22:26:29 +0000270 * Array to hold the value of v: variables.
271 * The value is in a dictitem, so that it can also be used in the v: scope.
272 * The reason to use this table anyway is for very quick access to the
273 * variables with the VV_ defines.
274 */
275#include "version.h"
276
277/* values for vv_flags: */
278#define VV_COMPAT 1 /* compatible, also used without "v:" */
279#define VV_RO 2 /* read-only */
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +0000280#define VV_RO_SBX 4 /* read-only in the sandbox */
Bram Moolenaar33570922005-01-25 22:26:29 +0000281
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +0000282#define VV_NAME(s, t) s, {{t}}, {0}
Bram Moolenaar33570922005-01-25 22:26:29 +0000283
284static struct vimvar
285{
286 char *vv_name; /* name of variable, without v: */
Bram Moolenaar33570922005-01-25 22:26:29 +0000287 dictitem_T vv_di; /* value and name for key */
288 char vv_filler[16]; /* space for LONGEST name below!!! */
289 char vv_flags; /* VV_COMPAT, VV_RO, VV_RO_SBX */
290} vimvars[VV_LEN] =
291{
292 /*
293 * The order here must match the VV_ defines in vim.h!
294 * Initializing a union does not work, leave tv.vval empty to get zero's.
295 */
296 {VV_NAME("count", VAR_NUMBER), VV_COMPAT+VV_RO},
297 {VV_NAME("count1", VAR_NUMBER), VV_RO},
298 {VV_NAME("prevcount", VAR_NUMBER), VV_RO},
299 {VV_NAME("errmsg", VAR_STRING), VV_COMPAT},
300 {VV_NAME("warningmsg", VAR_STRING), 0},
301 {VV_NAME("statusmsg", VAR_STRING), 0},
302 {VV_NAME("shell_error", VAR_NUMBER), VV_COMPAT+VV_RO},
303 {VV_NAME("this_session", VAR_STRING), VV_COMPAT},
304 {VV_NAME("version", VAR_NUMBER), VV_COMPAT+VV_RO},
305 {VV_NAME("lnum", VAR_NUMBER), VV_RO_SBX},
306 {VV_NAME("termresponse", VAR_STRING), VV_RO},
307 {VV_NAME("fname", VAR_STRING), VV_RO},
308 {VV_NAME("lang", VAR_STRING), VV_RO},
309 {VV_NAME("lc_time", VAR_STRING), VV_RO},
310 {VV_NAME("ctype", VAR_STRING), VV_RO},
311 {VV_NAME("charconvert_from", VAR_STRING), VV_RO},
312 {VV_NAME("charconvert_to", VAR_STRING), VV_RO},
313 {VV_NAME("fname_in", VAR_STRING), VV_RO},
314 {VV_NAME("fname_out", VAR_STRING), VV_RO},
315 {VV_NAME("fname_new", VAR_STRING), VV_RO},
316 {VV_NAME("fname_diff", VAR_STRING), VV_RO},
317 {VV_NAME("cmdarg", VAR_STRING), VV_RO},
318 {VV_NAME("foldstart", VAR_NUMBER), VV_RO_SBX},
319 {VV_NAME("foldend", VAR_NUMBER), VV_RO_SBX},
320 {VV_NAME("folddashes", VAR_STRING), VV_RO_SBX},
321 {VV_NAME("foldlevel", VAR_NUMBER), VV_RO_SBX},
322 {VV_NAME("progname", VAR_STRING), VV_RO},
323 {VV_NAME("servername", VAR_STRING), VV_RO},
324 {VV_NAME("dying", VAR_NUMBER), VV_RO},
325 {VV_NAME("exception", VAR_STRING), VV_RO},
326 {VV_NAME("throwpoint", VAR_STRING), VV_RO},
327 {VV_NAME("register", VAR_STRING), VV_RO},
328 {VV_NAME("cmdbang", VAR_NUMBER), VV_RO},
329 {VV_NAME("insertmode", VAR_STRING), VV_RO},
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +0000330 {VV_NAME("val", VAR_UNKNOWN), VV_RO},
331 {VV_NAME("key", VAR_UNKNOWN), VV_RO},
Bram Moolenaar05159a02005-02-26 23:04:13 +0000332 {VV_NAME("profiling", VAR_NUMBER), VV_RO},
Bram Moolenaar19a09a12005-03-04 23:39:37 +0000333 {VV_NAME("fcs_reason", VAR_STRING), VV_RO},
334 {VV_NAME("fcs_choice", VAR_STRING), 0},
Bram Moolenaare2ac10d2005-03-07 23:26:06 +0000335 {VV_NAME("beval_bufnr", VAR_NUMBER), VV_RO},
336 {VV_NAME("beval_winnr", VAR_NUMBER), VV_RO},
337 {VV_NAME("beval_lnum", VAR_NUMBER), VV_RO},
338 {VV_NAME("beval_col", VAR_NUMBER), VV_RO},
339 {VV_NAME("beval_text", VAR_STRING), VV_RO},
Bram Moolenaar761b1132005-10-03 22:05:45 +0000340 {VV_NAME("scrollstart", VAR_STRING), 0},
Bram Moolenaard5bc83f2005-12-07 21:07:59 +0000341 {VV_NAME("swapname", VAR_STRING), VV_RO},
342 {VV_NAME("swapchoice", VAR_STRING), 0},
Bram Moolenaar33570922005-01-25 22:26:29 +0000343};
344
345/* shorthand */
346#define vv_type vv_di.di_tv.v_type
347#define vv_nr vv_di.di_tv.vval.v_number
348#define vv_str vv_di.di_tv.vval.v_string
349#define vv_tv vv_di.di_tv
350
351/*
352 * The v: variables are stored in dictionary "vimvardict".
353 * "vimvars_var" is the variable that is used for the "l:" scope.
354 */
355static dict_T vimvardict;
356static dictitem_T vimvars_var;
357#define vimvarht vimvardict.dv_hashtab
358
Bram Moolenaara40058a2005-07-11 22:42:07 +0000359static void prepare_vimvar __ARGS((int idx, typval_T *save_tv));
360static void restore_vimvar __ARGS((int idx, typval_T *save_tv));
361#if defined(FEAT_USR_CMDS) && defined(FEAT_CMDL_COMPL)
362static int call_vim_function __ARGS((char_u *func, int argc, char_u **argv, int safe, typval_T *rettv));
363#endif
364static int ex_let_vars __ARGS((char_u *arg, typval_T *tv, int copy, int semicolon, int var_count, char_u *nextchars));
365static char_u *skip_var_list __ARGS((char_u *arg, int *var_count, int *semicolon));
366static char_u *skip_var_one __ARGS((char_u *arg));
367static void list_hashtable_vars __ARGS((hashtab_T *ht, char_u *prefix, int empty));
368static void list_glob_vars __ARGS((void));
369static void list_buf_vars __ARGS((void));
370static void list_win_vars __ARGS((void));
371static void list_vim_vars __ARGS((void));
372static char_u *list_arg_vars __ARGS((exarg_T *eap, char_u *arg));
373static char_u *ex_let_one __ARGS((char_u *arg, typval_T *tv, int copy, char_u *endchars, char_u *op));
374static int check_changedtick __ARGS((char_u *arg));
375static char_u *get_lval __ARGS((char_u *name, typval_T *rettv, lval_T *lp, int unlet, int skip, int quiet, int fne_flags));
376static void clear_lval __ARGS((lval_T *lp));
377static void set_var_lval __ARGS((lval_T *lp, char_u *endp, typval_T *rettv, int copy, char_u *op));
378static int tv_op __ARGS((typval_T *tv1, typval_T *tv2, char_u *op));
379static void list_add_watch __ARGS((list_T *l, listwatch_T *lw));
380static void list_rem_watch __ARGS((list_T *l, listwatch_T *lwrem));
381static void list_fix_watch __ARGS((list_T *l, listitem_T *item));
382static void ex_unletlock __ARGS((exarg_T *eap, char_u *argstart, int deep));
383static int do_unlet_var __ARGS((lval_T *lp, char_u *name_end, int forceit));
384static int do_lock_var __ARGS((lval_T *lp, char_u *name_end, int deep, int lock));
385static void item_lock __ARGS((typval_T *tv, int deep, int lock));
386static int tv_islocked __ARGS((typval_T *tv));
387
Bram Moolenaar33570922005-01-25 22:26:29 +0000388static int eval0 __ARGS((char_u *arg, typval_T *rettv, char_u **nextcmd, int evaluate));
389static int eval1 __ARGS((char_u **arg, typval_T *rettv, int evaluate));
390static int eval2 __ARGS((char_u **arg, typval_T *rettv, int evaluate));
391static int eval3 __ARGS((char_u **arg, typval_T *rettv, int evaluate));
392static int eval4 __ARGS((char_u **arg, typval_T *rettv, int evaluate));
393static int eval5 __ARGS((char_u **arg, typval_T *rettv, int evaluate));
394static int eval6 __ARGS((char_u **arg, typval_T *rettv, int evaluate));
395static int eval7 __ARGS((char_u **arg, typval_T *rettv, int evaluate));
Bram Moolenaara40058a2005-07-11 22:42:07 +0000396
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +0000397static int eval_index __ARGS((char_u **arg, typval_T *rettv, int evaluate, int verbose));
Bram Moolenaar33570922005-01-25 22:26:29 +0000398static int get_option_tv __ARGS((char_u **arg, typval_T *rettv, int evaluate));
399static int get_string_tv __ARGS((char_u **arg, typval_T *rettv, int evaluate));
400static int get_lit_string_tv __ARGS((char_u **arg, typval_T *rettv, int evaluate));
401static int get_list_tv __ARGS((char_u **arg, typval_T *rettv, int evaluate));
402static list_T *list_alloc __ARGS((void));
Bram Moolenaar33570922005-01-25 22:26:29 +0000403static void list_free __ARGS((list_T *l));
404static listitem_T *listitem_alloc __ARGS((void));
405static void listitem_free __ARGS((listitem_T *item));
406static void listitem_remove __ARGS((list_T *l, listitem_T *item));
407static long list_len __ARGS((list_T *l));
408static int list_equal __ARGS((list_T *l1, list_T *l2, int ic));
409static int dict_equal __ARGS((dict_T *d1, dict_T *d2, int ic));
410static int tv_equal __ARGS((typval_T *tv1, typval_T *tv2, int ic));
Bram Moolenaar33570922005-01-25 22:26:29 +0000411static listitem_T *list_find __ARGS((list_T *l, long n));
412static long list_idx_of_item __ARGS((list_T *l, listitem_T *item));
Bram Moolenaar33570922005-01-25 22:26:29 +0000413static void list_append __ARGS((list_T *l, listitem_T *item));
414static int list_append_tv __ARGS((list_T *l, typval_T *tv));
Bram Moolenaar4463f292005-09-25 22:20:24 +0000415static int list_append_string __ARGS((list_T *l, char_u *str, int len));
416static int list_append_number __ARGS((list_T *l, varnumber_T n));
Bram Moolenaar33570922005-01-25 22:26:29 +0000417static int list_insert_tv __ARGS((list_T *l, typval_T *tv, listitem_T *item));
418static int list_extend __ARGS((list_T *l1, list_T *l2, listitem_T *bef));
419static int list_concat __ARGS((list_T *l1, list_T *l2, typval_T *tv));
Bram Moolenaar81bf7082005-02-12 14:31:42 +0000420static list_T *list_copy __ARGS((list_T *orig, int deep, int copyID));
Bram Moolenaar33570922005-01-25 22:26:29 +0000421static void list_remove __ARGS((list_T *l, listitem_T *item, listitem_T *item2));
422static char_u *list2string __ARGS((typval_T *tv));
Bram Moolenaar81bf7082005-02-12 14:31:42 +0000423static int list_join __ARGS((garray_T *gap, list_T *l, char_u *sep, int echo));
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +0000424static void set_ref_in_ht __ARGS((hashtab_T *ht, int copyID));
425static void set_ref_in_list __ARGS((list_T *l, int copyID));
426static void set_ref_in_item __ARGS((typval_T *tv, int copyID));
Bram Moolenaar33570922005-01-25 22:26:29 +0000427static void dict_unref __ARGS((dict_T *d));
428static void dict_free __ARGS((dict_T *d));
429static dictitem_T *dictitem_alloc __ARGS((char_u *key));
430static dictitem_T *dictitem_copy __ARGS((dictitem_T *org));
431static void dictitem_remove __ARGS((dict_T *dict, dictitem_T *item));
432static void dictitem_free __ARGS((dictitem_T *item));
Bram Moolenaar81bf7082005-02-12 14:31:42 +0000433static dict_T *dict_copy __ARGS((dict_T *orig, int deep, int copyID));
Bram Moolenaar33570922005-01-25 22:26:29 +0000434static int dict_add __ARGS((dict_T *d, dictitem_T *item));
435static long dict_len __ARGS((dict_T *d));
436static dictitem_T *dict_find __ARGS((dict_T *d, char_u *key, int len));
437static char_u *dict2string __ARGS((typval_T *tv));
438static int get_dict_tv __ARGS((char_u **arg, typval_T *rettv, int evaluate));
Bram Moolenaar33570922005-01-25 22:26:29 +0000439static char_u *echo_string __ARGS((typval_T *tv, char_u **tofree, char_u *numbuf));
440static char_u *tv2string __ARGS((typval_T *tv, char_u **tofree, char_u *numbuf));
441static char_u *string_quote __ARGS((char_u *str, int function));
442static int get_env_tv __ARGS((char_u **arg, typval_T *rettv, int evaluate));
443static int find_internal_func __ARGS((char_u *name));
444static char_u *deref_func_name __ARGS((char_u *name, int *lenp));
445static 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));
446static 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 +0000447static void emsg_funcname __ARGS((char *msg, char_u *name));
Bram Moolenaar33570922005-01-25 22:26:29 +0000448
449static void f_add __ARGS((typval_T *argvars, typval_T *rettv));
450static void f_append __ARGS((typval_T *argvars, typval_T *rettv));
451static void f_argc __ARGS((typval_T *argvars, typval_T *rettv));
452static void f_argidx __ARGS((typval_T *argvars, typval_T *rettv));
453static void f_argv __ARGS((typval_T *argvars, typval_T *rettv));
454static void f_browse __ARGS((typval_T *argvars, typval_T *rettv));
455static void f_browsedir __ARGS((typval_T *argvars, typval_T *rettv));
456static void f_bufexists __ARGS((typval_T *argvars, typval_T *rettv));
457static void f_buflisted __ARGS((typval_T *argvars, typval_T *rettv));
458static void f_bufloaded __ARGS((typval_T *argvars, typval_T *rettv));
459static void f_bufname __ARGS((typval_T *argvars, typval_T *rettv));
460static void f_bufnr __ARGS((typval_T *argvars, typval_T *rettv));
461static void f_bufwinnr __ARGS((typval_T *argvars, typval_T *rettv));
462static void f_byte2line __ARGS((typval_T *argvars, typval_T *rettv));
463static void f_byteidx __ARGS((typval_T *argvars, typval_T *rettv));
464static void f_call __ARGS((typval_T *argvars, typval_T *rettv));
465static void f_char2nr __ARGS((typval_T *argvars, typval_T *rettv));
466static void f_cindent __ARGS((typval_T *argvars, typval_T *rettv));
467static void f_col __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar572cb562005-08-05 21:35:02 +0000468#if defined(FEAT_INS_EXPAND)
469static void f_complete_add __ARGS((typval_T *argvars, typval_T *rettv));
470static void f_complete_check __ARGS((typval_T *argvars, typval_T *rettv));
471#endif
Bram Moolenaar33570922005-01-25 22:26:29 +0000472static void f_confirm __ARGS((typval_T *argvars, typval_T *rettv));
473static void f_copy __ARGS((typval_T *argvars, typval_T *rettv));
474static void f_count __ARGS((typval_T *argvars, typval_T *rettv));
475static void f_cscope_connection __ARGS((typval_T *argvars, typval_T *rettv));
476static void f_cursor __ARGS((typval_T *argsvars, typval_T *rettv));
477static void f_deepcopy __ARGS((typval_T *argvars, typval_T *rettv));
478static void f_delete __ARGS((typval_T *argvars, typval_T *rettv));
479static void f_did_filetype __ARGS((typval_T *argvars, typval_T *rettv));
480static void f_diff_filler __ARGS((typval_T *argvars, typval_T *rettv));
481static void f_diff_hlID __ARGS((typval_T *argvars, typval_T *rettv));
482static void f_empty __ARGS((typval_T *argvars, typval_T *rettv));
483static void f_escape __ARGS((typval_T *argvars, typval_T *rettv));
484static void f_eval __ARGS((typval_T *argvars, typval_T *rettv));
485static void f_eventhandler __ARGS((typval_T *argvars, typval_T *rettv));
486static void f_executable __ARGS((typval_T *argvars, typval_T *rettv));
487static void f_exists __ARGS((typval_T *argvars, typval_T *rettv));
488static void f_expand __ARGS((typval_T *argvars, typval_T *rettv));
489static void f_extend __ARGS((typval_T *argvars, typval_T *rettv));
490static void f_filereadable __ARGS((typval_T *argvars, typval_T *rettv));
491static void f_filewritable __ARGS((typval_T *argvars, typval_T *rettv));
492static void f_filter __ARGS((typval_T *argvars, typval_T *rettv));
493static void f_finddir __ARGS((typval_T *argvars, typval_T *rettv));
494static void f_findfile __ARGS((typval_T *argvars, typval_T *rettv));
495static void f_fnamemodify __ARGS((typval_T *argvars, typval_T *rettv));
496static void f_foldclosed __ARGS((typval_T *argvars, typval_T *rettv));
497static void f_foldclosedend __ARGS((typval_T *argvars, typval_T *rettv));
498static void f_foldlevel __ARGS((typval_T *argvars, typval_T *rettv));
499static void f_foldtext __ARGS((typval_T *argvars, typval_T *rettv));
500static void f_foldtextresult __ARGS((typval_T *argvars, typval_T *rettv));
501static void f_foreground __ARGS((typval_T *argvars, typval_T *rettv));
502static void f_function __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +0000503static void f_garbagecollect __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar33570922005-01-25 22:26:29 +0000504static void f_get __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar80fc0432005-07-20 22:06:07 +0000505static void f_getbufline __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar33570922005-01-25 22:26:29 +0000506static void f_getbufvar __ARGS((typval_T *argvars, typval_T *rettv));
507static void f_getchar __ARGS((typval_T *argvars, typval_T *rettv));
508static void f_getcharmod __ARGS((typval_T *argvars, typval_T *rettv));
509static void f_getcmdline __ARGS((typval_T *argvars, typval_T *rettv));
510static void f_getcmdpos __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +0000511static void f_getcmdtype __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar33570922005-01-25 22:26:29 +0000512static void f_getcwd __ARGS((typval_T *argvars, typval_T *rettv));
513static void f_getfontname __ARGS((typval_T *argvars, typval_T *rettv));
514static void f_getfperm __ARGS((typval_T *argvars, typval_T *rettv));
515static void f_getfsize __ARGS((typval_T *argvars, typval_T *rettv));
516static void f_getftime __ARGS((typval_T *argvars, typval_T *rettv));
517static void f_getftype __ARGS((typval_T *argvars, typval_T *rettv));
518static void f_getline __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar2641f772005-03-25 21:58:17 +0000519static void f_getqflist __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar33570922005-01-25 22:26:29 +0000520static void f_getreg __ARGS((typval_T *argvars, typval_T *rettv));
521static void f_getregtype __ARGS((typval_T *argvars, typval_T *rettv));
522static void f_getwinposx __ARGS((typval_T *argvars, typval_T *rettv));
523static void f_getwinposy __ARGS((typval_T *argvars, typval_T *rettv));
524static void f_getwinvar __ARGS((typval_T *argvars, typval_T *rettv));
525static void f_glob __ARGS((typval_T *argvars, typval_T *rettv));
526static void f_globpath __ARGS((typval_T *argvars, typval_T *rettv));
527static void f_has __ARGS((typval_T *argvars, typval_T *rettv));
528static void f_has_key __ARGS((typval_T *argvars, typval_T *rettv));
529static void f_hasmapto __ARGS((typval_T *argvars, typval_T *rettv));
530static void f_histadd __ARGS((typval_T *argvars, typval_T *rettv));
531static void f_histdel __ARGS((typval_T *argvars, typval_T *rettv));
532static void f_histget __ARGS((typval_T *argvars, typval_T *rettv));
533static void f_histnr __ARGS((typval_T *argvars, typval_T *rettv));
534static void f_hlID __ARGS((typval_T *argvars, typval_T *rettv));
535static void f_hlexists __ARGS((typval_T *argvars, typval_T *rettv));
536static void f_hostname __ARGS((typval_T *argvars, typval_T *rettv));
537static void f_iconv __ARGS((typval_T *argvars, typval_T *rettv));
538static void f_indent __ARGS((typval_T *argvars, typval_T *rettv));
539static void f_index __ARGS((typval_T *argvars, typval_T *rettv));
540static void f_input __ARGS((typval_T *argvars, typval_T *rettv));
541static void f_inputdialog __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar6efa2b32005-09-10 19:26:26 +0000542static void f_inputlist __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar33570922005-01-25 22:26:29 +0000543static void f_inputrestore __ARGS((typval_T *argvars, typval_T *rettv));
544static void f_inputsave __ARGS((typval_T *argvars, typval_T *rettv));
545static void f_inputsecret __ARGS((typval_T *argvars, typval_T *rettv));
546static void f_insert __ARGS((typval_T *argvars, typval_T *rettv));
547static void f_isdirectory __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar2e6aff32005-01-31 19:25:36 +0000548static void f_islocked __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar33570922005-01-25 22:26:29 +0000549static void f_items __ARGS((typval_T *argvars, typval_T *rettv));
550static void f_join __ARGS((typval_T *argvars, typval_T *rettv));
551static void f_keys __ARGS((typval_T *argvars, typval_T *rettv));
552static void f_last_buffer_nr __ARGS((typval_T *argvars, typval_T *rettv));
553static void f_len __ARGS((typval_T *argvars, typval_T *rettv));
554static void f_libcall __ARGS((typval_T *argvars, typval_T *rettv));
555static void f_libcallnr __ARGS((typval_T *argvars, typval_T *rettv));
556static void f_line __ARGS((typval_T *argvars, typval_T *rettv));
557static void f_line2byte __ARGS((typval_T *argvars, typval_T *rettv));
558static void f_lispindent __ARGS((typval_T *argvars, typval_T *rettv));
559static void f_localtime __ARGS((typval_T *argvars, typval_T *rettv));
560static void f_map __ARGS((typval_T *argvars, typval_T *rettv));
561static void f_maparg __ARGS((typval_T *argvars, typval_T *rettv));
562static void f_mapcheck __ARGS((typval_T *argvars, typval_T *rettv));
563static void f_match __ARGS((typval_T *argvars, typval_T *rettv));
564static void f_matchend __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +0000565static void f_matchlist __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar33570922005-01-25 22:26:29 +0000566static void f_matchstr __ARGS((typval_T *argvars, typval_T *rettv));
567static void f_max __ARGS((typval_T *argvars, typval_T *rettv));
568static void f_min __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000569#ifdef vim_mkdir
570static void f_mkdir __ARGS((typval_T *argvars, typval_T *rettv));
571#endif
Bram Moolenaar33570922005-01-25 22:26:29 +0000572static void f_mode __ARGS((typval_T *argvars, typval_T *rettv));
573static void f_nextnonblank __ARGS((typval_T *argvars, typval_T *rettv));
574static void f_nr2char __ARGS((typval_T *argvars, typval_T *rettv));
575static void f_prevnonblank __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar4be06f92005-07-29 22:36:03 +0000576static void f_printf __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar33570922005-01-25 22:26:29 +0000577static void f_range __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +0000578static void f_readfile __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar33570922005-01-25 22:26:29 +0000579static void f_remote_expr __ARGS((typval_T *argvars, typval_T *rettv));
580static void f_remote_foreground __ARGS((typval_T *argvars, typval_T *rettv));
581static void f_remote_peek __ARGS((typval_T *argvars, typval_T *rettv));
582static void f_remote_read __ARGS((typval_T *argvars, typval_T *rettv));
583static void f_remote_send __ARGS((typval_T *argvars, typval_T *rettv));
584static void f_remove __ARGS((typval_T *argvars, typval_T *rettv));
585static void f_rename __ARGS((typval_T *argvars, typval_T *rettv));
586static void f_repeat __ARGS((typval_T *argvars, typval_T *rettv));
587static void f_resolve __ARGS((typval_T *argvars, typval_T *rettv));
588static void f_reverse __ARGS((typval_T *argvars, typval_T *rettv));
589static void f_search __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaardd2436f2005-09-05 22:14:46 +0000590static void f_searchdecl __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar33570922005-01-25 22:26:29 +0000591static void f_searchpair __ARGS((typval_T *argvars, typval_T *rettv));
592static void f_server2client __ARGS((typval_T *argvars, typval_T *rettv));
593static void f_serverlist __ARGS((typval_T *argvars, typval_T *rettv));
594static void f_setbufvar __ARGS((typval_T *argvars, typval_T *rettv));
595static void f_setcmdpos __ARGS((typval_T *argvars, typval_T *rettv));
596static void f_setline __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar2641f772005-03-25 21:58:17 +0000597static void f_setqflist __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar33570922005-01-25 22:26:29 +0000598static void f_setreg __ARGS((typval_T *argvars, typval_T *rettv));
599static void f_setwinvar __ARGS((typval_T *argvars, typval_T *rettv));
600static void f_simplify __ARGS((typval_T *argvars, typval_T *rettv));
601static void f_sort __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar24bbcfe2005-06-28 23:32:02 +0000602static void f_soundfold __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaard857f0e2005-06-21 22:37:39 +0000603static void f_spellbadword __ARGS((typval_T *argvars, typval_T *rettv));
604static void f_spellsuggest __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar33570922005-01-25 22:26:29 +0000605static void f_split __ARGS((typval_T *argvars, typval_T *rettv));
606#ifdef HAVE_STRFTIME
607static void f_strftime __ARGS((typval_T *argvars, typval_T *rettv));
608#endif
609static void f_stridx __ARGS((typval_T *argvars, typval_T *rettv));
610static void f_string __ARGS((typval_T *argvars, typval_T *rettv));
611static void f_strlen __ARGS((typval_T *argvars, typval_T *rettv));
612static void f_strpart __ARGS((typval_T *argvars, typval_T *rettv));
613static void f_strridx __ARGS((typval_T *argvars, typval_T *rettv));
614static void f_strtrans __ARGS((typval_T *argvars, typval_T *rettv));
615static void f_submatch __ARGS((typval_T *argvars, typval_T *rettv));
616static void f_substitute __ARGS((typval_T *argvars, typval_T *rettv));
617static void f_synID __ARGS((typval_T *argvars, typval_T *rettv));
618static void f_synIDattr __ARGS((typval_T *argvars, typval_T *rettv));
619static void f_synIDtrans __ARGS((typval_T *argvars, typval_T *rettv));
620static void f_system __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar19a09a12005-03-04 23:39:37 +0000621static void f_taglist __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaard43b6cf2005-09-09 19:53:42 +0000622static void f_tagfiles __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar33570922005-01-25 22:26:29 +0000623static void f_tempname __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaard52d9742005-08-21 22:20:28 +0000624static void f_test __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar33570922005-01-25 22:26:29 +0000625static void f_tolower __ARGS((typval_T *argvars, typval_T *rettv));
626static void f_toupper __ARGS((typval_T *argvars, typval_T *rettv));
627static void f_tr __ARGS((typval_T *argvars, typval_T *rettv));
628static void f_type __ARGS((typval_T *argvars, typval_T *rettv));
629static void f_values __ARGS((typval_T *argvars, typval_T *rettv));
630static void f_virtcol __ARGS((typval_T *argvars, typval_T *rettv));
631static void f_visualmode __ARGS((typval_T *argvars, typval_T *rettv));
632static void f_winbufnr __ARGS((typval_T *argvars, typval_T *rettv));
633static void f_wincol __ARGS((typval_T *argvars, typval_T *rettv));
634static void f_winheight __ARGS((typval_T *argvars, typval_T *rettv));
635static void f_winline __ARGS((typval_T *argvars, typval_T *rettv));
636static void f_winnr __ARGS((typval_T *argvars, typval_T *rettv));
637static void f_winrestcmd __ARGS((typval_T *argvars, typval_T *rettv));
638static void f_winwidth __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +0000639static void f_writefile __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar33570922005-01-25 22:26:29 +0000640
Bram Moolenaar33570922005-01-25 22:26:29 +0000641static pos_T *var2fpos __ARGS((typval_T *varp, int lnum));
642static int get_env_len __ARGS((char_u **arg));
643static int get_id_len __ARGS((char_u **arg));
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +0000644static int get_name_len __ARGS((char_u **arg, char_u **alias, int evaluate, int verbose));
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +0000645static char_u *find_name_end __ARGS((char_u *arg, char_u **expr_start, char_u **expr_end, int flags));
646#define FNE_INCL_BR 1 /* find_name_end(): include [] in name */
647#define FNE_CHECK_START 2 /* find_name_end(): check name starts with
648 valid character */
Bram Moolenaara40058a2005-07-11 22:42:07 +0000649static char_u * make_expanded_name __ARGS((char_u *in_start, char_u *expr_start, char_u *expr_end, char_u *in_end));
Bram Moolenaar33570922005-01-25 22:26:29 +0000650static int eval_isnamec __ARGS((int c));
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +0000651static int eval_isnamec1 __ARGS((int c));
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +0000652static int get_var_tv __ARGS((char_u *name, int len, typval_T *rettv, int verbose));
653static int handle_subscript __ARGS((char_u **arg, typval_T *rettv, int evaluate, int verbose));
Bram Moolenaar33570922005-01-25 22:26:29 +0000654static typval_T *alloc_tv __ARGS((void));
655static typval_T *alloc_string_tv __ARGS((char_u *string));
656static void free_tv __ARGS((typval_T *varp));
Bram Moolenaar33570922005-01-25 22:26:29 +0000657static void init_tv __ARGS((typval_T *varp));
658static long get_tv_number __ARGS((typval_T *varp));
659static linenr_T get_tv_lnum __ARGS((typval_T *argvars));
Bram Moolenaar661b1822005-07-28 22:36:45 +0000660static linenr_T get_tv_lnum_buf __ARGS((typval_T *argvars, buf_T *buf));
Bram Moolenaar33570922005-01-25 22:26:29 +0000661static char_u *get_tv_string __ARGS((typval_T *varp));
662static char_u *get_tv_string_buf __ARGS((typval_T *varp, char_u *buf));
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +0000663static char_u *get_tv_string_buf_chk __ARGS((typval_T *varp, char_u *buf));
Bram Moolenaar33570922005-01-25 22:26:29 +0000664static dictitem_T *find_var __ARGS((char_u *name, hashtab_T **htp));
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000665static dictitem_T *find_var_in_ht __ARGS((hashtab_T *ht, char_u *varname, int writing));
Bram Moolenaar33570922005-01-25 22:26:29 +0000666static hashtab_T *find_var_ht __ARGS((char_u *name, char_u **varname));
667static void vars_clear_ext __ARGS((hashtab_T *ht, int free_val));
668static void delete_var __ARGS((hashtab_T *ht, hashitem_T *hi));
669static void list_one_var __ARGS((dictitem_T *v, char_u *prefix));
670static void list_one_var_a __ARGS((char_u *prefix, char_u *name, int type, char_u *string));
671static void set_var __ARGS((char_u *name, typval_T *varp, int copy));
672static int var_check_ro __ARGS((int flags, char_u *name));
Bram Moolenaar2e6aff32005-01-31 19:25:36 +0000673static int tv_check_lock __ARGS((int lock, char_u *name));
Bram Moolenaar33570922005-01-25 22:26:29 +0000674static void copy_tv __ARGS((typval_T *from, typval_T *to));
Bram Moolenaar81bf7082005-02-12 14:31:42 +0000675static int item_copy __ARGS((typval_T *from, typval_T *to, int deep, int copyID));
Bram Moolenaar33570922005-01-25 22:26:29 +0000676static char_u *find_option_end __ARGS((char_u **arg, int *opt_flags));
677static char_u *trans_function_name __ARGS((char_u **pp, int skip, int flags, funcdict_T *fd));
678static int eval_fname_script __ARGS((char_u *p));
679static int eval_fname_sid __ARGS((char_u *p));
680static void list_func_head __ARGS((ufunc_T *fp, int indent));
Bram Moolenaar33570922005-01-25 22:26:29 +0000681static ufunc_T *find_func __ARGS((char_u *name));
682static int function_exists __ARGS((char_u *name));
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +0000683static int builtin_function __ARGS((char_u *name));
Bram Moolenaar05159a02005-02-26 23:04:13 +0000684#ifdef FEAT_PROFILE
685static void func_do_profile __ARGS((ufunc_T *fp));
Bram Moolenaar73830342005-02-28 22:48:19 +0000686static void prof_sort_list __ARGS((FILE *fd, ufunc_T **sorttab, int st_len, char *title, int prefer_self));
687static void prof_func_line __ARGS((FILE *fd, int count, proftime_T *total, proftime_T *self, int prefer_self));
688static int
689# ifdef __BORLANDC__
690 _RTLENTRYF
691# endif
692 prof_total_cmp __ARGS((const void *s1, const void *s2));
693static int
694# ifdef __BORLANDC__
695 _RTLENTRYF
696# endif
697 prof_self_cmp __ARGS((const void *s1, const void *s2));
Bram Moolenaar05159a02005-02-26 23:04:13 +0000698#endif
Bram Moolenaar87e25fd2005-07-27 21:13:01 +0000699static int script_autoload __ARGS((char_u *name, int reload));
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000700static char_u *autoload_name __ARGS((char_u *name));
Bram Moolenaara40058a2005-07-11 22:42:07 +0000701static void cat_func_name __ARGS((char_u *buf, ufunc_T *fp));
Bram Moolenaar33570922005-01-25 22:26:29 +0000702static void func_free __ARGS((ufunc_T *fp));
703static void func_unref __ARGS((char_u *name));
704static void func_ref __ARGS((char_u *name));
705static 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));
706static void add_nr_var __ARGS((dict_T *dp, dictitem_T *v, char *name, varnumber_T nr));
707
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +0000708/* Character used as separated in autoload function/variable names. */
709#define AUTOLOAD_CHAR '#'
710
Bram Moolenaar33570922005-01-25 22:26:29 +0000711/*
712 * Initialize the global and v: variables.
Bram Moolenaara7043832005-01-21 11:56:39 +0000713 */
714 void
715eval_init()
716{
Bram Moolenaar33570922005-01-25 22:26:29 +0000717 int i;
718 struct vimvar *p;
719
720 init_var_dict(&globvardict, &globvars_var);
721 init_var_dict(&vimvardict, &vimvars_var);
Bram Moolenaar532c7802005-01-27 14:44:31 +0000722 hash_init(&compat_hashtab);
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000723 hash_init(&func_hashtab);
Bram Moolenaar33570922005-01-25 22:26:29 +0000724
725 for (i = 0; i < VV_LEN; ++i)
726 {
727 p = &vimvars[i];
728 STRCPY(p->vv_di.di_key, p->vv_name);
729 if (p->vv_flags & VV_RO)
730 p->vv_di.di_flags = DI_FLAGS_RO | DI_FLAGS_FIX;
731 else if (p->vv_flags & VV_RO_SBX)
732 p->vv_di.di_flags = DI_FLAGS_RO_SBX | DI_FLAGS_FIX;
733 else
734 p->vv_di.di_flags = DI_FLAGS_FIX;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +0000735
736 /* add to v: scope dict, unless the value is not always available */
737 if (p->vv_type != VAR_UNKNOWN)
738 hash_add(&vimvarht, p->vv_di.di_key);
Bram Moolenaar33570922005-01-25 22:26:29 +0000739 if (p->vv_flags & VV_COMPAT)
Bram Moolenaar532c7802005-01-27 14:44:31 +0000740 /* add to compat scope dict */
741 hash_add(&compat_hashtab, p->vv_di.di_key);
Bram Moolenaar33570922005-01-25 22:26:29 +0000742 }
Bram Moolenaara7043832005-01-21 11:56:39 +0000743}
744
Bram Moolenaar29a1c1d2005-06-24 23:11:15 +0000745#if defined(EXITFREE) || defined(PROTO)
746 void
747eval_clear()
748{
749 int i;
750 struct vimvar *p;
751
752 for (i = 0; i < VV_LEN; ++i)
753 {
754 p = &vimvars[i];
755 if (p->vv_di.di_tv.v_type == VAR_STRING)
Bram Moolenaard9fba312005-06-26 22:34:35 +0000756 {
Bram Moolenaar29a1c1d2005-06-24 23:11:15 +0000757 vim_free(p->vv_di.di_tv.vval.v_string);
Bram Moolenaard9fba312005-06-26 22:34:35 +0000758 p->vv_di.di_tv.vval.v_string = NULL;
759 }
Bram Moolenaar29a1c1d2005-06-24 23:11:15 +0000760 }
761 hash_clear(&vimvarht);
762 hash_clear(&compat_hashtab);
763
764 /* script-local variables */
765 for (i = 1; i <= ga_scripts.ga_len; ++i)
766 vars_clear(&SCRIPT_VARS(i));
767 ga_clear(&ga_scripts);
Bram Moolenaard9fba312005-06-26 22:34:35 +0000768 free_scriptnames();
Bram Moolenaar29a1c1d2005-06-24 23:11:15 +0000769
770 /* global variables */
771 vars_clear(&globvarht);
Bram Moolenaard9fba312005-06-26 22:34:35 +0000772
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +0000773 /* functions */
Bram Moolenaard9fba312005-06-26 22:34:35 +0000774 free_all_functions();
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +0000775 hash_clear(&func_hashtab);
776
777 /* unreferenced lists and dicts */
778 (void)garbage_collect();
Bram Moolenaar29a1c1d2005-06-24 23:11:15 +0000779}
780#endif
781
Bram Moolenaar9ef486d2005-01-17 22:23:00 +0000782/*
Bram Moolenaar071d4272004-06-13 20:20:40 +0000783 * Return the name of the executed function.
784 */
785 char_u *
786func_name(cookie)
787 void *cookie;
788{
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000789 return ((funccall_T *)cookie)->func->uf_name;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000790}
791
792/*
793 * Return the address holding the next breakpoint line for a funccall cookie.
794 */
795 linenr_T *
796func_breakpoint(cookie)
797 void *cookie;
798{
Bram Moolenaar33570922005-01-25 22:26:29 +0000799 return &((funccall_T *)cookie)->breakpoint;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000800}
801
802/*
803 * Return the address holding the debug tick for a funccall cookie.
804 */
805 int *
806func_dbg_tick(cookie)
807 void *cookie;
808{
Bram Moolenaar33570922005-01-25 22:26:29 +0000809 return &((funccall_T *)cookie)->dbg_tick;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000810}
811
812/*
813 * Return the nesting level for a funccall cookie.
814 */
815 int
816func_level(cookie)
817 void *cookie;
818{
Bram Moolenaar33570922005-01-25 22:26:29 +0000819 return ((funccall_T *)cookie)->level;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000820}
821
822/* pointer to funccal for currently active function */
Bram Moolenaar33570922005-01-25 22:26:29 +0000823funccall_T *current_funccal = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000824
825/*
826 * Return TRUE when a function was ended by a ":return" command.
827 */
828 int
829current_func_returned()
830{
831 return current_funccal->returned;
832}
833
834
835/*
Bram Moolenaar071d4272004-06-13 20:20:40 +0000836 * Set an internal variable to a string value. Creates the variable if it does
837 * not already exist.
838 */
839 void
840set_internal_string_var(name, value)
841 char_u *name;
842 char_u *value;
843{
Bram Moolenaar49cd9572005-01-03 21:06:01 +0000844 char_u *val;
Bram Moolenaar33570922005-01-25 22:26:29 +0000845 typval_T *tvp;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000846
847 val = vim_strsave(value);
848 if (val != NULL)
849 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000850 tvp = alloc_string_tv(val);
Bram Moolenaar49cd9572005-01-03 21:06:01 +0000851 if (tvp != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000852 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +0000853 set_var(name, tvp, FALSE);
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000854 free_tv(tvp);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000855 }
856 }
857}
858
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000859static lval_T *redir_lval = NULL;
860static char_u *redir_endp = NULL;
861static char_u *redir_varname = NULL;
862
863/*
864 * Start recording command output to a variable
865 * Returns OK if successfully completed the setup. FAIL otherwise.
866 */
867 int
868var_redir_start(name, append)
869 char_u *name;
870 int append; /* append to an existing variable */
871{
872 int save_emsg;
873 int err;
874 typval_T tv;
875
876 /* Make sure a valid variable name is specified */
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +0000877 if (!eval_isnamec1(*name))
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000878 {
879 EMSG(_(e_invarg));
880 return FAIL;
881 }
882
883 redir_varname = vim_strsave(name);
884 if (redir_varname == NULL)
885 return FAIL;
886
887 redir_lval = (lval_T *)alloc_clear((unsigned)sizeof(lval_T));
888 if (redir_lval == NULL)
889 {
890 var_redir_stop();
891 return FAIL;
892 }
893
894 /* Parse the variable name (can be a dict or list entry). */
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +0000895 redir_endp = get_lval(redir_varname, NULL, redir_lval, FALSE, FALSE, FALSE,
896 FNE_CHECK_START);
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000897 if (redir_endp == NULL || redir_lval->ll_name == NULL || *redir_endp != NUL)
898 {
899 if (redir_endp != NULL && *redir_endp != NUL)
900 /* Trailing characters are present after the variable name */
901 EMSG(_(e_trailing));
902 else
903 EMSG(_(e_invarg));
904 var_redir_stop();
905 return FAIL;
906 }
907
908 /* check if we can write to the variable: set it to or append an empty
909 * string */
910 save_emsg = did_emsg;
911 did_emsg = FALSE;
912 tv.v_type = VAR_STRING;
913 tv.vval.v_string = (char_u *)"";
914 if (append)
915 set_var_lval(redir_lval, redir_endp, &tv, TRUE, (char_u *)".");
916 else
917 set_var_lval(redir_lval, redir_endp, &tv, TRUE, (char_u *)"=");
918 err = did_emsg;
919 did_emsg += save_emsg;
920 if (err)
921 {
922 var_redir_stop();
923 return FAIL;
924 }
925 if (redir_lval->ll_newkey != NULL)
926 {
927 /* Dictionary item was created, don't do it again. */
928 vim_free(redir_lval->ll_newkey);
929 redir_lval->ll_newkey = NULL;
930 }
931
932 return OK;
933}
934
935/*
936 * Append "value[len]" to the variable set by var_redir_start().
937 */
938 void
939var_redir_str(value, len)
940 char_u *value;
941 int len;
942{
943 char_u *val;
944 typval_T tv;
945 int save_emsg;
946 int err;
947
948 if (redir_lval == NULL)
949 return;
950
951 if (len == -1)
952 /* Append the entire string */
953 val = vim_strsave(value);
954 else
955 /* Append only the specified number of characters */
956 val = vim_strnsave(value, len);
957 if (val == NULL)
958 return;
959
960 tv.v_type = VAR_STRING;
961 tv.vval.v_string = val;
962
963 save_emsg = did_emsg;
964 did_emsg = FALSE;
965 set_var_lval(redir_lval, redir_endp, &tv, FALSE, (char_u *)".");
966 err = did_emsg;
967 did_emsg += save_emsg;
968 if (err)
969 var_redir_stop();
970
971 vim_free(tv.vval.v_string);
972}
973
974/*
975 * Stop redirecting command output to a variable.
976 */
977 void
978var_redir_stop()
979{
980 if (redir_lval != NULL)
981 {
982 clear_lval(redir_lval);
983 vim_free(redir_lval);
984 redir_lval = NULL;
985 }
986 vim_free(redir_varname);
987 redir_varname = NULL;
988}
989
Bram Moolenaar071d4272004-06-13 20:20:40 +0000990# if defined(FEAT_MBYTE) || defined(PROTO)
991 int
992eval_charconvert(enc_from, enc_to, fname_from, fname_to)
993 char_u *enc_from;
994 char_u *enc_to;
995 char_u *fname_from;
996 char_u *fname_to;
997{
998 int err = FALSE;
999
1000 set_vim_var_string(VV_CC_FROM, enc_from, -1);
1001 set_vim_var_string(VV_CC_TO, enc_to, -1);
1002 set_vim_var_string(VV_FNAME_IN, fname_from, -1);
1003 set_vim_var_string(VV_FNAME_OUT, fname_to, -1);
1004 if (eval_to_bool(p_ccv, &err, NULL, FALSE))
1005 err = TRUE;
1006 set_vim_var_string(VV_CC_FROM, NULL, -1);
1007 set_vim_var_string(VV_CC_TO, NULL, -1);
1008 set_vim_var_string(VV_FNAME_IN, NULL, -1);
1009 set_vim_var_string(VV_FNAME_OUT, NULL, -1);
1010
1011 if (err)
1012 return FAIL;
1013 return OK;
1014}
1015# endif
1016
1017# if defined(FEAT_POSTSCRIPT) || defined(PROTO)
1018 int
1019eval_printexpr(fname, args)
1020 char_u *fname;
1021 char_u *args;
1022{
1023 int err = FALSE;
1024
1025 set_vim_var_string(VV_FNAME_IN, fname, -1);
1026 set_vim_var_string(VV_CMDARG, args, -1);
1027 if (eval_to_bool(p_pexpr, &err, NULL, FALSE))
1028 err = TRUE;
1029 set_vim_var_string(VV_FNAME_IN, NULL, -1);
1030 set_vim_var_string(VV_CMDARG, NULL, -1);
1031
1032 if (err)
1033 {
1034 mch_remove(fname);
1035 return FAIL;
1036 }
1037 return OK;
1038}
1039# endif
1040
1041# if defined(FEAT_DIFF) || defined(PROTO)
1042 void
1043eval_diff(origfile, newfile, outfile)
1044 char_u *origfile;
1045 char_u *newfile;
1046 char_u *outfile;
1047{
1048 int err = FALSE;
1049
1050 set_vim_var_string(VV_FNAME_IN, origfile, -1);
1051 set_vim_var_string(VV_FNAME_NEW, newfile, -1);
1052 set_vim_var_string(VV_FNAME_OUT, outfile, -1);
1053 (void)eval_to_bool(p_dex, &err, NULL, FALSE);
1054 set_vim_var_string(VV_FNAME_IN, NULL, -1);
1055 set_vim_var_string(VV_FNAME_NEW, NULL, -1);
1056 set_vim_var_string(VV_FNAME_OUT, NULL, -1);
1057}
1058
1059 void
1060eval_patch(origfile, difffile, outfile)
1061 char_u *origfile;
1062 char_u *difffile;
1063 char_u *outfile;
1064{
1065 int err;
1066
1067 set_vim_var_string(VV_FNAME_IN, origfile, -1);
1068 set_vim_var_string(VV_FNAME_DIFF, difffile, -1);
1069 set_vim_var_string(VV_FNAME_OUT, outfile, -1);
1070 (void)eval_to_bool(p_pex, &err, NULL, FALSE);
1071 set_vim_var_string(VV_FNAME_IN, NULL, -1);
1072 set_vim_var_string(VV_FNAME_DIFF, NULL, -1);
1073 set_vim_var_string(VV_FNAME_OUT, NULL, -1);
1074}
1075# endif
1076
1077/*
1078 * Top level evaluation function, returning a boolean.
1079 * Sets "error" to TRUE if there was an error.
1080 * Return TRUE or FALSE.
1081 */
1082 int
1083eval_to_bool(arg, error, nextcmd, skip)
1084 char_u *arg;
1085 int *error;
1086 char_u **nextcmd;
1087 int skip; /* only parse, don't execute */
1088{
Bram Moolenaar33570922005-01-25 22:26:29 +00001089 typval_T tv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001090 int retval = FALSE;
1091
1092 if (skip)
1093 ++emsg_skip;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001094 if (eval0(arg, &tv, nextcmd, !skip) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001095 *error = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001096 else
1097 {
1098 *error = FALSE;
1099 if (!skip)
1100 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00001101 retval = (get_tv_number_chk(&tv, error) != 0);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001102 clear_tv(&tv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001103 }
1104 }
1105 if (skip)
1106 --emsg_skip;
1107
1108 return retval;
1109}
1110
1111/*
1112 * Top level evaluation function, returning a string. If "skip" is TRUE,
1113 * only parsing to "nextcmd" is done, without reporting errors. Return
1114 * pointer to allocated memory, or NULL for failure or when "skip" is TRUE.
1115 */
1116 char_u *
1117eval_to_string_skip(arg, nextcmd, skip)
1118 char_u *arg;
1119 char_u **nextcmd;
1120 int skip; /* only parse, don't execute */
1121{
Bram Moolenaar33570922005-01-25 22:26:29 +00001122 typval_T tv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001123 char_u *retval;
1124
1125 if (skip)
1126 ++emsg_skip;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001127 if (eval0(arg, &tv, nextcmd, !skip) == FAIL || skip)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001128 retval = NULL;
1129 else
1130 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001131 retval = vim_strsave(get_tv_string(&tv));
1132 clear_tv(&tv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001133 }
1134 if (skip)
1135 --emsg_skip;
1136
1137 return retval;
1138}
1139
1140/*
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001141 * Skip over an expression at "*pp".
1142 * Return FAIL for an error, OK otherwise.
1143 */
1144 int
1145skip_expr(pp)
1146 char_u **pp;
1147{
Bram Moolenaar33570922005-01-25 22:26:29 +00001148 typval_T rettv;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001149
1150 *pp = skipwhite(*pp);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001151 return eval1(pp, &rettv, FALSE);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001152}
1153
1154/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00001155 * Top level evaluation function, returning a string.
1156 * Return pointer to allocated memory, or NULL for failure.
1157 */
1158 char_u *
1159eval_to_string(arg, nextcmd)
1160 char_u *arg;
1161 char_u **nextcmd;
1162{
Bram Moolenaar33570922005-01-25 22:26:29 +00001163 typval_T tv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001164 char_u *retval;
1165
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001166 if (eval0(arg, &tv, nextcmd, TRUE) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001167 retval = NULL;
1168 else
1169 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001170 retval = vim_strsave(get_tv_string(&tv));
1171 clear_tv(&tv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001172 }
1173
1174 return retval;
1175}
1176
1177/*
1178 * Call eval_to_string() with "sandbox" set and not using local variables.
1179 */
1180 char_u *
1181eval_to_string_safe(arg, nextcmd)
1182 char_u *arg;
1183 char_u **nextcmd;
1184{
1185 char_u *retval;
1186 void *save_funccalp;
1187
1188 save_funccalp = save_funccal();
1189 ++sandbox;
1190 retval = eval_to_string(arg, nextcmd);
1191 --sandbox;
1192 restore_funccal(save_funccalp);
1193 return retval;
1194}
1195
Bram Moolenaar071d4272004-06-13 20:20:40 +00001196/*
1197 * Top level evaluation function, returning a number.
1198 * Evaluates "expr" silently.
1199 * Returns -1 for an error.
1200 */
1201 int
1202eval_to_number(expr)
1203 char_u *expr;
1204{
Bram Moolenaar33570922005-01-25 22:26:29 +00001205 typval_T rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001206 int retval;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00001207 char_u *p = skipwhite(expr);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001208
1209 ++emsg_off;
1210
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001211 if (eval1(&p, &rettv, TRUE) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001212 retval = -1;
1213 else
1214 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00001215 retval = get_tv_number_chk(&rettv, NULL);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001216 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001217 }
1218 --emsg_off;
1219
1220 return retval;
1221}
1222
Bram Moolenaara40058a2005-07-11 22:42:07 +00001223/*
1224 * Prepare v: variable "idx" to be used.
1225 * Save the current typeval in "save_tv".
1226 * When not used yet add the variable to the v: hashtable.
1227 */
1228 static void
1229prepare_vimvar(idx, save_tv)
1230 int idx;
1231 typval_T *save_tv;
1232{
1233 *save_tv = vimvars[idx].vv_tv;
1234 if (vimvars[idx].vv_type == VAR_UNKNOWN)
1235 hash_add(&vimvarht, vimvars[idx].vv_di.di_key);
1236}
1237
1238/*
1239 * Restore v: variable "idx" to typeval "save_tv".
1240 * When no longer defined, remove the variable from the v: hashtable.
1241 */
1242 static void
1243restore_vimvar(idx, save_tv)
1244 int idx;
1245 typval_T *save_tv;
1246{
1247 hashitem_T *hi;
1248
1249 clear_tv(&vimvars[idx].vv_tv);
1250 vimvars[idx].vv_tv = *save_tv;
1251 if (vimvars[idx].vv_type == VAR_UNKNOWN)
1252 {
1253 hi = hash_find(&vimvarht, vimvars[idx].vv_di.di_key);
1254 if (HASHITEM_EMPTY(hi))
1255 EMSG2(_(e_intern2), "restore_vimvar()");
1256 else
1257 hash_remove(&vimvarht, hi);
1258 }
1259}
1260
Bram Moolenaar24bbcfe2005-06-28 23:32:02 +00001261#if defined(FEAT_SYN_HL) || defined(PROTO)
1262/*
1263 * Evaluate an expression to a list with suggestions.
1264 * For the "expr:" part of 'spellsuggest'.
1265 */
1266 list_T *
1267eval_spell_expr(badword, expr)
1268 char_u *badword;
1269 char_u *expr;
1270{
1271 typval_T save_val;
1272 typval_T rettv;
1273 list_T *list = NULL;
1274 char_u *p = skipwhite(expr);
1275
1276 /* Set "v:val" to the bad word. */
1277 prepare_vimvar(VV_VAL, &save_val);
1278 vimvars[VV_VAL].vv_type = VAR_STRING;
1279 vimvars[VV_VAL].vv_str = badword;
1280 if (p_verbose == 0)
1281 ++emsg_off;
1282
1283 if (eval1(&p, &rettv, TRUE) == OK)
1284 {
1285 if (rettv.v_type != VAR_LIST)
1286 clear_tv(&rettv);
1287 else
1288 list = rettv.vval.v_list;
1289 }
1290
1291 if (p_verbose == 0)
1292 --emsg_off;
1293 vimvars[VV_VAL].vv_str = NULL;
1294 restore_vimvar(VV_VAL, &save_val);
1295
1296 return list;
1297}
1298
1299/*
1300 * "list" is supposed to contain two items: a word and a number. Return the
1301 * word in "pp" and the number as the return value.
1302 * Return -1 if anything isn't right.
1303 * Used to get the good word and score from the eval_spell_expr() result.
1304 */
1305 int
1306get_spellword(list, pp)
1307 list_T *list;
1308 char_u **pp;
1309{
1310 listitem_T *li;
1311
1312 li = list->lv_first;
1313 if (li == NULL)
1314 return -1;
1315 *pp = get_tv_string(&li->li_tv);
1316
1317 li = li->li_next;
1318 if (li == NULL)
1319 return -1;
1320 return get_tv_number(&li->li_tv);
1321}
1322#endif
1323
Bram Moolenaar87e25fd2005-07-27 21:13:01 +00001324/*
1325 * Top level evaluation function,
1326 */
1327 typval_T *
1328eval_expr(arg, nextcmd)
1329 char_u *arg;
1330 char_u **nextcmd;
1331{
1332 typval_T *tv;
1333
1334 tv = (typval_T *)alloc(sizeof(typval_T));
1335 if (!tv)
1336 return NULL;
1337
1338 if (eval0(arg, tv, nextcmd, TRUE) == FAIL)
1339 {
1340 vim_free(tv);
1341 return NULL;
1342 }
1343
1344 return tv;
1345}
1346
1347
Bram Moolenaar071d4272004-06-13 20:20:40 +00001348#if (defined(FEAT_USR_CMDS) && defined(FEAT_CMDL_COMPL)) || defined(PROTO)
1349/*
Bram Moolenaard8e9bb22005-07-09 21:14:46 +00001350 * Call some vimL function and return the result in "*rettv".
Bram Moolenaar071d4272004-06-13 20:20:40 +00001351 * Uses argv[argc] for the function arguments.
Bram Moolenaard8e9bb22005-07-09 21:14:46 +00001352 * Returns OK or FAIL.
Bram Moolenaar071d4272004-06-13 20:20:40 +00001353 */
Bram Moolenaard8e9bb22005-07-09 21:14:46 +00001354 static int
1355call_vim_function(func, argc, argv, safe, rettv)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001356 char_u *func;
1357 int argc;
1358 char_u **argv;
1359 int safe; /* use the sandbox */
Bram Moolenaard8e9bb22005-07-09 21:14:46 +00001360 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001361{
Bram Moolenaar33570922005-01-25 22:26:29 +00001362 typval_T *argvars;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001363 long n;
1364 int len;
1365 int i;
1366 int doesrange;
1367 void *save_funccalp = NULL;
Bram Moolenaard8e9bb22005-07-09 21:14:46 +00001368 int ret;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001369
Bram Moolenaar33570922005-01-25 22:26:29 +00001370 argvars = (typval_T *)alloc((unsigned)(argc * sizeof(typval_T)));
Bram Moolenaar071d4272004-06-13 20:20:40 +00001371 if (argvars == NULL)
Bram Moolenaard8e9bb22005-07-09 21:14:46 +00001372 return FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001373
1374 for (i = 0; i < argc; i++)
1375 {
Bram Moolenaarcfbc5ee2004-07-02 15:38:35 +00001376 /* Pass a NULL or empty argument as an empty string */
1377 if (argv[i] == NULL || *argv[i] == NUL)
1378 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +00001379 argvars[i].v_type = VAR_STRING;
1380 argvars[i].vval.v_string = (char_u *)"";
Bram Moolenaarcfbc5ee2004-07-02 15:38:35 +00001381 continue;
1382 }
1383
Bram Moolenaar071d4272004-06-13 20:20:40 +00001384 /* Recognize a number argument, the others must be strings. */
1385 vim_str2nr(argv[i], NULL, &len, TRUE, TRUE, &n, NULL);
1386 if (len != 0 && len == (int)STRLEN(argv[i]))
1387 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +00001388 argvars[i].v_type = VAR_NUMBER;
1389 argvars[i].vval.v_number = n;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001390 }
1391 else
1392 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +00001393 argvars[i].v_type = VAR_STRING;
1394 argvars[i].vval.v_string = argv[i];
Bram Moolenaar071d4272004-06-13 20:20:40 +00001395 }
1396 }
1397
1398 if (safe)
1399 {
1400 save_funccalp = save_funccal();
1401 ++sandbox;
1402 }
1403
Bram Moolenaard8e9bb22005-07-09 21:14:46 +00001404 rettv->v_type = VAR_UNKNOWN; /* clear_tv() uses this */
1405 ret = call_func(func, (int)STRLEN(func), rettv, argc, argvars,
Bram Moolenaar071d4272004-06-13 20:20:40 +00001406 curwin->w_cursor.lnum, curwin->w_cursor.lnum,
Bram Moolenaard8e9bb22005-07-09 21:14:46 +00001407 &doesrange, TRUE, NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001408 if (safe)
1409 {
1410 --sandbox;
1411 restore_funccal(save_funccalp);
1412 }
Bram Moolenaard8e9bb22005-07-09 21:14:46 +00001413 vim_free(argvars);
1414
1415 if (ret == FAIL)
1416 clear_tv(rettv);
1417
1418 return ret;
1419}
1420
1421/*
Bram Moolenaar25ceb222005-07-30 22:45:36 +00001422 * Call vimL function "func" and return the result as a string.
1423 * Returns NULL when calling the function fails.
Bram Moolenaard8e9bb22005-07-09 21:14:46 +00001424 * Uses argv[argc] for the function arguments.
1425 */
1426 void *
1427call_func_retstr(func, argc, argv, safe)
1428 char_u *func;
1429 int argc;
1430 char_u **argv;
1431 int safe; /* use the sandbox */
1432{
1433 typval_T rettv;
Bram Moolenaar25ceb222005-07-30 22:45:36 +00001434 char_u *retval;
Bram Moolenaard8e9bb22005-07-09 21:14:46 +00001435
1436 if (call_vim_function(func, argc, argv, safe, &rettv) == FAIL)
1437 return NULL;
1438
1439 retval = vim_strsave(get_tv_string(&rettv));
Bram Moolenaard8e9bb22005-07-09 21:14:46 +00001440 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001441 return retval;
1442}
Bram Moolenaard8e9bb22005-07-09 21:14:46 +00001443
Bram Moolenaar25ceb222005-07-30 22:45:36 +00001444#if defined(FEAT_COMPL_FUNC) || defined(PROTO)
Bram Moolenaard8e9bb22005-07-09 21:14:46 +00001445/*
Bram Moolenaar25ceb222005-07-30 22:45:36 +00001446 * Call vimL function "func" and return the result as a number.
1447 * Returns -1 when calling the function fails.
1448 * Uses argv[argc] for the function arguments.
1449 */
1450 long
1451call_func_retnr(func, argc, argv, safe)
1452 char_u *func;
1453 int argc;
1454 char_u **argv;
1455 int safe; /* use the sandbox */
1456{
1457 typval_T rettv;
1458 long retval;
1459
1460 if (call_vim_function(func, argc, argv, safe, &rettv) == FAIL)
1461 return -1;
1462
1463 retval = get_tv_number_chk(&rettv, NULL);
1464 clear_tv(&rettv);
1465 return retval;
1466}
1467#endif
1468
1469/*
1470 * Call vimL function "func" and return the result as a list
Bram Moolenaard8e9bb22005-07-09 21:14:46 +00001471 * Uses argv[argc] for the function arguments.
1472 */
1473 void *
1474call_func_retlist(func, argc, argv, safe)
1475 char_u *func;
1476 int argc;
1477 char_u **argv;
1478 int safe; /* use the sandbox */
1479{
1480 typval_T rettv;
1481
1482 if (call_vim_function(func, argc, argv, safe, &rettv) == FAIL)
1483 return NULL;
1484
1485 if (rettv.v_type != VAR_LIST)
1486 {
1487 clear_tv(&rettv);
1488 return NULL;
1489 }
1490
1491 return rettv.vval.v_list;
1492}
1493
Bram Moolenaar071d4272004-06-13 20:20:40 +00001494#endif
1495
1496/*
1497 * Save the current function call pointer, and set it to NULL.
1498 * Used when executing autocommands and for ":source".
1499 */
1500 void *
1501save_funccal()
1502{
Bram Moolenaar05159a02005-02-26 23:04:13 +00001503 funccall_T *fc = current_funccal;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001504
Bram Moolenaar071d4272004-06-13 20:20:40 +00001505 current_funccal = NULL;
1506 return (void *)fc;
1507}
1508
1509 void
Bram Moolenaar05159a02005-02-26 23:04:13 +00001510restore_funccal(vfc)
1511 void *vfc;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001512{
Bram Moolenaar05159a02005-02-26 23:04:13 +00001513 funccall_T *fc = (funccall_T *)vfc;
1514
1515 current_funccal = fc;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001516}
1517
Bram Moolenaar05159a02005-02-26 23:04:13 +00001518#if defined(FEAT_PROFILE) || defined(PROTO)
1519/*
1520 * Prepare profiling for entering a child or something else that is not
1521 * counted for the script/function itself.
1522 * Should always be called in pair with prof_child_exit().
1523 */
1524 void
1525prof_child_enter(tm)
1526 proftime_T *tm; /* place to store waittime */
1527{
1528 funccall_T *fc = current_funccal;
1529
1530 if (fc != NULL && fc->func->uf_profiling)
1531 profile_start(&fc->prof_child);
1532 script_prof_save(tm);
1533}
1534
1535/*
1536 * Take care of time spent in a child.
1537 * Should always be called after prof_child_enter().
1538 */
1539 void
1540prof_child_exit(tm)
1541 proftime_T *tm; /* where waittime was stored */
1542{
1543 funccall_T *fc = current_funccal;
1544
1545 if (fc != NULL && fc->func->uf_profiling)
1546 {
1547 profile_end(&fc->prof_child);
1548 profile_sub_wait(tm, &fc->prof_child); /* don't count waiting time */
1549 profile_add(&fc->func->uf_tm_children, &fc->prof_child);
1550 profile_add(&fc->func->uf_tml_children, &fc->prof_child);
1551 }
1552 script_prof_restore(tm);
1553}
1554#endif
1555
1556
Bram Moolenaar071d4272004-06-13 20:20:40 +00001557#ifdef FEAT_FOLDING
1558/*
1559 * Evaluate 'foldexpr'. Returns the foldlevel, and any character preceding
1560 * it in "*cp". Doesn't give error messages.
1561 */
1562 int
1563eval_foldexpr(arg, cp)
1564 char_u *arg;
1565 int *cp;
1566{
Bram Moolenaar33570922005-01-25 22:26:29 +00001567 typval_T tv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001568 int retval;
1569 char_u *s;
1570
1571 ++emsg_off;
1572 ++sandbox;
1573 *cp = NUL;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001574 if (eval0(arg, &tv, NULL, TRUE) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001575 retval = 0;
1576 else
1577 {
1578 /* If the result is a number, just return the number. */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001579 if (tv.v_type == VAR_NUMBER)
1580 retval = tv.vval.v_number;
Bram Moolenaar758711c2005-02-02 23:11:38 +00001581 else if (tv.v_type != VAR_STRING || tv.vval.v_string == NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001582 retval = 0;
1583 else
1584 {
1585 /* If the result is a string, check if there is a non-digit before
1586 * the number. */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001587 s = tv.vval.v_string;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001588 if (!VIM_ISDIGIT(*s) && *s != '-')
1589 *cp = *s++;
1590 retval = atol((char *)s);
1591 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001592 clear_tv(&tv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001593 }
1594 --emsg_off;
1595 --sandbox;
1596
1597 return retval;
1598}
1599#endif
1600
Bram Moolenaar071d4272004-06-13 20:20:40 +00001601/*
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001602 * ":let" list all variable values
1603 * ":let var1 var2" list variable values
1604 * ":let var = expr" assignment command.
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001605 * ":let var += expr" assignment command.
1606 * ":let var -= expr" assignment command.
1607 * ":let var .= expr" assignment command.
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001608 * ":let [var1, var2] = expr" unpack list.
Bram Moolenaar071d4272004-06-13 20:20:40 +00001609 */
1610 void
1611ex_let(eap)
1612 exarg_T *eap;
1613{
1614 char_u *arg = eap->arg;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001615 char_u *expr = NULL;
Bram Moolenaar33570922005-01-25 22:26:29 +00001616 typval_T rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001617 int i;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001618 int var_count = 0;
1619 int semicolon = 0;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001620 char_u op[2];
Bram Moolenaar071d4272004-06-13 20:20:40 +00001621
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001622 expr = skip_var_list(arg, &var_count, &semicolon);
1623 if (expr == NULL)
1624 return;
1625 expr = vim_strchr(expr, '=');
1626 if (expr == NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001627 {
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00001628 /*
1629 * ":let" without "=": list variables
1630 */
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001631 if (*arg == '[')
1632 EMSG(_(e_invarg));
1633 else if (!ends_excmd(*arg))
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001634 /* ":let var1 var2" */
1635 arg = list_arg_vars(eap, arg);
1636 else if (!eap->skip)
Bram Moolenaara7043832005-01-21 11:56:39 +00001637 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001638 /* ":let" */
Bram Moolenaara7043832005-01-21 11:56:39 +00001639 list_glob_vars();
1640 list_buf_vars();
1641 list_win_vars();
1642 list_vim_vars();
1643 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001644 eap->nextcmd = check_nextcmd(arg);
1645 }
1646 else
1647 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001648 op[0] = '=';
1649 op[1] = NUL;
1650 if (expr > arg)
1651 {
1652 if (vim_strchr((char_u *)"+-.", expr[-1]) != NULL)
1653 op[0] = expr[-1]; /* +=, -= or .= */
1654 }
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001655 expr = skipwhite(expr + 1);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001656
Bram Moolenaar071d4272004-06-13 20:20:40 +00001657 if (eap->skip)
1658 ++emsg_skip;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001659 i = eval0(expr, &rettv, &eap->nextcmd, !eap->skip);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001660 if (eap->skip)
1661 {
1662 if (i != FAIL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001663 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001664 --emsg_skip;
1665 }
1666 else if (i != FAIL)
1667 {
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001668 (void)ex_let_vars(eap->arg, &rettv, FALSE, semicolon, var_count,
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001669 op);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001670 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001671 }
1672 }
1673}
1674
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001675/*
1676 * Assign the typevalue "tv" to the variable or variables at "arg_start".
1677 * Handles both "var" with any type and "[var, var; var]" with a list type.
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001678 * When "nextchars" is not NULL it points to a string with characters that
1679 * must appear after the variable(s). Use "+", "-" or "." for add, subtract
1680 * or concatenate.
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001681 * Returns OK or FAIL;
1682 */
1683 static int
1684ex_let_vars(arg_start, tv, copy, semicolon, var_count, nextchars)
1685 char_u *arg_start;
Bram Moolenaar33570922005-01-25 22:26:29 +00001686 typval_T *tv;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001687 int copy; /* copy values from "tv", don't move */
1688 int semicolon; /* from skip_var_list() */
1689 int var_count; /* from skip_var_list() */
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001690 char_u *nextchars;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001691{
1692 char_u *arg = arg_start;
Bram Moolenaar33570922005-01-25 22:26:29 +00001693 list_T *l;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001694 int i;
Bram Moolenaar33570922005-01-25 22:26:29 +00001695 listitem_T *item;
1696 typval_T ltv;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001697
1698 if (*arg != '[')
1699 {
1700 /*
1701 * ":let var = expr" or ":for var in list"
1702 */
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001703 if (ex_let_one(arg, tv, copy, nextchars, nextchars) == NULL)
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001704 return FAIL;
1705 return OK;
1706 }
1707
1708 /*
1709 * ":let [v1, v2] = list" or ":for [v1, v2] in listlist"
1710 */
Bram Moolenaar758711c2005-02-02 23:11:38 +00001711 if (tv->v_type != VAR_LIST || (l = tv->vval.v_list) == NULL)
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001712 {
1713 EMSG(_(e_listreq));
1714 return FAIL;
1715 }
1716
1717 i = list_len(l);
1718 if (semicolon == 0 && var_count < i)
1719 {
Bram Moolenaare49b69a2005-01-08 16:11:57 +00001720 EMSG(_("E687: Less targets than List items"));
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001721 return FAIL;
1722 }
1723 if (var_count - semicolon > i)
1724 {
Bram Moolenaare49b69a2005-01-08 16:11:57 +00001725 EMSG(_("E688: More targets than List items"));
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001726 return FAIL;
1727 }
1728
1729 item = l->lv_first;
1730 while (*arg != ']')
1731 {
1732 arg = skipwhite(arg + 1);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001733 arg = ex_let_one(arg, &item->li_tv, TRUE, (char_u *)",;]", nextchars);
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001734 item = item->li_next;
1735 if (arg == NULL)
1736 return FAIL;
1737
1738 arg = skipwhite(arg);
1739 if (*arg == ';')
1740 {
1741 /* Put the rest of the list (may be empty) in the var after ';'.
1742 * Create a new list for this. */
1743 l = list_alloc();
1744 if (l == NULL)
1745 return FAIL;
1746 while (item != NULL)
1747 {
1748 list_append_tv(l, &item->li_tv);
1749 item = item->li_next;
1750 }
1751
1752 ltv.v_type = VAR_LIST;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00001753 ltv.v_lock = 0;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001754 ltv.vval.v_list = l;
1755 l->lv_refcount = 1;
1756
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001757 arg = ex_let_one(skipwhite(arg + 1), &ltv, FALSE,
1758 (char_u *)"]", nextchars);
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001759 clear_tv(&ltv);
1760 if (arg == NULL)
1761 return FAIL;
1762 break;
1763 }
1764 else if (*arg != ',' && *arg != ']')
1765 {
1766 EMSG2(_(e_intern2), "ex_let_vars()");
1767 return FAIL;
1768 }
1769 }
1770
1771 return OK;
1772}
1773
1774/*
1775 * Skip over assignable variable "var" or list of variables "[var, var]".
1776 * Used for ":let varvar = expr" and ":for varvar in expr".
1777 * For "[var, var]" increment "*var_count" for each variable.
1778 * for "[var, var; var]" set "semicolon".
1779 * Return NULL for an error.
1780 */
1781 static char_u *
1782skip_var_list(arg, var_count, semicolon)
1783 char_u *arg;
1784 int *var_count;
1785 int *semicolon;
1786{
1787 char_u *p, *s;
1788
1789 if (*arg == '[')
1790 {
1791 /* "[var, var]": find the matching ']'. */
1792 p = arg;
Bram Moolenaard8e9bb22005-07-09 21:14:46 +00001793 for (;;)
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001794 {
1795 p = skipwhite(p + 1); /* skip whites after '[', ';' or ',' */
1796 s = skip_var_one(p);
1797 if (s == p)
1798 {
1799 EMSG2(_(e_invarg2), p);
1800 return NULL;
1801 }
1802 ++*var_count;
1803
1804 p = skipwhite(s);
1805 if (*p == ']')
1806 break;
1807 else if (*p == ';')
1808 {
1809 if (*semicolon == 1)
1810 {
1811 EMSG(_("Double ; in list of variables"));
1812 return NULL;
1813 }
1814 *semicolon = 1;
1815 }
1816 else if (*p != ',')
1817 {
1818 EMSG2(_(e_invarg2), p);
1819 return NULL;
1820 }
1821 }
1822 return p + 1;
1823 }
1824 else
1825 return skip_var_one(arg);
1826}
1827
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001828/*
Bram Moolenaar92124a32005-06-17 22:03:40 +00001829 * Skip one (assignable) variable name, includig @r, $VAR, &option, d.key,
1830 * l[idx].
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001831 */
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001832 static char_u *
1833skip_var_one(arg)
1834 char_u *arg;
1835{
Bram Moolenaar92124a32005-06-17 22:03:40 +00001836 if (*arg == '@' && arg[1] != NUL)
1837 return arg + 2;
1838 return find_name_end(*arg == '$' || *arg == '&' ? arg + 1 : arg,
1839 NULL, NULL, FNE_INCL_BR | FNE_CHECK_START);
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001840}
1841
Bram Moolenaara7043832005-01-21 11:56:39 +00001842/*
Bram Moolenaar33570922005-01-25 22:26:29 +00001843 * List variables for hashtab "ht" with prefix "prefix".
1844 * If "empty" is TRUE also list NULL strings as empty strings.
Bram Moolenaara7043832005-01-21 11:56:39 +00001845 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001846 static void
Bram Moolenaar33570922005-01-25 22:26:29 +00001847list_hashtable_vars(ht, prefix, empty)
1848 hashtab_T *ht;
Bram Moolenaara7043832005-01-21 11:56:39 +00001849 char_u *prefix;
Bram Moolenaar33570922005-01-25 22:26:29 +00001850 int empty;
Bram Moolenaara7043832005-01-21 11:56:39 +00001851{
Bram Moolenaar33570922005-01-25 22:26:29 +00001852 hashitem_T *hi;
1853 dictitem_T *di;
Bram Moolenaara7043832005-01-21 11:56:39 +00001854 int todo;
1855
1856 todo = ht->ht_used;
1857 for (hi = ht->ht_array; todo > 0 && !got_int; ++hi)
1858 {
1859 if (!HASHITEM_EMPTY(hi))
1860 {
1861 --todo;
Bram Moolenaar33570922005-01-25 22:26:29 +00001862 di = HI2DI(hi);
1863 if (empty || di->di_tv.v_type != VAR_STRING
1864 || di->di_tv.vval.v_string != NULL)
1865 list_one_var(di, prefix);
Bram Moolenaara7043832005-01-21 11:56:39 +00001866 }
1867 }
1868}
1869
1870/*
1871 * List global variables.
1872 */
1873 static void
1874list_glob_vars()
1875{
Bram Moolenaar33570922005-01-25 22:26:29 +00001876 list_hashtable_vars(&globvarht, (char_u *)"", TRUE);
Bram Moolenaara7043832005-01-21 11:56:39 +00001877}
1878
1879/*
1880 * List buffer variables.
1881 */
1882 static void
1883list_buf_vars()
1884{
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001885 char_u numbuf[NUMBUFLEN];
1886
Bram Moolenaar33570922005-01-25 22:26:29 +00001887 list_hashtable_vars(&curbuf->b_vars.dv_hashtab, (char_u *)"b:", TRUE);
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001888
1889 sprintf((char *)numbuf, "%ld", (long)curbuf->b_changedtick);
1890 list_one_var_a((char_u *)"b:", (char_u *)"changedtick", VAR_NUMBER, numbuf);
Bram Moolenaara7043832005-01-21 11:56:39 +00001891}
1892
1893/*
1894 * List window variables.
1895 */
1896 static void
1897list_win_vars()
1898{
Bram Moolenaar33570922005-01-25 22:26:29 +00001899 list_hashtable_vars(&curwin->w_vars.dv_hashtab, (char_u *)"w:", TRUE);
Bram Moolenaara7043832005-01-21 11:56:39 +00001900}
1901
1902/*
1903 * List Vim variables.
1904 */
1905 static void
1906list_vim_vars()
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001907{
Bram Moolenaar33570922005-01-25 22:26:29 +00001908 list_hashtable_vars(&vimvarht, (char_u *)"v:", FALSE);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001909}
1910
1911/*
1912 * List variables in "arg".
1913 */
1914 static char_u *
1915list_arg_vars(eap, arg)
1916 exarg_T *eap;
1917 char_u *arg;
1918{
1919 int error = FALSE;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001920 int len;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001921 char_u *name;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001922 char_u *name_start;
1923 char_u *arg_subsc;
1924 char_u *tofree;
1925 typval_T tv;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001926
1927 while (!ends_excmd(*arg) && !got_int)
1928 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001929 if (error || eap->skip)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001930 {
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +00001931 arg = find_name_end(arg, NULL, NULL, FNE_INCL_BR | FNE_CHECK_START);
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001932 if (!vim_iswhite(*arg) && !ends_excmd(*arg))
1933 {
1934 emsg_severe = TRUE;
1935 EMSG(_(e_trailing));
1936 break;
1937 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001938 }
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001939 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001940 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001941 /* get_name_len() takes care of expanding curly braces */
1942 name_start = name = arg;
1943 len = get_name_len(&arg, &tofree, TRUE, TRUE);
1944 if (len <= 0)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001945 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001946 /* This is mainly to keep test 49 working: when expanding
1947 * curly braces fails overrule the exception error message. */
1948 if (len < 0 && !aborting())
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001949 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001950 emsg_severe = TRUE;
1951 EMSG2(_(e_invarg2), arg);
1952 break;
1953 }
1954 error = TRUE;
1955 }
1956 else
1957 {
1958 if (tofree != NULL)
1959 name = tofree;
1960 if (get_var_tv(name, len, &tv, TRUE) == FAIL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001961 error = TRUE;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001962 else
1963 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001964 /* handle d.key, l[idx], f(expr) */
1965 arg_subsc = arg;
1966 if (handle_subscript(&arg, &tv, TRUE, TRUE) == FAIL)
Bram Moolenaara7043832005-01-21 11:56:39 +00001967 error = TRUE;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001968 else
Bram Moolenaara7043832005-01-21 11:56:39 +00001969 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001970 if (arg == arg_subsc && len == 2 && name[1] == ':')
Bram Moolenaara7043832005-01-21 11:56:39 +00001971 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001972 switch (*name)
Bram Moolenaara7043832005-01-21 11:56:39 +00001973 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001974 case 'g': list_glob_vars(); break;
1975 case 'b': list_buf_vars(); break;
1976 case 'w': list_win_vars(); break;
1977 case 'v': list_vim_vars(); break;
1978 default:
1979 EMSG2(_("E738: Can't list variables for %s"), name);
Bram Moolenaara7043832005-01-21 11:56:39 +00001980 }
Bram Moolenaara7043832005-01-21 11:56:39 +00001981 }
1982 else
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001983 {
1984 char_u numbuf[NUMBUFLEN];
1985 char_u *tf;
1986 int c;
1987 char_u *s;
1988
1989 s = echo_string(&tv, &tf, numbuf);
1990 c = *arg;
1991 *arg = NUL;
1992 list_one_var_a((char_u *)"",
1993 arg == arg_subsc ? name : name_start,
1994 tv.v_type, s == NULL ? (char_u *)"" : s);
1995 *arg = c;
1996 vim_free(tf);
1997 }
1998 clear_tv(&tv);
Bram Moolenaara7043832005-01-21 11:56:39 +00001999 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002000 }
2001 }
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00002002
2003 vim_free(tofree);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002004 }
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00002005
2006 arg = skipwhite(arg);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002007 }
2008
2009 return arg;
2010}
2011
2012/*
2013 * Set one item of ":let var = expr" or ":let [v1, v2] = list" to its value.
2014 * Returns a pointer to the char just after the var name.
2015 * Returns NULL if there is an error.
2016 */
2017 static char_u *
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002018ex_let_one(arg, tv, copy, endchars, op)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002019 char_u *arg; /* points to variable name */
Bram Moolenaar33570922005-01-25 22:26:29 +00002020 typval_T *tv; /* value to assign to variable */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002021 int copy; /* copy value from "tv" */
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002022 char_u *endchars; /* valid chars after variable name or NULL */
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002023 char_u *op; /* "+", "-", "." or NULL*/
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002024{
2025 int c1;
2026 char_u *name;
2027 char_u *p;
2028 char_u *arg_end = NULL;
2029 int len;
2030 int opt_flags;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002031 char_u *tofree = NULL;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002032
2033 /*
2034 * ":let $VAR = expr": Set environment variable.
2035 */
2036 if (*arg == '$')
2037 {
2038 /* Find the end of the name. */
2039 ++arg;
2040 name = arg;
2041 len = get_env_len(&arg);
2042 if (len == 0)
2043 EMSG2(_(e_invarg2), name - 1);
2044 else
2045 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002046 if (op != NULL && (*op == '+' || *op == '-'))
2047 EMSG2(_(e_letwrong), op);
2048 else if (endchars != NULL
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002049 && vim_strchr(endchars, *skipwhite(arg)) == NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002050 EMSG(_(e_letunexp));
2051 else
2052 {
2053 c1 = name[len];
2054 name[len] = NUL;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00002055 p = get_tv_string_chk(tv);
2056 if (p != NULL && op != NULL && *op == '.')
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002057 {
2058 int mustfree = FALSE;
2059 char_u *s = vim_getenv(name, &mustfree);
2060
2061 if (s != NULL)
2062 {
2063 p = tofree = concat_str(s, p);
2064 if (mustfree)
2065 vim_free(s);
2066 }
2067 }
2068 if (p != NULL)
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00002069 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002070 vim_setenv(name, p);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00002071 if (STRICMP(name, "HOME") == 0)
2072 init_homedir();
2073 else if (didset_vim && STRICMP(name, "VIM") == 0)
2074 didset_vim = FALSE;
2075 else if (didset_vimruntime
2076 && STRICMP(name, "VIMRUNTIME") == 0)
2077 didset_vimruntime = FALSE;
2078 arg_end = arg;
2079 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002080 name[len] = c1;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002081 vim_free(tofree);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002082 }
2083 }
2084 }
2085
2086 /*
2087 * ":let &option = expr": Set option value.
2088 * ":let &l:option = expr": Set local option value.
2089 * ":let &g:option = expr": Set global option value.
2090 */
2091 else if (*arg == '&')
2092 {
2093 /* Find the end of the name. */
2094 p = find_option_end(&arg, &opt_flags);
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002095 if (p == NULL || (endchars != NULL
2096 && vim_strchr(endchars, *skipwhite(p)) == NULL))
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002097 EMSG(_(e_letunexp));
2098 else
2099 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002100 long n;
2101 int opt_type;
2102 long numval;
2103 char_u *stringval = NULL;
2104 char_u *s;
2105
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002106 c1 = *p;
2107 *p = NUL;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002108
2109 n = get_tv_number(tv);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00002110 s = get_tv_string_chk(tv); /* != NULL if number or string */
2111 if (s != NULL && op != NULL && *op != '=')
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002112 {
2113 opt_type = get_option_value(arg, &numval,
2114 &stringval, opt_flags);
2115 if ((opt_type == 1 && *op == '.')
2116 || (opt_type == 0 && *op != '.'))
2117 EMSG2(_(e_letwrong), op);
2118 else
2119 {
2120 if (opt_type == 1) /* number */
2121 {
2122 if (*op == '+')
2123 n = numval + n;
2124 else
2125 n = numval - n;
2126 }
2127 else if (opt_type == 0 && stringval != NULL) /* string */
2128 {
2129 s = concat_str(stringval, s);
2130 vim_free(stringval);
2131 stringval = s;
2132 }
2133 }
2134 }
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00002135 if (s != NULL)
2136 {
2137 set_option_value(arg, n, s, opt_flags);
2138 arg_end = p;
2139 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002140 *p = c1;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002141 vim_free(stringval);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002142 }
2143 }
2144
2145 /*
2146 * ":let @r = expr": Set register contents.
2147 */
2148 else if (*arg == '@')
2149 {
2150 ++arg;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002151 if (op != NULL && (*op == '+' || *op == '-'))
2152 EMSG2(_(e_letwrong), op);
2153 else if (endchars != NULL
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002154 && vim_strchr(endchars, *skipwhite(arg + 1)) == NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002155 EMSG(_(e_letunexp));
2156 else
2157 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002158 char_u *tofree = NULL;
2159 char_u *s;
2160
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00002161 p = get_tv_string_chk(tv);
2162 if (p != NULL && op != NULL && *op == '.')
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002163 {
Bram Moolenaar92124a32005-06-17 22:03:40 +00002164 s = get_reg_contents(*arg == '@' ? '"' : *arg, TRUE, TRUE);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002165 if (s != NULL)
2166 {
2167 p = tofree = concat_str(s, p);
2168 vim_free(s);
2169 }
2170 }
2171 if (p != NULL)
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00002172 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002173 write_reg_contents(*arg == '@' ? '"' : *arg, p, -1, FALSE);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00002174 arg_end = arg + 1;
2175 }
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002176 vim_free(tofree);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002177 }
2178 }
2179
2180 /*
2181 * ":let var = expr": Set internal variable.
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002182 * ":let {expr} = expr": Idem, name made with curly braces
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002183 */
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +00002184 else if (eval_isnamec1(*arg) || *arg == '{')
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002185 {
Bram Moolenaar33570922005-01-25 22:26:29 +00002186 lval_T lv;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002187
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +00002188 p = get_lval(arg, tv, &lv, FALSE, FALSE, FALSE, FNE_CHECK_START);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002189 if (p != NULL && lv.ll_name != NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002190 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002191 if (endchars != NULL && vim_strchr(endchars, *skipwhite(p)) == NULL)
2192 EMSG(_(e_letunexp));
2193 else
2194 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002195 set_var_lval(&lv, p, tv, copy, op);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002196 arg_end = p;
2197 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002198 }
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002199 clear_lval(&lv);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002200 }
2201
2202 else
2203 EMSG2(_(e_invarg2), arg);
2204
2205 return arg_end;
2206}
2207
2208/*
Bram Moolenaar8c711452005-01-14 21:53:12 +00002209 * If "arg" is equal to "b:changedtick" give an error and return TRUE.
2210 */
2211 static int
2212check_changedtick(arg)
2213 char_u *arg;
2214{
2215 if (STRNCMP(arg, "b:changedtick", 13) == 0 && !eval_isnamec(arg[13]))
2216 {
2217 EMSG2(_(e_readonlyvar), arg);
2218 return TRUE;
2219 }
2220 return FALSE;
2221}
2222
2223/*
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002224 * Get an lval: variable, Dict item or List item that can be assigned a value
2225 * to: "name", "na{me}", "name[expr]", "name[expr:expr]", "name[expr][expr]",
2226 * "name.key", "name.key[expr]" etc.
2227 * Indexing only works if "name" is an existing List or Dictionary.
2228 * "name" points to the start of the name.
2229 * If "rettv" is not NULL it points to the value to be assigned.
2230 * "unlet" is TRUE for ":unlet": slightly different behavior when something is
2231 * wrong; must end in space or cmd separator.
2232 *
2233 * Returns a pointer to just after the name, including indexes.
Bram Moolenaara7043832005-01-21 11:56:39 +00002234 * When an evaluation error occurs "lp->ll_name" is NULL;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002235 * Returns NULL for a parsing error. Still need to free items in "lp"!
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002236 */
2237 static char_u *
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +00002238get_lval(name, rettv, lp, unlet, skip, quiet, fne_flags)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002239 char_u *name;
Bram Moolenaar33570922005-01-25 22:26:29 +00002240 typval_T *rettv;
2241 lval_T *lp;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002242 int unlet;
2243 int skip;
2244 int quiet; /* don't give error messages */
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +00002245 int fne_flags; /* flags for find_name_end() */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002246{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002247 char_u *p;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002248 char_u *expr_start, *expr_end;
2249 int cc;
Bram Moolenaar33570922005-01-25 22:26:29 +00002250 dictitem_T *v;
2251 typval_T var1;
2252 typval_T var2;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002253 int empty1 = FALSE;
Bram Moolenaar33570922005-01-25 22:26:29 +00002254 listitem_T *ni;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002255 char_u *key = NULL;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002256 int len;
Bram Moolenaar33570922005-01-25 22:26:29 +00002257 hashtab_T *ht;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002258
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002259 /* Clear everything in "lp". */
Bram Moolenaar33570922005-01-25 22:26:29 +00002260 vim_memset(lp, 0, sizeof(lval_T));
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002261
2262 if (skip)
2263 {
2264 /* When skipping just find the end of the name. */
2265 lp->ll_name = name;
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +00002266 return find_name_end(name, NULL, NULL, FNE_INCL_BR | fne_flags);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002267 }
2268
2269 /* Find the end of the name. */
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +00002270 p = find_name_end(name, &expr_start, &expr_end, fne_flags);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002271 if (expr_start != NULL)
2272 {
2273 /* Don't expand the name when we already know there is an error. */
2274 if (unlet && !vim_iswhite(*p) && !ends_excmd(*p)
2275 && *p != '[' && *p != '.')
2276 {
2277 EMSG(_(e_trailing));
2278 return NULL;
2279 }
2280
2281 lp->ll_exp_name = make_expanded_name(name, expr_start, expr_end, p);
2282 if (lp->ll_exp_name == NULL)
2283 {
2284 /* Report an invalid expression in braces, unless the
2285 * expression evaluation has been cancelled due to an
2286 * aborting error, an interrupt, or an exception. */
2287 if (!aborting() && !quiet)
2288 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00002289 emsg_severe = TRUE;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002290 EMSG2(_(e_invarg2), name);
2291 return NULL;
2292 }
2293 }
2294 lp->ll_name = lp->ll_exp_name;
2295 }
2296 else
2297 lp->ll_name = name;
2298
2299 /* Without [idx] or .key we are done. */
2300 if ((*p != '[' && *p != '.') || lp->ll_name == NULL)
2301 return p;
2302
2303 cc = *p;
2304 *p = NUL;
Bram Moolenaara7043832005-01-21 11:56:39 +00002305 v = find_var(lp->ll_name, &ht);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002306 if (v == NULL && !quiet)
2307 EMSG2(_(e_undefvar), lp->ll_name);
2308 *p = cc;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002309 if (v == NULL)
2310 return NULL;
2311
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002312 /*
2313 * Loop until no more [idx] or .key is following.
2314 */
Bram Moolenaar33570922005-01-25 22:26:29 +00002315 lp->ll_tv = &v->di_tv;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002316 while (*p == '[' || (*p == '.' && lp->ll_tv->v_type == VAR_DICT))
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002317 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002318 if (!(lp->ll_tv->v_type == VAR_LIST && lp->ll_tv->vval.v_list != NULL)
2319 && !(lp->ll_tv->v_type == VAR_DICT
2320 && lp->ll_tv->vval.v_dict != NULL))
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002321 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002322 if (!quiet)
2323 EMSG(_("E689: Can only index a List or Dictionary"));
2324 return NULL;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002325 }
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002326 if (lp->ll_range)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002327 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002328 if (!quiet)
2329 EMSG(_("E708: [:] must come last"));
2330 return NULL;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002331 }
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002332
Bram Moolenaar8c711452005-01-14 21:53:12 +00002333 len = -1;
2334 if (*p == '.')
2335 {
2336 key = p + 1;
2337 for (len = 0; ASCII_ISALNUM(key[len]) || key[len] == '_'; ++len)
2338 ;
2339 if (len == 0)
2340 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002341 if (!quiet)
2342 EMSG(_(e_emptykey));
2343 return NULL;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002344 }
2345 p = key + len;
2346 }
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002347 else
2348 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00002349 /* Get the index [expr] or the first index [expr: ]. */
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002350 p = skipwhite(p + 1);
Bram Moolenaar8c711452005-01-14 21:53:12 +00002351 if (*p == ':')
2352 empty1 = TRUE;
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002353 else
2354 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00002355 empty1 = FALSE;
2356 if (eval1(&p, &var1, TRUE) == FAIL) /* recursive! */
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002357 return NULL;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00002358 if (get_tv_string_chk(&var1) == NULL)
2359 {
2360 /* not a number or string */
2361 clear_tv(&var1);
2362 return NULL;
2363 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00002364 }
2365
2366 /* Optionally get the second index [ :expr]. */
2367 if (*p == ':')
2368 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002369 if (lp->ll_tv->v_type == VAR_DICT)
Bram Moolenaar8c711452005-01-14 21:53:12 +00002370 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002371 if (!quiet)
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002372 EMSG(_(e_dictrange));
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002373 if (!empty1)
2374 clear_tv(&var1);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002375 return NULL;
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002376 }
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002377 if (rettv != NULL && (rettv->v_type != VAR_LIST
2378 || rettv->vval.v_list == NULL))
Bram Moolenaar8c711452005-01-14 21:53:12 +00002379 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002380 if (!quiet)
2381 EMSG(_("E709: [:] requires a List value"));
Bram Moolenaar8c711452005-01-14 21:53:12 +00002382 if (!empty1)
2383 clear_tv(&var1);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002384 return NULL;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002385 }
2386 p = skipwhite(p + 1);
2387 if (*p == ']')
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002388 lp->ll_empty2 = TRUE;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002389 else
2390 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002391 lp->ll_empty2 = FALSE;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002392 if (eval1(&p, &var2, TRUE) == FAIL) /* recursive! */
2393 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00002394 if (!empty1)
2395 clear_tv(&var1);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002396 return NULL;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002397 }
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00002398 if (get_tv_string_chk(&var2) == NULL)
2399 {
2400 /* not a number or string */
2401 if (!empty1)
2402 clear_tv(&var1);
2403 clear_tv(&var2);
2404 return NULL;
2405 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00002406 }
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002407 lp->ll_range = TRUE;
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002408 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00002409 else
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002410 lp->ll_range = FALSE;
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002411
Bram Moolenaar8c711452005-01-14 21:53:12 +00002412 if (*p != ']')
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002413 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002414 if (!quiet)
2415 EMSG(_(e_missbrac));
Bram Moolenaar8c711452005-01-14 21:53:12 +00002416 if (!empty1)
2417 clear_tv(&var1);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002418 if (lp->ll_range && !lp->ll_empty2)
Bram Moolenaar8c711452005-01-14 21:53:12 +00002419 clear_tv(&var2);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002420 return NULL;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002421 }
2422
2423 /* Skip to past ']'. */
2424 ++p;
2425 }
2426
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002427 if (lp->ll_tv->v_type == VAR_DICT)
Bram Moolenaar8c711452005-01-14 21:53:12 +00002428 {
2429 if (len == -1)
2430 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002431 /* "[key]": get key from "var1" */
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00002432 key = get_tv_string(&var1); /* is number or string */
Bram Moolenaar8c711452005-01-14 21:53:12 +00002433 if (*key == NUL)
2434 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002435 if (!quiet)
2436 EMSG(_(e_emptykey));
Bram Moolenaar8c711452005-01-14 21:53:12 +00002437 clear_tv(&var1);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002438 return NULL;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002439 }
2440 }
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002441 lp->ll_list = NULL;
2442 lp->ll_dict = lp->ll_tv->vval.v_dict;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00002443 lp->ll_di = dict_find(lp->ll_dict, key, len);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002444 if (lp->ll_di == NULL)
Bram Moolenaar8c711452005-01-14 21:53:12 +00002445 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00002446 /* Key does not exist in dict: may need to add it. */
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002447 if (*p == '[' || *p == '.' || unlet)
Bram Moolenaar8c711452005-01-14 21:53:12 +00002448 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002449 if (!quiet)
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002450 EMSG2(_(e_dictkey), key);
Bram Moolenaar8c711452005-01-14 21:53:12 +00002451 if (len == -1)
2452 clear_tv(&var1);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002453 return NULL;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002454 }
2455 if (len == -1)
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002456 lp->ll_newkey = vim_strsave(key);
Bram Moolenaar8c711452005-01-14 21:53:12 +00002457 else
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002458 lp->ll_newkey = vim_strnsave(key, len);
Bram Moolenaar8c711452005-01-14 21:53:12 +00002459 if (len == -1)
2460 clear_tv(&var1);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002461 if (lp->ll_newkey == NULL)
Bram Moolenaar8c711452005-01-14 21:53:12 +00002462 p = NULL;
2463 break;
2464 }
2465 if (len == -1)
2466 clear_tv(&var1);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002467 lp->ll_tv = &lp->ll_di->di_tv;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002468 }
2469 else
2470 {
2471 /*
2472 * Get the number and item for the only or first index of the List.
2473 */
2474 if (empty1)
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002475 lp->ll_n1 = 0;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002476 else
2477 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00002478 lp->ll_n1 = get_tv_number(&var1); /* is number or string */
Bram Moolenaar8c711452005-01-14 21:53:12 +00002479 clear_tv(&var1);
2480 }
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002481 lp->ll_dict = NULL;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002482 lp->ll_list = lp->ll_tv->vval.v_list;
2483 lp->ll_li = list_find(lp->ll_list, lp->ll_n1);
2484 if (lp->ll_li == NULL)
Bram Moolenaar8c711452005-01-14 21:53:12 +00002485 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002486 if (!quiet)
2487 EMSGN(_(e_listidx), lp->ll_n1);
2488 if (lp->ll_range && !lp->ll_empty2)
Bram Moolenaar8c711452005-01-14 21:53:12 +00002489 clear_tv(&var2);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002490 return NULL;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002491 }
2492
2493 /*
2494 * May need to find the item or absolute index for the second
2495 * index of a range.
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002496 * When no index given: "lp->ll_empty2" is TRUE.
2497 * Otherwise "lp->ll_n2" is set to the second index.
Bram Moolenaar8c711452005-01-14 21:53:12 +00002498 */
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002499 if (lp->ll_range && !lp->ll_empty2)
Bram Moolenaar8c711452005-01-14 21:53:12 +00002500 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00002501 lp->ll_n2 = get_tv_number(&var2); /* is number or string */
Bram Moolenaar8c711452005-01-14 21:53:12 +00002502 clear_tv(&var2);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002503 if (lp->ll_n2 < 0)
Bram Moolenaar8c711452005-01-14 21:53:12 +00002504 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002505 ni = list_find(lp->ll_list, lp->ll_n2);
Bram Moolenaar8c711452005-01-14 21:53:12 +00002506 if (ni == NULL)
2507 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002508 if (!quiet)
2509 EMSGN(_(e_listidx), lp->ll_n2);
2510 return NULL;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002511 }
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002512 lp->ll_n2 = list_idx_of_item(lp->ll_list, ni);
Bram Moolenaar8c711452005-01-14 21:53:12 +00002513 }
2514
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002515 /* Check that lp->ll_n2 isn't before lp->ll_n1. */
2516 if (lp->ll_n1 < 0)
2517 lp->ll_n1 = list_idx_of_item(lp->ll_list, lp->ll_li);
2518 if (lp->ll_n2 < lp->ll_n1)
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002519 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002520 if (!quiet)
2521 EMSGN(_(e_listidx), lp->ll_n2);
2522 return NULL;
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002523 }
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002524 }
2525
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002526 lp->ll_tv = &lp->ll_li->li_tv;
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002527 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002528 }
2529
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002530 return p;
2531}
2532
2533/*
Bram Moolenaar33570922005-01-25 22:26:29 +00002534 * Clear lval "lp" that was filled by get_lval().
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002535 */
2536 static void
2537clear_lval(lp)
Bram Moolenaar33570922005-01-25 22:26:29 +00002538 lval_T *lp;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002539{
2540 vim_free(lp->ll_exp_name);
2541 vim_free(lp->ll_newkey);
2542}
2543
2544/*
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00002545 * Set a variable that was parsed by get_lval() to "rettv".
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002546 * "endp" points to just after the parsed name.
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002547 * "op" is NULL, "+" for "+=", "-" for "-=", "." for ".=" or "=" for "=".
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002548 */
2549 static void
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002550set_var_lval(lp, endp, rettv, copy, op)
Bram Moolenaar33570922005-01-25 22:26:29 +00002551 lval_T *lp;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002552 char_u *endp;
Bram Moolenaar33570922005-01-25 22:26:29 +00002553 typval_T *rettv;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002554 int copy;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002555 char_u *op;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002556{
2557 int cc;
Bram Moolenaar33570922005-01-25 22:26:29 +00002558 listitem_T *ri;
2559 dictitem_T *di;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002560
2561 if (lp->ll_tv == NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002562 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002563 if (!check_changedtick(lp->ll_name))
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002564 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002565 cc = *endp;
2566 *endp = NUL;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002567 if (op != NULL && *op != '=')
2568 {
Bram Moolenaar33570922005-01-25 22:26:29 +00002569 typval_T tv;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002570
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00002571 /* handle +=, -= and .= */
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00002572 if (get_var_tv(lp->ll_name, STRLEN(lp->ll_name),
2573 &tv, TRUE) == OK)
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002574 {
2575 if (tv_op(&tv, rettv, op) == OK)
2576 set_var(lp->ll_name, &tv, FALSE);
2577 clear_tv(&tv);
2578 }
2579 }
2580 else
2581 set_var(lp->ll_name, rettv, copy);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002582 *endp = cc;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002583 }
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002584 }
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00002585 else if (tv_check_lock(lp->ll_newkey == NULL
2586 ? lp->ll_tv->v_lock
2587 : lp->ll_tv->vval.v_dict->dv_lock, lp->ll_name))
2588 ;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002589 else if (lp->ll_range)
2590 {
2591 /*
2592 * Assign the List values to the list items.
2593 */
2594 for (ri = rettv->vval.v_list->lv_first; ri != NULL; )
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002595 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002596 if (op != NULL && *op != '=')
2597 tv_op(&lp->ll_li->li_tv, &ri->li_tv, op);
2598 else
2599 {
2600 clear_tv(&lp->ll_li->li_tv);
2601 copy_tv(&ri->li_tv, &lp->ll_li->li_tv);
2602 }
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002603 ri = ri->li_next;
2604 if (ri == NULL || (!lp->ll_empty2 && lp->ll_n2 == lp->ll_n1))
2605 break;
2606 if (lp->ll_li->li_next == NULL)
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002607 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002608 /* Need to add an empty item. */
Bram Moolenaar4463f292005-09-25 22:20:24 +00002609 if (list_append_number(lp->ll_list, 0) == FAIL)
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002610 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002611 ri = NULL;
2612 break;
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002613 }
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002614 }
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002615 lp->ll_li = lp->ll_li->li_next;
2616 ++lp->ll_n1;
2617 }
2618 if (ri != NULL)
2619 EMSG(_("E710: List value has more items than target"));
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002620 else if (lp->ll_empty2
2621 ? (lp->ll_li != NULL && lp->ll_li->li_next != NULL)
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002622 : lp->ll_n1 != lp->ll_n2)
2623 EMSG(_("E711: List value has not enough items"));
2624 }
2625 else
2626 {
2627 /*
2628 * Assign to a List or Dictionary item.
2629 */
2630 if (lp->ll_newkey != NULL)
2631 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002632 if (op != NULL && *op != '=')
2633 {
2634 EMSG2(_(e_letwrong), op);
2635 return;
2636 }
2637
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002638 /* Need to add an item to the Dictionary. */
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00002639 di = dictitem_alloc(lp->ll_newkey);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002640 if (di == NULL)
2641 return;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00002642 if (dict_add(lp->ll_tv->vval.v_dict, di) == FAIL)
2643 {
2644 vim_free(di);
2645 return;
2646 }
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002647 lp->ll_tv = &di->di_tv;
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002648 }
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002649 else if (op != NULL && *op != '=')
2650 {
2651 tv_op(lp->ll_tv, rettv, op);
2652 return;
2653 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002654 else
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002655 clear_tv(lp->ll_tv);
Bram Moolenaar8c711452005-01-14 21:53:12 +00002656
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002657 /*
2658 * Assign the value to the variable or list item.
2659 */
2660 if (copy)
2661 copy_tv(rettv, lp->ll_tv);
2662 else
2663 {
2664 *lp->ll_tv = *rettv;
Bram Moolenaar758711c2005-02-02 23:11:38 +00002665 lp->ll_tv->v_lock = 0;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002666 init_tv(rettv);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002667 }
2668 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002669}
2670
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002671/*
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002672 * Handle "tv1 += tv2", "tv1 -= tv2" and "tv1 .= tv2"
2673 * Returns OK or FAIL.
2674 */
2675 static int
2676tv_op(tv1, tv2, op)
Bram Moolenaar33570922005-01-25 22:26:29 +00002677 typval_T *tv1;
2678 typval_T *tv2;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002679 char_u *op;
2680{
2681 long n;
2682 char_u numbuf[NUMBUFLEN];
2683 char_u *s;
2684
2685 /* Can't do anything with a Funcref or a Dict on the right. */
2686 if (tv2->v_type != VAR_FUNC && tv2->v_type != VAR_DICT)
2687 {
2688 switch (tv1->v_type)
2689 {
2690 case VAR_DICT:
2691 case VAR_FUNC:
2692 break;
2693
2694 case VAR_LIST:
2695 if (*op != '+' || tv2->v_type != VAR_LIST)
2696 break;
2697 /* List += List */
2698 if (tv1->vval.v_list != NULL && tv2->vval.v_list != NULL)
2699 list_extend(tv1->vval.v_list, tv2->vval.v_list, NULL);
2700 return OK;
2701
2702 case VAR_NUMBER:
2703 case VAR_STRING:
2704 if (tv2->v_type == VAR_LIST)
2705 break;
2706 if (*op == '+' || *op == '-')
2707 {
2708 /* nr += nr or nr -= nr*/
2709 n = get_tv_number(tv1);
2710 if (*op == '+')
2711 n += get_tv_number(tv2);
2712 else
2713 n -= get_tv_number(tv2);
2714 clear_tv(tv1);
2715 tv1->v_type = VAR_NUMBER;
2716 tv1->vval.v_number = n;
2717 }
2718 else
2719 {
2720 /* str .= str */
2721 s = get_tv_string(tv1);
2722 s = concat_str(s, get_tv_string_buf(tv2, numbuf));
2723 clear_tv(tv1);
2724 tv1->v_type = VAR_STRING;
2725 tv1->vval.v_string = s;
2726 }
2727 return OK;
2728 }
2729 }
2730
2731 EMSG2(_(e_letwrong), op);
2732 return FAIL;
2733}
2734
2735/*
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002736 * Add a watcher to a list.
2737 */
2738 static void
2739list_add_watch(l, lw)
Bram Moolenaar33570922005-01-25 22:26:29 +00002740 list_T *l;
2741 listwatch_T *lw;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002742{
2743 lw->lw_next = l->lv_watch;
2744 l->lv_watch = lw;
2745}
2746
2747/*
Bram Moolenaar758711c2005-02-02 23:11:38 +00002748 * Remove a watcher from a list.
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002749 * No warning when it isn't found...
2750 */
2751 static void
2752list_rem_watch(l, lwrem)
Bram Moolenaar33570922005-01-25 22:26:29 +00002753 list_T *l;
2754 listwatch_T *lwrem;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002755{
Bram Moolenaar33570922005-01-25 22:26:29 +00002756 listwatch_T *lw, **lwp;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002757
2758 lwp = &l->lv_watch;
2759 for (lw = l->lv_watch; lw != NULL; lw = lw->lw_next)
2760 {
2761 if (lw == lwrem)
2762 {
2763 *lwp = lw->lw_next;
2764 break;
2765 }
2766 lwp = &lw->lw_next;
2767 }
2768}
2769
2770/*
2771 * Just before removing an item from a list: advance watchers to the next
2772 * item.
2773 */
2774 static void
2775list_fix_watch(l, item)
Bram Moolenaar33570922005-01-25 22:26:29 +00002776 list_T *l;
2777 listitem_T *item;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002778{
Bram Moolenaar33570922005-01-25 22:26:29 +00002779 listwatch_T *lw;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002780
2781 for (lw = l->lv_watch; lw != NULL; lw = lw->lw_next)
2782 if (lw->lw_item == item)
2783 lw->lw_item = item->li_next;
2784}
2785
2786/*
2787 * Evaluate the expression used in a ":for var in expr" command.
2788 * "arg" points to "var".
2789 * Set "*errp" to TRUE for an error, FALSE otherwise;
2790 * Return a pointer that holds the info. Null when there is an error.
2791 */
2792 void *
2793eval_for_line(arg, errp, nextcmdp, skip)
2794 char_u *arg;
2795 int *errp;
2796 char_u **nextcmdp;
2797 int skip;
2798{
Bram Moolenaar33570922005-01-25 22:26:29 +00002799 forinfo_T *fi;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002800 char_u *expr;
Bram Moolenaar33570922005-01-25 22:26:29 +00002801 typval_T tv;
2802 list_T *l;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002803
2804 *errp = TRUE; /* default: there is an error */
2805
Bram Moolenaar33570922005-01-25 22:26:29 +00002806 fi = (forinfo_T *)alloc_clear(sizeof(forinfo_T));
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002807 if (fi == NULL)
2808 return NULL;
2809
2810 expr = skip_var_list(arg, &fi->fi_varcount, &fi->fi_semicolon);
2811 if (expr == NULL)
2812 return fi;
2813
2814 expr = skipwhite(expr);
2815 if (expr[0] != 'i' || expr[1] != 'n' || !vim_iswhite(expr[2]))
2816 {
Bram Moolenaare49b69a2005-01-08 16:11:57 +00002817 EMSG(_("E690: Missing \"in\" after :for"));
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002818 return fi;
2819 }
2820
2821 if (skip)
2822 ++emsg_skip;
2823 if (eval0(skipwhite(expr + 2), &tv, nextcmdp, !skip) == OK)
2824 {
2825 *errp = FALSE;
2826 if (!skip)
2827 {
2828 l = tv.vval.v_list;
2829 if (tv.v_type != VAR_LIST || l == NULL)
Bram Moolenaarf461c8e2005-06-25 23:04:51 +00002830 {
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002831 EMSG(_(e_listreq));
Bram Moolenaarf461c8e2005-06-25 23:04:51 +00002832 clear_tv(&tv);
2833 }
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002834 else
2835 {
Bram Moolenaar7bb4c6e2005-09-07 21:22:27 +00002836 /* No need to increment the refcount, it's already set for the
2837 * list being used in "tv". */
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002838 fi->fi_list = l;
2839 list_add_watch(l, &fi->fi_lw);
2840 fi->fi_lw.lw_item = l->lv_first;
2841 }
2842 }
2843 }
2844 if (skip)
2845 --emsg_skip;
2846
2847 return fi;
2848}
2849
2850/*
2851 * Use the first item in a ":for" list. Advance to the next.
2852 * Assign the values to the variable (list). "arg" points to the first one.
2853 * Return TRUE when a valid item was found, FALSE when at end of list or
2854 * something wrong.
2855 */
2856 int
2857next_for_item(fi_void, arg)
2858 void *fi_void;
2859 char_u *arg;
2860{
Bram Moolenaar33570922005-01-25 22:26:29 +00002861 forinfo_T *fi = (forinfo_T *)fi_void;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002862 int result;
Bram Moolenaar33570922005-01-25 22:26:29 +00002863 listitem_T *item;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002864
2865 item = fi->fi_lw.lw_item;
2866 if (item == NULL)
2867 result = FALSE;
2868 else
2869 {
2870 fi->fi_lw.lw_item = item->li_next;
2871 result = (ex_let_vars(arg, &item->li_tv, TRUE,
2872 fi->fi_semicolon, fi->fi_varcount, NULL) == OK);
2873 }
2874 return result;
2875}
2876
2877/*
2878 * Free the structure used to store info used by ":for".
2879 */
2880 void
2881free_for_info(fi_void)
2882 void *fi_void;
2883{
Bram Moolenaar33570922005-01-25 22:26:29 +00002884 forinfo_T *fi = (forinfo_T *)fi_void;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002885
Bram Moolenaarab7013c2005-01-09 21:23:56 +00002886 if (fi != NULL && fi->fi_list != NULL)
Bram Moolenaarf461c8e2005-06-25 23:04:51 +00002887 {
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002888 list_rem_watch(fi->fi_list, &fi->fi_lw);
Bram Moolenaarf461c8e2005-06-25 23:04:51 +00002889 list_unref(fi->fi_list);
2890 }
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002891 vim_free(fi);
2892}
2893
Bram Moolenaar071d4272004-06-13 20:20:40 +00002894#if defined(FEAT_CMDL_COMPL) || defined(PROTO)
2895
2896 void
2897set_context_for_expression(xp, arg, cmdidx)
2898 expand_T *xp;
2899 char_u *arg;
2900 cmdidx_T cmdidx;
2901{
2902 int got_eq = FALSE;
2903 int c;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002904 char_u *p;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002905
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002906 if (cmdidx == CMD_let)
2907 {
2908 xp->xp_context = EXPAND_USER_VARS;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00002909 if (vim_strpbrk(arg, (char_u *)"\"'+-*/%.=!?~|&$([<>,#") == NULL)
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002910 {
2911 /* ":let var1 var2 ...": find last space. */
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00002912 for (p = arg + STRLEN(arg); p >= arg; )
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002913 {
2914 xp->xp_pattern = p;
Bram Moolenaar33570922005-01-25 22:26:29 +00002915 mb_ptr_back(arg, p);
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002916 if (vim_iswhite(*p))
2917 break;
2918 }
2919 return;
2920 }
2921 }
2922 else
2923 xp->xp_context = cmdidx == CMD_call ? EXPAND_FUNCTIONS
2924 : EXPAND_EXPRESSION;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002925 while ((xp->xp_pattern = vim_strpbrk(arg,
2926 (char_u *)"\"'+-*/%.=!?~|&$([<>,#")) != NULL)
2927 {
2928 c = *xp->xp_pattern;
2929 if (c == '&')
2930 {
2931 c = xp->xp_pattern[1];
2932 if (c == '&')
2933 {
2934 ++xp->xp_pattern;
2935 xp->xp_context = cmdidx != CMD_let || got_eq
2936 ? EXPAND_EXPRESSION : EXPAND_NOTHING;
2937 }
2938 else if (c != ' ')
Bram Moolenaar11cbeb12005-03-11 22:51:16 +00002939 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00002940 xp->xp_context = EXPAND_SETTINGS;
Bram Moolenaar11cbeb12005-03-11 22:51:16 +00002941 if ((c == 'l' || c == 'g') && xp->xp_pattern[2] == ':')
2942 xp->xp_pattern += 2;
2943
2944 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00002945 }
2946 else if (c == '$')
2947 {
2948 /* environment variable */
2949 xp->xp_context = EXPAND_ENV_VARS;
2950 }
2951 else if (c == '=')
2952 {
2953 got_eq = TRUE;
2954 xp->xp_context = EXPAND_EXPRESSION;
2955 }
2956 else if (c == '<'
2957 && xp->xp_context == EXPAND_FUNCTIONS
2958 && vim_strchr(xp->xp_pattern, '(') == NULL)
2959 {
2960 /* Function name can start with "<SNR>" */
2961 break;
2962 }
2963 else if (cmdidx != CMD_let || got_eq)
2964 {
2965 if (c == '"') /* string */
2966 {
2967 while ((c = *++xp->xp_pattern) != NUL && c != '"')
2968 if (c == '\\' && xp->xp_pattern[1] != NUL)
2969 ++xp->xp_pattern;
2970 xp->xp_context = EXPAND_NOTHING;
2971 }
2972 else if (c == '\'') /* literal string */
2973 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00002974 /* Trick: '' is like stopping and starting a literal string. */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002975 while ((c = *++xp->xp_pattern) != NUL && c != '\'')
2976 /* skip */ ;
2977 xp->xp_context = EXPAND_NOTHING;
2978 }
2979 else if (c == '|')
2980 {
2981 if (xp->xp_pattern[1] == '|')
2982 {
2983 ++xp->xp_pattern;
2984 xp->xp_context = EXPAND_EXPRESSION;
2985 }
2986 else
2987 xp->xp_context = EXPAND_COMMANDS;
2988 }
2989 else
2990 xp->xp_context = EXPAND_EXPRESSION;
2991 }
2992 else
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002993 /* Doesn't look like something valid, expand as an expression
2994 * anyway. */
2995 xp->xp_context = EXPAND_EXPRESSION;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002996 arg = xp->xp_pattern;
2997 if (*arg != NUL)
2998 while ((c = *++arg) != NUL && (c == ' ' || c == '\t'))
2999 /* skip */ ;
3000 }
3001 xp->xp_pattern = arg;
3002}
3003
3004#endif /* FEAT_CMDL_COMPL */
3005
3006/*
3007 * ":1,25call func(arg1, arg2)" function call.
3008 */
3009 void
3010ex_call(eap)
3011 exarg_T *eap;
3012{
3013 char_u *arg = eap->arg;
3014 char_u *startarg;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003015 char_u *name;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00003016 char_u *tofree;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003017 int len;
Bram Moolenaar33570922005-01-25 22:26:29 +00003018 typval_T rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003019 linenr_T lnum;
3020 int doesrange;
3021 int failed = FALSE;
Bram Moolenaar33570922005-01-25 22:26:29 +00003022 funcdict_T fudi;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003023
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00003024 tofree = trans_function_name(&arg, eap->skip, TFN_INT, &fudi);
3025 vim_free(fudi.fd_newkey);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00003026 if (tofree == NULL)
3027 return;
3028
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00003029 /* Increase refcount on dictionary, it could get deleted when evaluating
3030 * the arguments. */
3031 if (fudi.fd_dict != NULL)
3032 ++fudi.fd_dict->dv_refcount;
3033
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00003034 /* If it is the name of a variable of type VAR_FUNC use its contents. */
3035 len = STRLEN(tofree);
3036 name = deref_func_name(tofree, &len);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003037
Bram Moolenaar532c7802005-01-27 14:44:31 +00003038 /* Skip white space to allow ":call func ()". Not good, but required for
3039 * backward compatibility. */
3040 startarg = skipwhite(arg);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003041 rettv.v_type = VAR_UNKNOWN; /* clear_tv() uses this */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003042
3043 if (*startarg != '(')
3044 {
Bram Moolenaar81bf7082005-02-12 14:31:42 +00003045 EMSG2(_("E107: Missing braces: %s"), eap->arg);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003046 goto end;
3047 }
3048
3049 /*
3050 * When skipping, evaluate the function once, to find the end of the
3051 * arguments.
3052 * When the function takes a range, this is discovered after the first
3053 * call, and the loop is broken.
3054 */
3055 if (eap->skip)
3056 {
3057 ++emsg_skip;
3058 lnum = eap->line2; /* do it once, also with an invalid range */
3059 }
3060 else
3061 lnum = eap->line1;
3062 for ( ; lnum <= eap->line2; ++lnum)
3063 {
3064 if (!eap->skip && eap->addr_count > 0)
3065 {
3066 curwin->w_cursor.lnum = lnum;
3067 curwin->w_cursor.col = 0;
3068 }
3069 arg = startarg;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00003070 if (get_func_tv(name, STRLEN(name), &rettv, &arg,
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00003071 eap->line1, eap->line2, &doesrange,
3072 !eap->skip, fudi.fd_dict) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003073 {
3074 failed = TRUE;
3075 break;
3076 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003077 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003078 if (doesrange || eap->skip)
3079 break;
3080 /* Stop when immediately aborting on error, or when an interrupt
Bram Moolenaar49cd9572005-01-03 21:06:01 +00003081 * occurred or an exception was thrown but not caught.
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003082 * get_func_tv() returned OK, so that the check for trailing
Bram Moolenaar49cd9572005-01-03 21:06:01 +00003083 * characters below is executed. */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003084 if (aborting())
3085 break;
3086 }
3087 if (eap->skip)
3088 --emsg_skip;
3089
3090 if (!failed)
3091 {
3092 /* Check for trailing illegal characters and a following command. */
3093 if (!ends_excmd(*arg))
3094 {
3095 emsg_severe = TRUE;
3096 EMSG(_(e_trailing));
3097 }
3098 else
3099 eap->nextcmd = check_nextcmd(arg);
3100 }
3101
3102end:
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00003103 dict_unref(fudi.fd_dict);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00003104 vim_free(tofree);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003105}
3106
3107/*
3108 * ":unlet[!] var1 ... " command.
3109 */
3110 void
3111ex_unlet(eap)
3112 exarg_T *eap;
3113{
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00003114 ex_unletlock(eap, eap->arg, 0);
3115}
3116
3117/*
3118 * ":lockvar" and ":unlockvar" commands
3119 */
3120 void
3121ex_lockvar(eap)
3122 exarg_T *eap;
3123{
Bram Moolenaar071d4272004-06-13 20:20:40 +00003124 char_u *arg = eap->arg;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00003125 int deep = 2;
3126
3127 if (eap->forceit)
3128 deep = -1;
3129 else if (vim_isdigit(*arg))
3130 {
3131 deep = getdigits(&arg);
3132 arg = skipwhite(arg);
3133 }
3134
3135 ex_unletlock(eap, arg, deep);
3136}
3137
3138/*
3139 * ":unlet", ":lockvar" and ":unlockvar" are quite similar.
3140 */
3141 static void
3142ex_unletlock(eap, argstart, deep)
3143 exarg_T *eap;
3144 char_u *argstart;
3145 int deep;
3146{
3147 char_u *arg = argstart;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003148 char_u *name_end;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003149 int error = FALSE;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00003150 lval_T lv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003151
3152 do
3153 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00003154 /* Parse the name and find the end. */
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +00003155 name_end = get_lval(arg, NULL, &lv, TRUE, eap->skip || error, FALSE,
3156 FNE_CHECK_START);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00003157 if (lv.ll_name == NULL)
3158 error = TRUE; /* error but continue parsing */
3159 if (name_end == NULL || (!vim_iswhite(*name_end)
3160 && !ends_excmd(*name_end)))
Bram Moolenaar071d4272004-06-13 20:20:40 +00003161 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00003162 if (name_end != NULL)
3163 {
3164 emsg_severe = TRUE;
3165 EMSG(_(e_trailing));
3166 }
3167 if (!(eap->skip || error))
3168 clear_lval(&lv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003169 break;
3170 }
3171
3172 if (!error && !eap->skip)
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00003173 {
3174 if (eap->cmdidx == CMD_unlet)
3175 {
3176 if (do_unlet_var(&lv, name_end, eap->forceit) == FAIL)
3177 error = TRUE;
3178 }
3179 else
3180 {
3181 if (do_lock_var(&lv, name_end, deep,
3182 eap->cmdidx == CMD_lockvar) == FAIL)
3183 error = TRUE;
3184 }
3185 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00003186
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00003187 if (!eap->skip)
3188 clear_lval(&lv);
3189
Bram Moolenaar071d4272004-06-13 20:20:40 +00003190 arg = skipwhite(name_end);
3191 } while (!ends_excmd(*arg));
3192
3193 eap->nextcmd = check_nextcmd(arg);
3194}
3195
Bram Moolenaar8c711452005-01-14 21:53:12 +00003196 static int
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00003197do_unlet_var(lp, name_end, forceit)
Bram Moolenaar33570922005-01-25 22:26:29 +00003198 lval_T *lp;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00003199 char_u *name_end;
Bram Moolenaar8c711452005-01-14 21:53:12 +00003200 int forceit;
3201{
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00003202 int ret = OK;
3203 int cc;
3204
3205 if (lp->ll_tv == NULL)
Bram Moolenaar8c711452005-01-14 21:53:12 +00003206 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00003207 cc = *name_end;
3208 *name_end = NUL;
3209
3210 /* Normal name or expanded name. */
3211 if (check_changedtick(lp->ll_name))
3212 ret = FAIL;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00003213 else if (do_unlet(lp->ll_name, forceit) == FAIL)
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00003214 ret = FAIL;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00003215 *name_end = cc;
Bram Moolenaar8c711452005-01-14 21:53:12 +00003216 }
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00003217 else if (tv_check_lock(lp->ll_tv->v_lock, lp->ll_name))
3218 return FAIL;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00003219 else if (lp->ll_range)
3220 {
Bram Moolenaar33570922005-01-25 22:26:29 +00003221 listitem_T *li;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00003222
3223 /* Delete a range of List items. */
3224 while (lp->ll_li != NULL && (lp->ll_empty2 || lp->ll_n2 >= lp->ll_n1))
3225 {
3226 li = lp->ll_li->li_next;
3227 listitem_remove(lp->ll_list, lp->ll_li);
3228 lp->ll_li = li;
3229 ++lp->ll_n1;
3230 }
3231 }
3232 else
3233 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00003234 if (lp->ll_list != NULL)
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00003235 /* unlet a List item. */
3236 listitem_remove(lp->ll_list, lp->ll_li);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00003237 else
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00003238 /* unlet a Dictionary item. */
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00003239 dictitem_remove(lp->ll_dict, lp->ll_di);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00003240 }
3241
3242 return ret;
Bram Moolenaar8c711452005-01-14 21:53:12 +00003243}
3244
Bram Moolenaar071d4272004-06-13 20:20:40 +00003245/*
3246 * "unlet" a variable. Return OK if it existed, FAIL if not.
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00003247 * When "forceit" is TRUE don't complain if the variable doesn't exist.
Bram Moolenaar071d4272004-06-13 20:20:40 +00003248 */
3249 int
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00003250do_unlet(name, forceit)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003251 char_u *name;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00003252 int forceit;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003253{
Bram Moolenaar33570922005-01-25 22:26:29 +00003254 hashtab_T *ht;
3255 hashitem_T *hi;
Bram Moolenaara7043832005-01-21 11:56:39 +00003256 char_u *varname;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003257
Bram Moolenaar33570922005-01-25 22:26:29 +00003258 ht = find_var_ht(name, &varname);
3259 if (ht != NULL && *varname != NUL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003260 {
Bram Moolenaar33570922005-01-25 22:26:29 +00003261 hi = hash_find(ht, varname);
3262 if (!HASHITEM_EMPTY(hi))
Bram Moolenaara7043832005-01-21 11:56:39 +00003263 {
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00003264 if (var_check_ro(HI2DI(hi)->di_flags, name))
3265 return FAIL;
3266 delete_var(ht, hi);
3267 return OK;
Bram Moolenaara7043832005-01-21 11:56:39 +00003268 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00003269 }
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00003270 if (forceit)
3271 return OK;
3272 EMSG2(_("E108: No such variable: \"%s\""), name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003273 return FAIL;
3274}
3275
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00003276/*
3277 * Lock or unlock variable indicated by "lp".
3278 * "deep" is the levels to go (-1 for unlimited);
3279 * "lock" is TRUE for ":lockvar", FALSE for ":unlockvar".
3280 */
3281 static int
3282do_lock_var(lp, name_end, deep, lock)
3283 lval_T *lp;
3284 char_u *name_end;
3285 int deep;
3286 int lock;
3287{
3288 int ret = OK;
3289 int cc;
3290 dictitem_T *di;
3291
3292 if (deep == 0) /* nothing to do */
3293 return OK;
3294
3295 if (lp->ll_tv == NULL)
3296 {
3297 cc = *name_end;
3298 *name_end = NUL;
3299
3300 /* Normal name or expanded name. */
3301 if (check_changedtick(lp->ll_name))
3302 ret = FAIL;
3303 else
3304 {
3305 di = find_var(lp->ll_name, NULL);
3306 if (di == NULL)
3307 ret = FAIL;
3308 else
3309 {
3310 if (lock)
3311 di->di_flags |= DI_FLAGS_LOCK;
3312 else
3313 di->di_flags &= ~DI_FLAGS_LOCK;
3314 item_lock(&di->di_tv, deep, lock);
3315 }
3316 }
3317 *name_end = cc;
3318 }
3319 else if (lp->ll_range)
3320 {
3321 listitem_T *li = lp->ll_li;
3322
3323 /* (un)lock a range of List items. */
3324 while (li != NULL && (lp->ll_empty2 || lp->ll_n2 >= lp->ll_n1))
3325 {
3326 item_lock(&li->li_tv, deep, lock);
3327 li = li->li_next;
3328 ++lp->ll_n1;
3329 }
3330 }
3331 else if (lp->ll_list != NULL)
3332 /* (un)lock a List item. */
3333 item_lock(&lp->ll_li->li_tv, deep, lock);
3334 else
3335 /* un(lock) a Dictionary item. */
3336 item_lock(&lp->ll_di->di_tv, deep, lock);
3337
3338 return ret;
3339}
3340
3341/*
3342 * Lock or unlock an item. "deep" is nr of levels to go.
3343 */
3344 static void
3345item_lock(tv, deep, lock)
3346 typval_T *tv;
3347 int deep;
3348 int lock;
3349{
3350 static int recurse = 0;
3351 list_T *l;
3352 listitem_T *li;
3353 dict_T *d;
3354 hashitem_T *hi;
3355 int todo;
3356
3357 if (recurse >= DICT_MAXNEST)
3358 {
3359 EMSG(_("E743: variable nested too deep for (un)lock"));
3360 return;
3361 }
3362 if (deep == 0)
3363 return;
3364 ++recurse;
3365
3366 /* lock/unlock the item itself */
3367 if (lock)
3368 tv->v_lock |= VAR_LOCKED;
3369 else
3370 tv->v_lock &= ~VAR_LOCKED;
3371
3372 switch (tv->v_type)
3373 {
3374 case VAR_LIST:
3375 if ((l = tv->vval.v_list) != NULL)
3376 {
3377 if (lock)
3378 l->lv_lock |= VAR_LOCKED;
3379 else
3380 l->lv_lock &= ~VAR_LOCKED;
3381 if (deep < 0 || deep > 1)
3382 /* recursive: lock/unlock the items the List contains */
3383 for (li = l->lv_first; li != NULL; li = li->li_next)
3384 item_lock(&li->li_tv, deep - 1, lock);
3385 }
3386 break;
3387 case VAR_DICT:
3388 if ((d = tv->vval.v_dict) != NULL)
3389 {
3390 if (lock)
3391 d->dv_lock |= VAR_LOCKED;
3392 else
3393 d->dv_lock &= ~VAR_LOCKED;
3394 if (deep < 0 || deep > 1)
3395 {
3396 /* recursive: lock/unlock the items the List contains */
3397 todo = d->dv_hashtab.ht_used;
3398 for (hi = d->dv_hashtab.ht_array; todo > 0; ++hi)
3399 {
3400 if (!HASHITEM_EMPTY(hi))
3401 {
3402 --todo;
3403 item_lock(&HI2DI(hi)->di_tv, deep - 1, lock);
3404 }
3405 }
3406 }
3407 }
3408 }
3409 --recurse;
3410}
3411
Bram Moolenaara40058a2005-07-11 22:42:07 +00003412/*
3413 * Return TRUE if typeval "tv" is locked: Either tha value is locked itself or
3414 * it refers to a List or Dictionary that is locked.
3415 */
3416 static int
3417tv_islocked(tv)
3418 typval_T *tv;
3419{
3420 return (tv->v_lock & VAR_LOCKED)
3421 || (tv->v_type == VAR_LIST
3422 && tv->vval.v_list != NULL
3423 && (tv->vval.v_list->lv_lock & VAR_LOCKED))
3424 || (tv->v_type == VAR_DICT
3425 && tv->vval.v_dict != NULL
3426 && (tv->vval.v_dict->dv_lock & VAR_LOCKED));
3427}
3428
Bram Moolenaar071d4272004-06-13 20:20:40 +00003429#if (defined(FEAT_MENU) && defined(FEAT_MULTI_LANG)) || defined(PROTO)
3430/*
3431 * Delete all "menutrans_" variables.
3432 */
3433 void
3434del_menutrans_vars()
3435{
Bram Moolenaar33570922005-01-25 22:26:29 +00003436 hashitem_T *hi;
Bram Moolenaara7043832005-01-21 11:56:39 +00003437 int todo;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003438
Bram Moolenaar33570922005-01-25 22:26:29 +00003439 hash_lock(&globvarht);
3440 todo = globvarht.ht_used;
3441 for (hi = globvarht.ht_array; todo > 0 && !got_int; ++hi)
Bram Moolenaara7043832005-01-21 11:56:39 +00003442 {
3443 if (!HASHITEM_EMPTY(hi))
3444 {
3445 --todo;
Bram Moolenaar33570922005-01-25 22:26:29 +00003446 if (STRNCMP(HI2DI(hi)->di_key, "menutrans_", 10) == 0)
3447 delete_var(&globvarht, hi);
Bram Moolenaara7043832005-01-21 11:56:39 +00003448 }
3449 }
Bram Moolenaar33570922005-01-25 22:26:29 +00003450 hash_unlock(&globvarht);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003451}
3452#endif
3453
3454#if defined(FEAT_CMDL_COMPL) || defined(PROTO)
3455
3456/*
3457 * Local string buffer for the next two functions to store a variable name
3458 * with its prefix. Allocated in cat_prefix_varname(), freed later in
3459 * get_user_var_name().
3460 */
3461
3462static char_u *cat_prefix_varname __ARGS((int prefix, char_u *name));
3463
3464static char_u *varnamebuf = NULL;
3465static int varnamebuflen = 0;
3466
3467/*
3468 * Function to concatenate a prefix and a variable name.
3469 */
3470 static char_u *
3471cat_prefix_varname(prefix, name)
3472 int prefix;
3473 char_u *name;
3474{
3475 int len;
3476
3477 len = (int)STRLEN(name) + 3;
3478 if (len > varnamebuflen)
3479 {
3480 vim_free(varnamebuf);
3481 len += 10; /* some additional space */
3482 varnamebuf = alloc(len);
3483 if (varnamebuf == NULL)
3484 {
3485 varnamebuflen = 0;
3486 return NULL;
3487 }
3488 varnamebuflen = len;
3489 }
3490 *varnamebuf = prefix;
3491 varnamebuf[1] = ':';
3492 STRCPY(varnamebuf + 2, name);
3493 return varnamebuf;
3494}
3495
3496/*
3497 * Function given to ExpandGeneric() to obtain the list of user defined
3498 * (global/buffer/window/built-in) variable names.
3499 */
3500/*ARGSUSED*/
3501 char_u *
3502get_user_var_name(xp, idx)
3503 expand_T *xp;
3504 int idx;
3505{
Bram Moolenaar532c7802005-01-27 14:44:31 +00003506 static long_u gdone;
3507 static long_u bdone;
3508 static long_u wdone;
3509 static int vidx;
3510 static hashitem_T *hi;
3511 hashtab_T *ht;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003512
3513 if (idx == 0)
Bram Moolenaara7043832005-01-21 11:56:39 +00003514 gdone = bdone = wdone = vidx = 0;
Bram Moolenaar33570922005-01-25 22:26:29 +00003515
3516 /* Global variables */
3517 if (gdone < globvarht.ht_used)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003518 {
Bram Moolenaara7043832005-01-21 11:56:39 +00003519 if (gdone++ == 0)
Bram Moolenaar33570922005-01-25 22:26:29 +00003520 hi = globvarht.ht_array;
Bram Moolenaar532c7802005-01-27 14:44:31 +00003521 else
3522 ++hi;
Bram Moolenaara7043832005-01-21 11:56:39 +00003523 while (HASHITEM_EMPTY(hi))
3524 ++hi;
3525 if (STRNCMP("g:", xp->xp_pattern, 2) == 0)
3526 return cat_prefix_varname('g', hi->hi_key);
3527 return hi->hi_key;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003528 }
Bram Moolenaar33570922005-01-25 22:26:29 +00003529
3530 /* b: variables */
3531 ht = &curbuf->b_vars.dv_hashtab;
3532 if (bdone < ht->ht_used)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003533 {
Bram Moolenaara7043832005-01-21 11:56:39 +00003534 if (bdone++ == 0)
Bram Moolenaar33570922005-01-25 22:26:29 +00003535 hi = ht->ht_array;
Bram Moolenaar532c7802005-01-27 14:44:31 +00003536 else
3537 ++hi;
Bram Moolenaara7043832005-01-21 11:56:39 +00003538 while (HASHITEM_EMPTY(hi))
3539 ++hi;
3540 return cat_prefix_varname('b', hi->hi_key);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003541 }
Bram Moolenaar33570922005-01-25 22:26:29 +00003542 if (bdone == ht->ht_used)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003543 {
Bram Moolenaara7043832005-01-21 11:56:39 +00003544 ++bdone;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003545 return (char_u *)"b:changedtick";
3546 }
Bram Moolenaar33570922005-01-25 22:26:29 +00003547
3548 /* w: variables */
3549 ht = &curwin->w_vars.dv_hashtab;
3550 if (wdone < ht->ht_used)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003551 {
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +00003552 if (wdone++ == 0)
Bram Moolenaar33570922005-01-25 22:26:29 +00003553 hi = ht->ht_array;
Bram Moolenaar532c7802005-01-27 14:44:31 +00003554 else
3555 ++hi;
Bram Moolenaara7043832005-01-21 11:56:39 +00003556 while (HASHITEM_EMPTY(hi))
3557 ++hi;
3558 return cat_prefix_varname('w', hi->hi_key);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003559 }
Bram Moolenaar33570922005-01-25 22:26:29 +00003560
3561 /* v: variables */
3562 if (vidx < VV_LEN)
3563 return cat_prefix_varname('v', (char_u *)vimvars[vidx++].vv_name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003564
3565 vim_free(varnamebuf);
3566 varnamebuf = NULL;
3567 varnamebuflen = 0;
3568 return NULL;
3569}
3570
3571#endif /* FEAT_CMDL_COMPL */
3572
3573/*
3574 * types for expressions.
3575 */
3576typedef enum
3577{
3578 TYPE_UNKNOWN = 0
3579 , TYPE_EQUAL /* == */
3580 , TYPE_NEQUAL /* != */
3581 , TYPE_GREATER /* > */
3582 , TYPE_GEQUAL /* >= */
3583 , TYPE_SMALLER /* < */
3584 , TYPE_SEQUAL /* <= */
3585 , TYPE_MATCH /* =~ */
3586 , TYPE_NOMATCH /* !~ */
3587} exptype_T;
3588
3589/*
3590 * The "evaluate" argument: When FALSE, the argument is only parsed but not
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003591 * executed. The function may return OK, but the rettv will be of type
Bram Moolenaar071d4272004-06-13 20:20:40 +00003592 * VAR_UNKNOWN. The function still returns FAIL for a syntax error.
3593 */
3594
3595/*
3596 * Handle zero level expression.
3597 * This calls eval1() and handles error message and nextcmd.
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003598 * Put the result in "rettv" when returning OK and "evaluate" is TRUE.
Bram Moolenaar4463f292005-09-25 22:20:24 +00003599 * Note: "rettv.v_lock" is not set.
Bram Moolenaar071d4272004-06-13 20:20:40 +00003600 * Return OK or FAIL.
3601 */
3602 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003603eval0(arg, rettv, nextcmd, evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003604 char_u *arg;
Bram Moolenaar33570922005-01-25 22:26:29 +00003605 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003606 char_u **nextcmd;
3607 int evaluate;
3608{
3609 int ret;
3610 char_u *p;
3611
3612 p = skipwhite(arg);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003613 ret = eval1(&p, rettv, evaluate);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003614 if (ret == FAIL || !ends_excmd(*p))
3615 {
3616 if (ret != FAIL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003617 clear_tv(rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003618 /*
3619 * Report the invalid expression unless the expression evaluation has
3620 * been cancelled due to an aborting error, an interrupt, or an
3621 * exception.
3622 */
3623 if (!aborting())
3624 EMSG2(_(e_invexpr2), arg);
3625 ret = FAIL;
3626 }
3627 if (nextcmd != NULL)
3628 *nextcmd = check_nextcmd(p);
3629
3630 return ret;
3631}
3632
3633/*
3634 * Handle top level expression:
3635 * expr1 ? expr0 : expr0
3636 *
3637 * "arg" must point to the first non-white of the expression.
3638 * "arg" is advanced to the next non-white after the recognized expression.
3639 *
Bram Moolenaar4463f292005-09-25 22:20:24 +00003640 * Note: "rettv.v_lock" is not set.
3641 *
Bram Moolenaar071d4272004-06-13 20:20:40 +00003642 * Return OK or FAIL.
3643 */
3644 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003645eval1(arg, rettv, evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003646 char_u **arg;
Bram Moolenaar33570922005-01-25 22:26:29 +00003647 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003648 int evaluate;
3649{
3650 int result;
Bram Moolenaar33570922005-01-25 22:26:29 +00003651 typval_T var2;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003652
3653 /*
3654 * Get the first variable.
3655 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003656 if (eval2(arg, rettv, evaluate) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003657 return FAIL;
3658
3659 if ((*arg)[0] == '?')
3660 {
3661 result = FALSE;
3662 if (evaluate)
3663 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00003664 int error = FALSE;
3665
3666 if (get_tv_number_chk(rettv, &error) != 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003667 result = TRUE;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003668 clear_tv(rettv);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00003669 if (error)
3670 return FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003671 }
3672
3673 /*
3674 * Get the second variable.
3675 */
3676 *arg = skipwhite(*arg + 1);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003677 if (eval1(arg, rettv, evaluate && result) == FAIL) /* recursive! */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003678 return FAIL;
3679
3680 /*
3681 * Check for the ":".
3682 */
3683 if ((*arg)[0] != ':')
3684 {
3685 EMSG(_("E109: Missing ':' after '?'"));
3686 if (evaluate && result)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003687 clear_tv(rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003688 return FAIL;
3689 }
3690
3691 /*
3692 * Get the third variable.
3693 */
3694 *arg = skipwhite(*arg + 1);
3695 if (eval1(arg, &var2, evaluate && !result) == FAIL) /* recursive! */
3696 {
3697 if (evaluate && result)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003698 clear_tv(rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003699 return FAIL;
3700 }
3701 if (evaluate && !result)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003702 *rettv = var2;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003703 }
3704
3705 return OK;
3706}
3707
3708/*
3709 * Handle first level expression:
3710 * expr2 || expr2 || expr2 logical OR
3711 *
3712 * "arg" must point to the first non-white of the expression.
3713 * "arg" is advanced to the next non-white after the recognized expression.
3714 *
3715 * Return OK or FAIL.
3716 */
3717 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003718eval2(arg, rettv, evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003719 char_u **arg;
Bram Moolenaar33570922005-01-25 22:26:29 +00003720 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003721 int evaluate;
3722{
Bram Moolenaar33570922005-01-25 22:26:29 +00003723 typval_T var2;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003724 long result;
3725 int first;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00003726 int error = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003727
3728 /*
3729 * Get the first variable.
3730 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003731 if (eval3(arg, rettv, evaluate) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003732 return FAIL;
3733
3734 /*
3735 * Repeat until there is no following "||".
3736 */
3737 first = TRUE;
3738 result = FALSE;
3739 while ((*arg)[0] == '|' && (*arg)[1] == '|')
3740 {
3741 if (evaluate && first)
3742 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00003743 if (get_tv_number_chk(rettv, &error) != 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003744 result = TRUE;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003745 clear_tv(rettv);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00003746 if (error)
3747 return FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003748 first = FALSE;
3749 }
3750
3751 /*
3752 * Get the second variable.
3753 */
3754 *arg = skipwhite(*arg + 2);
3755 if (eval3(arg, &var2, evaluate && !result) == FAIL)
3756 return FAIL;
3757
3758 /*
3759 * Compute the result.
3760 */
3761 if (evaluate && !result)
3762 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00003763 if (get_tv_number_chk(&var2, &error) != 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003764 result = TRUE;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003765 clear_tv(&var2);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00003766 if (error)
3767 return FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003768 }
3769 if (evaluate)
3770 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003771 rettv->v_type = VAR_NUMBER;
3772 rettv->vval.v_number = result;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003773 }
3774 }
3775
3776 return OK;
3777}
3778
3779/*
3780 * Handle second level expression:
3781 * expr3 && expr3 && expr3 logical AND
3782 *
3783 * "arg" must point to the first non-white of the expression.
3784 * "arg" is advanced to the next non-white after the recognized expression.
3785 *
3786 * Return OK or FAIL.
3787 */
3788 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003789eval3(arg, rettv, evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003790 char_u **arg;
Bram Moolenaar33570922005-01-25 22:26:29 +00003791 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003792 int evaluate;
3793{
Bram Moolenaar33570922005-01-25 22:26:29 +00003794 typval_T var2;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003795 long result;
3796 int first;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00003797 int error = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003798
3799 /*
3800 * Get the first variable.
3801 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003802 if (eval4(arg, rettv, evaluate) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003803 return FAIL;
3804
3805 /*
3806 * Repeat until there is no following "&&".
3807 */
3808 first = TRUE;
3809 result = TRUE;
3810 while ((*arg)[0] == '&' && (*arg)[1] == '&')
3811 {
3812 if (evaluate && first)
3813 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00003814 if (get_tv_number_chk(rettv, &error) == 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003815 result = FALSE;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003816 clear_tv(rettv);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00003817 if (error)
3818 return FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003819 first = FALSE;
3820 }
3821
3822 /*
3823 * Get the second variable.
3824 */
3825 *arg = skipwhite(*arg + 2);
3826 if (eval4(arg, &var2, evaluate && result) == FAIL)
3827 return FAIL;
3828
3829 /*
3830 * Compute the result.
3831 */
3832 if (evaluate && result)
3833 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00003834 if (get_tv_number_chk(&var2, &error) == 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003835 result = FALSE;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003836 clear_tv(&var2);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00003837 if (error)
3838 return FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003839 }
3840 if (evaluate)
3841 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003842 rettv->v_type = VAR_NUMBER;
3843 rettv->vval.v_number = result;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003844 }
3845 }
3846
3847 return OK;
3848}
3849
3850/*
3851 * Handle third level expression:
3852 * var1 == var2
3853 * var1 =~ var2
3854 * var1 != var2
3855 * var1 !~ var2
3856 * var1 > var2
3857 * var1 >= var2
3858 * var1 < var2
3859 * var1 <= var2
Bram Moolenaar8a283e52005-01-06 23:28:25 +00003860 * var1 is var2
3861 * var1 isnot var2
Bram Moolenaar071d4272004-06-13 20:20:40 +00003862 *
3863 * "arg" must point to the first non-white of the expression.
3864 * "arg" is advanced to the next non-white after the recognized expression.
3865 *
3866 * Return OK or FAIL.
3867 */
3868 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003869eval4(arg, rettv, evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003870 char_u **arg;
Bram Moolenaar33570922005-01-25 22:26:29 +00003871 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003872 int evaluate;
3873{
Bram Moolenaar33570922005-01-25 22:26:29 +00003874 typval_T var2;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003875 char_u *p;
3876 int i;
3877 exptype_T type = TYPE_UNKNOWN;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00003878 int type_is = FALSE; /* TRUE for "is" and "isnot" */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003879 int len = 2;
3880 long n1, n2;
3881 char_u *s1, *s2;
3882 char_u buf1[NUMBUFLEN], buf2[NUMBUFLEN];
3883 regmatch_T regmatch;
3884 int ic;
3885 char_u *save_cpo;
3886
3887 /*
3888 * Get the first variable.
3889 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003890 if (eval5(arg, rettv, evaluate) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003891 return FAIL;
3892
3893 p = *arg;
3894 switch (p[0])
3895 {
3896 case '=': if (p[1] == '=')
3897 type = TYPE_EQUAL;
3898 else if (p[1] == '~')
3899 type = TYPE_MATCH;
3900 break;
3901 case '!': if (p[1] == '=')
3902 type = TYPE_NEQUAL;
3903 else if (p[1] == '~')
3904 type = TYPE_NOMATCH;
3905 break;
3906 case '>': if (p[1] != '=')
3907 {
3908 type = TYPE_GREATER;
3909 len = 1;
3910 }
3911 else
3912 type = TYPE_GEQUAL;
3913 break;
3914 case '<': if (p[1] != '=')
3915 {
3916 type = TYPE_SMALLER;
3917 len = 1;
3918 }
3919 else
3920 type = TYPE_SEQUAL;
3921 break;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00003922 case 'i': if (p[1] == 's')
3923 {
3924 if (p[2] == 'n' && p[3] == 'o' && p[4] == 't')
3925 len = 5;
3926 if (!vim_isIDc(p[len]))
3927 {
3928 type = len == 2 ? TYPE_EQUAL : TYPE_NEQUAL;
3929 type_is = TRUE;
3930 }
3931 }
3932 break;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003933 }
3934
3935 /*
3936 * If there is a comparitive operator, use it.
3937 */
3938 if (type != TYPE_UNKNOWN)
3939 {
3940 /* extra question mark appended: ignore case */
3941 if (p[len] == '?')
3942 {
3943 ic = TRUE;
3944 ++len;
3945 }
3946 /* extra '#' appended: match case */
3947 else if (p[len] == '#')
3948 {
3949 ic = FALSE;
3950 ++len;
3951 }
3952 /* nothing appened: use 'ignorecase' */
3953 else
3954 ic = p_ic;
3955
3956 /*
3957 * Get the second variable.
3958 */
3959 *arg = skipwhite(p + len);
3960 if (eval5(arg, &var2, evaluate) == FAIL)
3961 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003962 clear_tv(rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003963 return FAIL;
3964 }
3965
3966 if (evaluate)
3967 {
Bram Moolenaar8a283e52005-01-06 23:28:25 +00003968 if (type_is && rettv->v_type != var2.v_type)
3969 {
3970 /* For "is" a different type always means FALSE, for "notis"
3971 * it means TRUE. */
3972 n1 = (type == TYPE_NEQUAL);
3973 }
3974 else if (rettv->v_type == VAR_LIST || var2.v_type == VAR_LIST)
3975 {
3976 if (type_is)
3977 {
3978 n1 = (rettv->v_type == var2.v_type
3979 && rettv->vval.v_list == var2.vval.v_list);
3980 if (type == TYPE_NEQUAL)
3981 n1 = !n1;
3982 }
3983 else if (rettv->v_type != var2.v_type
3984 || (type != TYPE_EQUAL && type != TYPE_NEQUAL))
3985 {
3986 if (rettv->v_type != var2.v_type)
Bram Moolenaare49b69a2005-01-08 16:11:57 +00003987 EMSG(_("E691: Can only compare List with List"));
Bram Moolenaar8a283e52005-01-06 23:28:25 +00003988 else
Bram Moolenaare49b69a2005-01-08 16:11:57 +00003989 EMSG(_("E692: Invalid operation for Lists"));
Bram Moolenaar8a283e52005-01-06 23:28:25 +00003990 clear_tv(rettv);
3991 clear_tv(&var2);
3992 return FAIL;
3993 }
3994 else
3995 {
3996 /* Compare two Lists for being equal or unequal. */
3997 n1 = list_equal(rettv->vval.v_list, var2.vval.v_list, ic);
3998 if (type == TYPE_NEQUAL)
3999 n1 = !n1;
4000 }
4001 }
4002
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00004003 else if (rettv->v_type == VAR_DICT || var2.v_type == VAR_DICT)
4004 {
4005 if (type_is)
4006 {
4007 n1 = (rettv->v_type == var2.v_type
4008 && rettv->vval.v_dict == var2.vval.v_dict);
4009 if (type == TYPE_NEQUAL)
4010 n1 = !n1;
4011 }
4012 else if (rettv->v_type != var2.v_type
4013 || (type != TYPE_EQUAL && type != TYPE_NEQUAL))
4014 {
4015 if (rettv->v_type != var2.v_type)
4016 EMSG(_("E735: Can only compare Dictionary with Dictionary"));
4017 else
4018 EMSG(_("E736: Invalid operation for Dictionary"));
4019 clear_tv(rettv);
4020 clear_tv(&var2);
4021 return FAIL;
4022 }
4023 else
4024 {
4025 /* Compare two Dictionaries for being equal or unequal. */
4026 n1 = dict_equal(rettv->vval.v_dict, var2.vval.v_dict, ic);
4027 if (type == TYPE_NEQUAL)
4028 n1 = !n1;
4029 }
4030 }
4031
Bram Moolenaar8a283e52005-01-06 23:28:25 +00004032 else if (rettv->v_type == VAR_FUNC || var2.v_type == VAR_FUNC)
4033 {
4034 if (rettv->v_type != var2.v_type
4035 || (type != TYPE_EQUAL && type != TYPE_NEQUAL))
4036 {
4037 if (rettv->v_type != var2.v_type)
Bram Moolenaare49b69a2005-01-08 16:11:57 +00004038 EMSG(_("E693: Can only compare Funcref with Funcref"));
Bram Moolenaar8a283e52005-01-06 23:28:25 +00004039 else
Bram Moolenaare49b69a2005-01-08 16:11:57 +00004040 EMSG(_("E694: Invalid operation for Funcrefs"));
Bram Moolenaar8a283e52005-01-06 23:28:25 +00004041 clear_tv(rettv);
4042 clear_tv(&var2);
4043 return FAIL;
4044 }
4045 else
4046 {
4047 /* Compare two Funcrefs for being equal or unequal. */
4048 if (rettv->vval.v_string == NULL
4049 || var2.vval.v_string == NULL)
4050 n1 = FALSE;
4051 else
4052 n1 = STRCMP(rettv->vval.v_string,
4053 var2.vval.v_string) == 0;
4054 if (type == TYPE_NEQUAL)
4055 n1 = !n1;
4056 }
4057 }
4058
Bram Moolenaar071d4272004-06-13 20:20:40 +00004059 /*
4060 * If one of the two variables is a number, compare as a number.
4061 * When using "=~" or "!~", always compare as string.
4062 */
Bram Moolenaar8a283e52005-01-06 23:28:25 +00004063 else if ((rettv->v_type == VAR_NUMBER || var2.v_type == VAR_NUMBER)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004064 && type != TYPE_MATCH && type != TYPE_NOMATCH)
4065 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004066 n1 = get_tv_number(rettv);
4067 n2 = get_tv_number(&var2);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004068 switch (type)
4069 {
4070 case TYPE_EQUAL: n1 = (n1 == n2); break;
4071 case TYPE_NEQUAL: n1 = (n1 != n2); break;
4072 case TYPE_GREATER: n1 = (n1 > n2); break;
4073 case TYPE_GEQUAL: n1 = (n1 >= n2); break;
4074 case TYPE_SMALLER: n1 = (n1 < n2); break;
4075 case TYPE_SEQUAL: n1 = (n1 <= n2); break;
4076 case TYPE_UNKNOWN:
4077 case TYPE_MATCH:
4078 case TYPE_NOMATCH: break; /* avoid gcc warning */
4079 }
4080 }
4081 else
4082 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004083 s1 = get_tv_string_buf(rettv, buf1);
4084 s2 = get_tv_string_buf(&var2, buf2);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004085 if (type != TYPE_MATCH && type != TYPE_NOMATCH)
4086 i = ic ? MB_STRICMP(s1, s2) : STRCMP(s1, s2);
4087 else
4088 i = 0;
4089 n1 = FALSE;
4090 switch (type)
4091 {
4092 case TYPE_EQUAL: n1 = (i == 0); break;
4093 case TYPE_NEQUAL: n1 = (i != 0); break;
4094 case TYPE_GREATER: n1 = (i > 0); break;
4095 case TYPE_GEQUAL: n1 = (i >= 0); break;
4096 case TYPE_SMALLER: n1 = (i < 0); break;
4097 case TYPE_SEQUAL: n1 = (i <= 0); break;
4098
4099 case TYPE_MATCH:
4100 case TYPE_NOMATCH:
4101 /* avoid 'l' flag in 'cpoptions' */
4102 save_cpo = p_cpo;
4103 p_cpo = (char_u *)"";
4104 regmatch.regprog = vim_regcomp(s2,
4105 RE_MAGIC + RE_STRING);
4106 regmatch.rm_ic = ic;
4107 if (regmatch.regprog != NULL)
4108 {
4109 n1 = vim_regexec_nl(&regmatch, s1, (colnr_T)0);
4110 vim_free(regmatch.regprog);
4111 if (type == TYPE_NOMATCH)
4112 n1 = !n1;
4113 }
4114 p_cpo = save_cpo;
4115 break;
4116
4117 case TYPE_UNKNOWN: break; /* avoid gcc warning */
4118 }
4119 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004120 clear_tv(rettv);
4121 clear_tv(&var2);
4122 rettv->v_type = VAR_NUMBER;
4123 rettv->vval.v_number = n1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004124 }
4125 }
4126
4127 return OK;
4128}
4129
4130/*
4131 * Handle fourth level expression:
4132 * + number addition
4133 * - number subtraction
4134 * . string concatenation
4135 *
4136 * "arg" must point to the first non-white of the expression.
4137 * "arg" is advanced to the next non-white after the recognized expression.
4138 *
4139 * Return OK or FAIL.
4140 */
4141 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004142eval5(arg, rettv, evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004143 char_u **arg;
Bram Moolenaar33570922005-01-25 22:26:29 +00004144 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004145 int evaluate;
4146{
Bram Moolenaar33570922005-01-25 22:26:29 +00004147 typval_T var2;
4148 typval_T var3;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004149 int op;
4150 long n1, n2;
4151 char_u *s1, *s2;
4152 char_u buf1[NUMBUFLEN], buf2[NUMBUFLEN];
4153 char_u *p;
4154
4155 /*
4156 * Get the first variable.
4157 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004158 if (eval6(arg, rettv, evaluate) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004159 return FAIL;
4160
4161 /*
4162 * Repeat computing, until no '+', '-' or '.' is following.
4163 */
4164 for (;;)
4165 {
4166 op = **arg;
4167 if (op != '+' && op != '-' && op != '.')
4168 break;
4169
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004170 if (op != '+' || rettv->v_type != VAR_LIST)
4171 {
4172 /* For "list + ...", an illegal use of the first operand as
4173 * a number cannot be determined before evaluating the 2nd
4174 * operand: if this is also a list, all is ok.
4175 * For "something . ...", "something - ..." or "non-list + ...",
4176 * we know that the first operand needs to be a string or number
4177 * without evaluating the 2nd operand. So check before to avoid
4178 * side effects after an error. */
4179 if (evaluate && get_tv_string_chk(rettv) == NULL)
4180 {
4181 clear_tv(rettv);
4182 return FAIL;
4183 }
4184 }
4185
Bram Moolenaar071d4272004-06-13 20:20:40 +00004186 /*
4187 * Get the second variable.
4188 */
4189 *arg = skipwhite(*arg + 1);
4190 if (eval6(arg, &var2, evaluate) == FAIL)
4191 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004192 clear_tv(rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004193 return FAIL;
4194 }
4195
4196 if (evaluate)
4197 {
4198 /*
4199 * Compute the result.
4200 */
4201 if (op == '.')
4202 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004203 s1 = get_tv_string_buf(rettv, buf1); /* already checked */
4204 s2 = get_tv_string_buf_chk(&var2, buf2);
4205 if (s2 == NULL) /* type error ? */
4206 {
4207 clear_tv(rettv);
4208 clear_tv(&var2);
4209 return FAIL;
4210 }
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00004211 p = concat_str(s1, s2);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004212 clear_tv(rettv);
4213 rettv->v_type = VAR_STRING;
4214 rettv->vval.v_string = p;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004215 }
Bram Moolenaare9a41262005-01-15 22:18:47 +00004216 else if (op == '+' && rettv->v_type == VAR_LIST
4217 && var2.v_type == VAR_LIST)
Bram Moolenaar8a283e52005-01-06 23:28:25 +00004218 {
4219 /* concatenate Lists */
4220 if (list_concat(rettv->vval.v_list, var2.vval.v_list,
4221 &var3) == FAIL)
4222 {
4223 clear_tv(rettv);
4224 clear_tv(&var2);
4225 return FAIL;
4226 }
4227 clear_tv(rettv);
4228 *rettv = var3;
4229 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004230 else
4231 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004232 int error = FALSE;
4233
4234 n1 = get_tv_number_chk(rettv, &error);
4235 if (error)
4236 {
4237 /* This can only happen for "list + non-list".
4238 * For "non-list + ..." or "something - ...", we returned
4239 * before evaluating the 2nd operand. */
4240 clear_tv(rettv);
4241 return FAIL;
4242 }
4243 n2 = get_tv_number_chk(&var2, &error);
4244 if (error)
4245 {
4246 clear_tv(rettv);
4247 clear_tv(&var2);
4248 return FAIL;
4249 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004250 clear_tv(rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004251 if (op == '+')
4252 n1 = n1 + n2;
4253 else
4254 n1 = n1 - n2;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004255 rettv->v_type = VAR_NUMBER;
4256 rettv->vval.v_number = n1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004257 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004258 clear_tv(&var2);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004259 }
4260 }
4261 return OK;
4262}
4263
4264/*
4265 * Handle fifth level expression:
4266 * * number multiplication
4267 * / number division
4268 * % number modulo
4269 *
4270 * "arg" must point to the first non-white of the expression.
4271 * "arg" is advanced to the next non-white after the recognized expression.
4272 *
4273 * Return OK or FAIL.
4274 */
4275 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004276eval6(arg, rettv, evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004277 char_u **arg;
Bram Moolenaar33570922005-01-25 22:26:29 +00004278 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004279 int evaluate;
4280{
Bram Moolenaar33570922005-01-25 22:26:29 +00004281 typval_T var2;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004282 int op;
4283 long n1, n2;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004284 int error = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004285
4286 /*
4287 * Get the first variable.
4288 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004289 if (eval7(arg, rettv, evaluate) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004290 return FAIL;
4291
4292 /*
4293 * Repeat computing, until no '*', '/' or '%' is following.
4294 */
4295 for (;;)
4296 {
4297 op = **arg;
4298 if (op != '*' && op != '/' && op != '%')
4299 break;
4300
4301 if (evaluate)
4302 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004303 n1 = get_tv_number_chk(rettv, &error);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004304 clear_tv(rettv);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004305 if (error)
4306 return FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004307 }
4308 else
4309 n1 = 0;
4310
4311 /*
4312 * Get the second variable.
4313 */
4314 *arg = skipwhite(*arg + 1);
4315 if (eval7(arg, &var2, evaluate) == FAIL)
4316 return FAIL;
4317
4318 if (evaluate)
4319 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004320 n2 = get_tv_number_chk(&var2, &error);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004321 clear_tv(&var2);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004322 if (error)
4323 return FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004324
4325 /*
4326 * Compute the result.
4327 */
4328 if (op == '*')
4329 n1 = n1 * n2;
4330 else if (op == '/')
4331 {
4332 if (n2 == 0) /* give an error message? */
4333 n1 = 0x7fffffffL;
4334 else
4335 n1 = n1 / n2;
4336 }
4337 else
4338 {
4339 if (n2 == 0) /* give an error message? */
4340 n1 = 0;
4341 else
4342 n1 = n1 % n2;
4343 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004344 rettv->v_type = VAR_NUMBER;
4345 rettv->vval.v_number = n1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004346 }
4347 }
4348
4349 return OK;
4350}
4351
4352/*
4353 * Handle sixth level expression:
4354 * number number constant
4355 * "string" string contstant
4356 * 'string' literal string contstant
4357 * &option-name option value
4358 * @r register contents
4359 * identifier variable value
4360 * function() function call
4361 * $VAR environment variable
4362 * (expression) nested expression
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00004363 * [expr, expr] List
4364 * {key: val, key: val} Dictionary
Bram Moolenaar071d4272004-06-13 20:20:40 +00004365 *
4366 * Also handle:
4367 * ! in front logical NOT
4368 * - in front unary minus
4369 * + in front unary plus (ignored)
Bram Moolenaar8c711452005-01-14 21:53:12 +00004370 * trailing [] subscript in String or List
4371 * trailing .name entry in Dictionary
Bram Moolenaar071d4272004-06-13 20:20:40 +00004372 *
4373 * "arg" must point to the first non-white of the expression.
4374 * "arg" is advanced to the next non-white after the recognized expression.
4375 *
4376 * Return OK or FAIL.
4377 */
4378 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004379eval7(arg, rettv, evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004380 char_u **arg;
Bram Moolenaar33570922005-01-25 22:26:29 +00004381 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004382 int evaluate;
4383{
Bram Moolenaar071d4272004-06-13 20:20:40 +00004384 long n;
4385 int len;
4386 char_u *s;
4387 int val;
4388 char_u *start_leader, *end_leader;
4389 int ret = OK;
4390 char_u *alias;
4391
4392 /*
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004393 * Initialise variable so that clear_tv() can't mistake this for a
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004394 * string and free a string that isn't there.
Bram Moolenaar071d4272004-06-13 20:20:40 +00004395 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004396 rettv->v_type = VAR_UNKNOWN;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004397
4398 /*
4399 * Skip '!' and '-' characters. They are handled later.
4400 */
4401 start_leader = *arg;
4402 while (**arg == '!' || **arg == '-' || **arg == '+')
4403 *arg = skipwhite(*arg + 1);
4404 end_leader = *arg;
4405
4406 switch (**arg)
4407 {
4408 /*
4409 * Number constant.
4410 */
4411 case '0':
4412 case '1':
4413 case '2':
4414 case '3':
4415 case '4':
4416 case '5':
4417 case '6':
4418 case '7':
4419 case '8':
4420 case '9':
4421 vim_str2nr(*arg, NULL, &len, TRUE, TRUE, &n, NULL);
4422 *arg += len;
4423 if (evaluate)
4424 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004425 rettv->v_type = VAR_NUMBER;
4426 rettv->vval.v_number = n;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004427 }
4428 break;
4429
4430 /*
4431 * String constant: "string".
4432 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004433 case '"': ret = get_string_tv(arg, rettv, evaluate);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004434 break;
4435
4436 /*
Bram Moolenaar8c711452005-01-14 21:53:12 +00004437 * Literal string constant: 'str''ing'.
Bram Moolenaar071d4272004-06-13 20:20:40 +00004438 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004439 case '\'': ret = get_lit_string_tv(arg, rettv, evaluate);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004440 break;
4441
4442 /*
4443 * List: [expr, expr]
4444 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004445 case '[': ret = get_list_tv(arg, rettv, evaluate);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004446 break;
4447
4448 /*
Bram Moolenaar8c711452005-01-14 21:53:12 +00004449 * Dictionary: {key: val, key: val}
4450 */
4451 case '{': ret = get_dict_tv(arg, rettv, evaluate);
4452 break;
4453
4454 /*
Bram Moolenaare9a41262005-01-15 22:18:47 +00004455 * Option value: &name
Bram Moolenaar071d4272004-06-13 20:20:40 +00004456 */
Bram Moolenaare9a41262005-01-15 22:18:47 +00004457 case '&': ret = get_option_tv(arg, rettv, evaluate);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004458 break;
4459
4460 /*
4461 * Environment variable: $VAR.
4462 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004463 case '$': ret = get_env_tv(arg, rettv, evaluate);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004464 break;
4465
4466 /*
4467 * Register contents: @r.
4468 */
4469 case '@': ++*arg;
4470 if (evaluate)
4471 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004472 rettv->v_type = VAR_STRING;
Bram Moolenaar92124a32005-06-17 22:03:40 +00004473 rettv->vval.v_string = get_reg_contents(**arg, TRUE, TRUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004474 }
4475 if (**arg != NUL)
4476 ++*arg;
4477 break;
4478
4479 /*
4480 * nested expression: (expression).
4481 */
4482 case '(': *arg = skipwhite(*arg + 1);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004483 ret = eval1(arg, rettv, evaluate); /* recursive! */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004484 if (**arg == ')')
4485 ++*arg;
4486 else if (ret == OK)
4487 {
4488 EMSG(_("E110: Missing ')'"));
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004489 clear_tv(rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004490 ret = FAIL;
4491 }
4492 break;
4493
Bram Moolenaar8c711452005-01-14 21:53:12 +00004494 default: ret = NOTDONE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004495 break;
4496 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00004497
4498 if (ret == NOTDONE)
4499 {
4500 /*
4501 * Must be a variable or function name.
4502 * Can also be a curly-braces kind of name: {expr}.
4503 */
4504 s = *arg;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00004505 len = get_name_len(arg, &alias, evaluate, TRUE);
Bram Moolenaar8c711452005-01-14 21:53:12 +00004506 if (alias != NULL)
4507 s = alias;
4508
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00004509 if (len <= 0)
Bram Moolenaar8c711452005-01-14 21:53:12 +00004510 ret = FAIL;
4511 else
4512 {
4513 if (**arg == '(') /* recursive! */
4514 {
4515 /* If "s" is the name of a variable of type VAR_FUNC
4516 * use its contents. */
4517 s = deref_func_name(s, &len);
4518
4519 /* Invoke the function. */
4520 ret = get_func_tv(s, len, rettv, arg,
4521 curwin->w_cursor.lnum, curwin->w_cursor.lnum,
Bram Moolenaare9a41262005-01-15 22:18:47 +00004522 &len, evaluate, NULL);
Bram Moolenaar8c711452005-01-14 21:53:12 +00004523 /* Stop the expression evaluation when immediately
4524 * aborting on error, or when an interrupt occurred or
4525 * an exception was thrown but not caught. */
4526 if (aborting())
4527 {
4528 if (ret == OK)
4529 clear_tv(rettv);
4530 ret = FAIL;
4531 }
4532 }
4533 else if (evaluate)
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00004534 ret = get_var_tv(s, len, rettv, TRUE);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00004535 else
4536 ret = OK;
Bram Moolenaar8c711452005-01-14 21:53:12 +00004537 }
4538
4539 if (alias != NULL)
4540 vim_free(alias);
4541 }
4542
Bram Moolenaar071d4272004-06-13 20:20:40 +00004543 *arg = skipwhite(*arg);
4544
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00004545 /* Handle following '[', '(' and '.' for expr[expr], expr.name,
4546 * expr(expr). */
4547 if (ret == OK)
4548 ret = handle_subscript(arg, rettv, evaluate, TRUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004549
4550 /*
4551 * Apply logical NOT and unary '-', from right to left, ignore '+'.
4552 */
4553 if (ret == OK && evaluate && end_leader > start_leader)
4554 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004555 int error = FALSE;
4556
4557 val = get_tv_number_chk(rettv, &error);
4558 if (error)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004559 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004560 clear_tv(rettv);
4561 ret = FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004562 }
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004563 else
4564 {
4565 while (end_leader > start_leader)
4566 {
4567 --end_leader;
4568 if (*end_leader == '!')
4569 val = !val;
4570 else if (*end_leader == '-')
4571 val = -val;
4572 }
4573 clear_tv(rettv);
4574 rettv->v_type = VAR_NUMBER;
4575 rettv->vval.v_number = val;
4576 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004577 }
4578
4579 return ret;
4580}
4581
4582/*
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004583 * Evaluate an "[expr]" or "[expr:expr]" index.
4584 * "*arg" points to the '['.
4585 * Returns FAIL or OK. "*arg" is advanced to after the ']'.
4586 */
4587 static int
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00004588eval_index(arg, rettv, evaluate, verbose)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004589 char_u **arg;
Bram Moolenaar33570922005-01-25 22:26:29 +00004590 typval_T *rettv;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004591 int evaluate;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00004592 int verbose; /* give error messages */
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004593{
4594 int empty1 = FALSE, empty2 = FALSE;
Bram Moolenaar33570922005-01-25 22:26:29 +00004595 typval_T var1, var2;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004596 long n1, n2 = 0;
Bram Moolenaar8c711452005-01-14 21:53:12 +00004597 long len = -1;
4598 int range = FALSE;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004599 char_u *s;
Bram Moolenaar8c711452005-01-14 21:53:12 +00004600 char_u *key = NULL;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004601
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004602 if (rettv->v_type == VAR_FUNC)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004603 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00004604 if (verbose)
4605 EMSG(_("E695: Cannot index a Funcref"));
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004606 return FAIL;
4607 }
4608
Bram Moolenaar8c711452005-01-14 21:53:12 +00004609 if (**arg == '.')
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004610 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00004611 /*
4612 * dict.name
4613 */
4614 key = *arg + 1;
4615 for (len = 0; ASCII_ISALNUM(key[len]) || key[len] == '_'; ++len)
4616 ;
4617 if (len == 0)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004618 return FAIL;
Bram Moolenaar8c711452005-01-14 21:53:12 +00004619 *arg = skipwhite(key + len);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004620 }
4621 else
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004622 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00004623 /*
4624 * something[idx]
4625 *
4626 * Get the (first) variable from inside the [].
4627 */
4628 *arg = skipwhite(*arg + 1);
4629 if (**arg == ':')
4630 empty1 = TRUE;
4631 else if (eval1(arg, &var1, evaluate) == FAIL) /* recursive! */
4632 return FAIL;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004633 else if (evaluate && get_tv_string_chk(&var1) == NULL)
4634 {
4635 /* not a number or string */
4636 clear_tv(&var1);
4637 return FAIL;
4638 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00004639
4640 /*
4641 * Get the second variable from inside the [:].
4642 */
4643 if (**arg == ':')
4644 {
4645 range = TRUE;
4646 *arg = skipwhite(*arg + 1);
4647 if (**arg == ']')
4648 empty2 = TRUE;
4649 else if (eval1(arg, &var2, evaluate) == FAIL) /* recursive! */
4650 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00004651 if (!empty1)
4652 clear_tv(&var1);
4653 return FAIL;
4654 }
4655 else if (evaluate && get_tv_string_chk(&var2) == NULL)
4656 {
4657 /* not a number or string */
4658 if (!empty1)
4659 clear_tv(&var1);
4660 clear_tv(&var2);
Bram Moolenaar8c711452005-01-14 21:53:12 +00004661 return FAIL;
4662 }
4663 }
4664
4665 /* Check for the ']'. */
4666 if (**arg != ']')
4667 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00004668 if (verbose)
4669 EMSG(_(e_missbrac));
Bram Moolenaar8c711452005-01-14 21:53:12 +00004670 clear_tv(&var1);
4671 if (range)
4672 clear_tv(&var2);
4673 return FAIL;
4674 }
4675 *arg = skipwhite(*arg + 1); /* skip the ']' */
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004676 }
4677
4678 if (evaluate)
4679 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00004680 n1 = 0;
4681 if (!empty1 && rettv->v_type != VAR_DICT)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004682 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004683 n1 = get_tv_number(&var1);
4684 clear_tv(&var1);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004685 }
4686 if (range)
4687 {
4688 if (empty2)
4689 n2 = -1;
4690 else
4691 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004692 n2 = get_tv_number(&var2);
4693 clear_tv(&var2);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004694 }
4695 }
4696
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004697 switch (rettv->v_type)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004698 {
4699 case VAR_NUMBER:
4700 case VAR_STRING:
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004701 s = get_tv_string(rettv);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004702 len = (long)STRLEN(s);
4703 if (range)
4704 {
4705 /* The resulting variable is a substring. If the indexes
4706 * are out of range the result is empty. */
4707 if (n1 < 0)
4708 {
4709 n1 = len + n1;
4710 if (n1 < 0)
4711 n1 = 0;
4712 }
4713 if (n2 < 0)
4714 n2 = len + n2;
4715 else if (n2 >= len)
4716 n2 = len;
4717 if (n1 >= len || n2 < 0 || n1 > n2)
4718 s = NULL;
4719 else
4720 s = vim_strnsave(s + n1, (int)(n2 - n1 + 1));
4721 }
4722 else
4723 {
4724 /* The resulting variable is a string of a single
4725 * character. If the index is too big or negative the
4726 * result is empty. */
4727 if (n1 >= len || n1 < 0)
4728 s = NULL;
4729 else
4730 s = vim_strnsave(s + n1, 1);
4731 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004732 clear_tv(rettv);
4733 rettv->v_type = VAR_STRING;
4734 rettv->vval.v_string = s;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004735 break;
4736
4737 case VAR_LIST:
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004738 len = list_len(rettv->vval.v_list);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004739 if (n1 < 0)
4740 n1 = len + n1;
4741 if (!empty1 && (n1 < 0 || n1 >= len))
4742 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00004743 if (verbose)
4744 EMSGN(_(e_listidx), n1);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004745 return FAIL;
4746 }
4747 if (range)
4748 {
Bram Moolenaar33570922005-01-25 22:26:29 +00004749 list_T *l;
4750 listitem_T *item;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004751
4752 if (n2 < 0)
4753 n2 = len + n2;
Bram Moolenaar8c711452005-01-14 21:53:12 +00004754 if (!empty2 && (n2 < 0 || n2 >= len || n2 + 1 < n1))
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004755 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00004756 if (verbose)
4757 EMSGN(_(e_listidx), n2);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004758 return FAIL;
4759 }
4760 l = list_alloc();
4761 if (l == NULL)
4762 return FAIL;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004763 for (item = list_find(rettv->vval.v_list, n1);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004764 n1 <= n2; ++n1)
4765 {
4766 if (list_append_tv(l, &item->li_tv) == FAIL)
4767 {
4768 list_free(l);
4769 return FAIL;
4770 }
4771 item = item->li_next;
4772 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004773 clear_tv(rettv);
4774 rettv->v_type = VAR_LIST;
4775 rettv->vval.v_list = l;
Bram Moolenaar0d660222005-01-07 21:51:51 +00004776 ++l->lv_refcount;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004777 }
4778 else
4779 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004780 copy_tv(&list_find(rettv->vval.v_list, n1)->li_tv,
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004781 &var1);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004782 clear_tv(rettv);
4783 *rettv = var1;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004784 }
4785 break;
Bram Moolenaar8c711452005-01-14 21:53:12 +00004786
4787 case VAR_DICT:
4788 if (range)
4789 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00004790 if (verbose)
4791 EMSG(_(e_dictrange));
Bram Moolenaar8c711452005-01-14 21:53:12 +00004792 if (len == -1)
4793 clear_tv(&var1);
4794 return FAIL;
4795 }
4796 {
Bram Moolenaar33570922005-01-25 22:26:29 +00004797 dictitem_T *item;
Bram Moolenaar8c711452005-01-14 21:53:12 +00004798
4799 if (len == -1)
4800 {
4801 key = get_tv_string(&var1);
4802 if (*key == NUL)
4803 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00004804 if (verbose)
4805 EMSG(_(e_emptykey));
Bram Moolenaar8c711452005-01-14 21:53:12 +00004806 clear_tv(&var1);
4807 return FAIL;
4808 }
4809 }
4810
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00004811 item = dict_find(rettv->vval.v_dict, key, (int)len);
Bram Moolenaar8c711452005-01-14 21:53:12 +00004812
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00004813 if (item == NULL && verbose)
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00004814 EMSG2(_(e_dictkey), key);
Bram Moolenaar8c711452005-01-14 21:53:12 +00004815 if (len == -1)
4816 clear_tv(&var1);
4817 if (item == NULL)
4818 return FAIL;
4819
4820 copy_tv(&item->di_tv, &var1);
4821 clear_tv(rettv);
4822 *rettv = var1;
4823 }
4824 break;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004825 }
4826 }
4827
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004828 return OK;
4829}
4830
4831/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00004832 * Get an option value.
4833 * "arg" points to the '&' or '+' before the option name.
4834 * "arg" is advanced to character after the option name.
4835 * Return OK or FAIL.
4836 */
4837 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004838get_option_tv(arg, rettv, evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004839 char_u **arg;
Bram Moolenaar33570922005-01-25 22:26:29 +00004840 typval_T *rettv; /* when NULL, only check if option exists */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004841 int evaluate;
4842{
4843 char_u *option_end;
4844 long numval;
4845 char_u *stringval;
4846 int opt_type;
4847 int c;
4848 int working = (**arg == '+'); /* has("+option") */
4849 int ret = OK;
4850 int opt_flags;
4851
4852 /*
4853 * Isolate the option name and find its value.
4854 */
4855 option_end = find_option_end(arg, &opt_flags);
4856 if (option_end == NULL)
4857 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004858 if (rettv != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004859 EMSG2(_("E112: Option name missing: %s"), *arg);
4860 return FAIL;
4861 }
4862
4863 if (!evaluate)
4864 {
4865 *arg = option_end;
4866 return OK;
4867 }
4868
4869 c = *option_end;
4870 *option_end = NUL;
4871 opt_type = get_option_value(*arg, &numval,
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004872 rettv == NULL ? NULL : &stringval, opt_flags);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004873
4874 if (opt_type == -3) /* invalid name */
4875 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004876 if (rettv != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004877 EMSG2(_("E113: Unknown option: %s"), *arg);
4878 ret = FAIL;
4879 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004880 else if (rettv != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004881 {
4882 if (opt_type == -2) /* hidden string option */
4883 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004884 rettv->v_type = VAR_STRING;
4885 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004886 }
4887 else if (opt_type == -1) /* hidden number option */
4888 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004889 rettv->v_type = VAR_NUMBER;
4890 rettv->vval.v_number = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004891 }
4892 else if (opt_type == 1) /* number option */
4893 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004894 rettv->v_type = VAR_NUMBER;
4895 rettv->vval.v_number = numval;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004896 }
4897 else /* string option */
4898 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004899 rettv->v_type = VAR_STRING;
4900 rettv->vval.v_string = stringval;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004901 }
4902 }
4903 else if (working && (opt_type == -2 || opt_type == -1))
4904 ret = FAIL;
4905
4906 *option_end = c; /* put back for error messages */
4907 *arg = option_end;
4908
4909 return ret;
4910}
4911
4912/*
4913 * Allocate a variable for a string constant.
4914 * Return OK or FAIL.
4915 */
4916 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004917get_string_tv(arg, rettv, evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004918 char_u **arg;
Bram Moolenaar33570922005-01-25 22:26:29 +00004919 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004920 int evaluate;
4921{
4922 char_u *p;
4923 char_u *name;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004924 int extra = 0;
4925
4926 /*
4927 * Find the end of the string, skipping backslashed characters.
4928 */
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00004929 for (p = *arg + 1; *p != NUL && *p != '"'; mb_ptr_adv(p))
Bram Moolenaar071d4272004-06-13 20:20:40 +00004930 {
4931 if (*p == '\\' && p[1] != NUL)
4932 {
4933 ++p;
4934 /* A "\<x>" form occupies at least 4 characters, and produces up
4935 * to 6 characters: reserve space for 2 extra */
4936 if (*p == '<')
4937 extra += 2;
4938 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004939 }
4940
4941 if (*p != '"')
4942 {
4943 EMSG2(_("E114: Missing quote: %s"), *arg);
4944 return FAIL;
4945 }
4946
4947 /* If only parsing, set *arg and return here */
4948 if (!evaluate)
4949 {
4950 *arg = p + 1;
4951 return OK;
4952 }
4953
4954 /*
4955 * Copy the string into allocated memory, handling backslashed
4956 * characters.
4957 */
4958 name = alloc((unsigned)(p - *arg + extra));
4959 if (name == NULL)
4960 return FAIL;
Bram Moolenaar8c711452005-01-14 21:53:12 +00004961 rettv->v_type = VAR_STRING;
4962 rettv->vval.v_string = name;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004963
Bram Moolenaar8c711452005-01-14 21:53:12 +00004964 for (p = *arg + 1; *p != NUL && *p != '"'; )
Bram Moolenaar071d4272004-06-13 20:20:40 +00004965 {
4966 if (*p == '\\')
4967 {
4968 switch (*++p)
4969 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00004970 case 'b': *name++ = BS; ++p; break;
4971 case 'e': *name++ = ESC; ++p; break;
4972 case 'f': *name++ = FF; ++p; break;
4973 case 'n': *name++ = NL; ++p; break;
4974 case 'r': *name++ = CAR; ++p; break;
4975 case 't': *name++ = TAB; ++p; break;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004976
4977 case 'X': /* hex: "\x1", "\x12" */
4978 case 'x':
4979 case 'u': /* Unicode: "\u0023" */
4980 case 'U':
4981 if (vim_isxdigit(p[1]))
4982 {
4983 int n, nr;
4984 int c = toupper(*p);
4985
4986 if (c == 'X')
4987 n = 2;
4988 else
4989 n = 4;
4990 nr = 0;
4991 while (--n >= 0 && vim_isxdigit(p[1]))
4992 {
4993 ++p;
4994 nr = (nr << 4) + hex2nr(*p);
4995 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00004996 ++p;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004997#ifdef FEAT_MBYTE
4998 /* For "\u" store the number according to
4999 * 'encoding'. */
5000 if (c != 'X')
Bram Moolenaar8c711452005-01-14 21:53:12 +00005001 name += (*mb_char2bytes)(nr, name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005002 else
5003#endif
Bram Moolenaar8c711452005-01-14 21:53:12 +00005004 *name++ = nr;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005005 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00005006 break;
5007
5008 /* octal: "\1", "\12", "\123" */
5009 case '0':
5010 case '1':
5011 case '2':
5012 case '3':
5013 case '4':
5014 case '5':
5015 case '6':
Bram Moolenaar8c711452005-01-14 21:53:12 +00005016 case '7': *name = *p++ - '0';
5017 if (*p >= '0' && *p <= '7')
Bram Moolenaar071d4272004-06-13 20:20:40 +00005018 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00005019 *name = (*name << 3) + *p++ - '0';
5020 if (*p >= '0' && *p <= '7')
5021 *name = (*name << 3) + *p++ - '0';
Bram Moolenaar071d4272004-06-13 20:20:40 +00005022 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00005023 ++name;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005024 break;
5025
5026 /* Special key, e.g.: "\<C-W>" */
Bram Moolenaar8c711452005-01-14 21:53:12 +00005027 case '<': extra = trans_special(&p, name, TRUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005028 if (extra != 0)
5029 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00005030 name += extra;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005031 break;
5032 }
5033 /* FALLTHROUGH */
5034
Bram Moolenaar8c711452005-01-14 21:53:12 +00005035 default: MB_COPY_CHAR(p, name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005036 break;
5037 }
5038 }
5039 else
Bram Moolenaar8c711452005-01-14 21:53:12 +00005040 MB_COPY_CHAR(p, name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005041
Bram Moolenaar071d4272004-06-13 20:20:40 +00005042 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00005043 *name = NUL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005044 *arg = p + 1;
5045
Bram Moolenaar071d4272004-06-13 20:20:40 +00005046 return OK;
5047}
5048
5049/*
Bram Moolenaar8c711452005-01-14 21:53:12 +00005050 * Allocate a variable for a 'str''ing' constant.
Bram Moolenaar071d4272004-06-13 20:20:40 +00005051 * Return OK or FAIL.
5052 */
5053 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005054get_lit_string_tv(arg, rettv, evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005055 char_u **arg;
Bram Moolenaar33570922005-01-25 22:26:29 +00005056 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005057 int evaluate;
5058{
5059 char_u *p;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005060 char_u *str;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005061 int reduce = 0;
5062
5063 /*
Bram Moolenaar8c711452005-01-14 21:53:12 +00005064 * Find the end of the string, skipping ''.
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005065 */
5066 for (p = *arg + 1; *p != NUL; mb_ptr_adv(p))
5067 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00005068 if (*p == '\'')
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005069 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00005070 if (p[1] != '\'')
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005071 break;
5072 ++reduce;
5073 ++p;
5074 }
5075 }
5076
Bram Moolenaar8c711452005-01-14 21:53:12 +00005077 if (*p != '\'')
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005078 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00005079 EMSG2(_("E115: Missing quote: %s"), *arg);
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005080 return FAIL;
5081 }
5082
Bram Moolenaar8c711452005-01-14 21:53:12 +00005083 /* If only parsing return after setting "*arg" */
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005084 if (!evaluate)
5085 {
5086 *arg = p + 1;
5087 return OK;
5088 }
5089
5090 /*
Bram Moolenaar8c711452005-01-14 21:53:12 +00005091 * Copy the string into allocated memory, handling '' to ' reduction.
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005092 */
5093 str = alloc((unsigned)((p - *arg) - reduce));
5094 if (str == NULL)
5095 return FAIL;
Bram Moolenaar8c711452005-01-14 21:53:12 +00005096 rettv->v_type = VAR_STRING;
5097 rettv->vval.v_string = str;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005098
Bram Moolenaar8c711452005-01-14 21:53:12 +00005099 for (p = *arg + 1; *p != NUL; )
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005100 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00005101 if (*p == '\'')
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005102 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00005103 if (p[1] != '\'')
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005104 break;
5105 ++p;
5106 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00005107 MB_COPY_CHAR(p, str);
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005108 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00005109 *str = NUL;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005110 *arg = p + 1;
5111
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005112 return OK;
5113}
5114
5115/*
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005116 * Allocate a variable for a List and fill it from "*arg".
5117 * Return OK or FAIL.
5118 */
5119 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005120get_list_tv(arg, rettv, evaluate)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005121 char_u **arg;
Bram Moolenaar33570922005-01-25 22:26:29 +00005122 typval_T *rettv;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005123 int evaluate;
5124{
Bram Moolenaar33570922005-01-25 22:26:29 +00005125 list_T *l = NULL;
5126 typval_T tv;
5127 listitem_T *item;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005128
5129 if (evaluate)
5130 {
5131 l = list_alloc();
5132 if (l == NULL)
5133 return FAIL;
5134 }
5135
5136 *arg = skipwhite(*arg + 1);
5137 while (**arg != ']' && **arg != NUL)
5138 {
5139 if (eval1(arg, &tv, evaluate) == FAIL) /* recursive! */
5140 goto failret;
5141 if (evaluate)
5142 {
5143 item = listitem_alloc();
5144 if (item != NULL)
5145 {
5146 item->li_tv = tv;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00005147 item->li_tv.v_lock = 0;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005148 list_append(l, item);
5149 }
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005150 else
5151 clear_tv(&tv);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005152 }
5153
5154 if (**arg == ']')
5155 break;
5156 if (**arg != ',')
5157 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00005158 EMSG2(_("E696: Missing comma in List: %s"), *arg);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005159 goto failret;
5160 }
5161 *arg = skipwhite(*arg + 1);
5162 }
5163
5164 if (**arg != ']')
5165 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00005166 EMSG2(_("E697: Missing end of List ']': %s"), *arg);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005167failret:
5168 if (evaluate)
5169 list_free(l);
5170 return FAIL;
5171 }
5172
5173 *arg = skipwhite(*arg + 1);
5174 if (evaluate)
5175 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005176 rettv->v_type = VAR_LIST;
5177 rettv->vval.v_list = l;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005178 ++l->lv_refcount;
5179 }
5180
5181 return OK;
5182}
5183
5184/*
5185 * Allocate an empty header for a list.
Bram Moolenaard43b6cf2005-09-09 19:53:42 +00005186 * Caller should take care of the reference count.
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005187 */
Bram Moolenaar33570922005-01-25 22:26:29 +00005188 static list_T *
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005189list_alloc()
5190{
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00005191 list_T *l;
5192
5193 l = (list_T *)alloc_clear(sizeof(list_T));
5194 if (l != NULL)
5195 {
5196 /* Prepend the list to the list of lists for garbage collection. */
5197 if (first_list != NULL)
5198 first_list->lv_used_prev = l;
5199 l->lv_used_prev = NULL;
5200 l->lv_used_next = first_list;
5201 first_list = l;
5202 }
5203 return l;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005204}
5205
5206/*
5207 * Unreference a list: decrement the reference count and free it when it
5208 * becomes zero.
5209 */
Bram Moolenaar24bbcfe2005-06-28 23:32:02 +00005210 void
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005211list_unref(l)
Bram Moolenaar33570922005-01-25 22:26:29 +00005212 list_T *l;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005213{
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00005214 if (l != NULL && l->lv_refcount != DEL_REFCOUNT && --l->lv_refcount <= 0)
5215 list_free(l);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005216}
5217
5218/*
5219 * Free a list, including all items it points to.
5220 * Ignores the reference count.
5221 */
5222 static void
5223list_free(l)
Bram Moolenaar33570922005-01-25 22:26:29 +00005224 list_T *l;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005225{
Bram Moolenaar33570922005-01-25 22:26:29 +00005226 listitem_T *item;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005227
Bram Moolenaard9fba312005-06-26 22:34:35 +00005228 /* Avoid that recursive reference to the list frees us again. */
5229 l->lv_refcount = DEL_REFCOUNT;
5230
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00005231 /* Remove the list from the list of lists for garbage collection. */
5232 if (l->lv_used_prev == NULL)
5233 first_list = l->lv_used_next;
5234 else
5235 l->lv_used_prev->lv_used_next = l->lv_used_next;
5236 if (l->lv_used_next != NULL)
5237 l->lv_used_next->lv_used_prev = l->lv_used_prev;
5238
Bram Moolenaard9fba312005-06-26 22:34:35 +00005239 for (item = l->lv_first; item != NULL; item = l->lv_first)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005240 {
Bram Moolenaard9fba312005-06-26 22:34:35 +00005241 /* Remove the item before deleting it. */
5242 l->lv_first = item->li_next;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005243 listitem_free(item);
5244 }
5245 vim_free(l);
5246}
5247
5248/*
5249 * Allocate a list item.
5250 */
Bram Moolenaar33570922005-01-25 22:26:29 +00005251 static listitem_T *
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005252listitem_alloc()
5253{
Bram Moolenaar33570922005-01-25 22:26:29 +00005254 return (listitem_T *)alloc(sizeof(listitem_T));
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005255}
5256
5257/*
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00005258 * Free a list item. Also clears the value. Does not notify watchers.
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005259 */
5260 static void
5261listitem_free(item)
Bram Moolenaar33570922005-01-25 22:26:29 +00005262 listitem_T *item;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005263{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005264 clear_tv(&item->li_tv);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005265 vim_free(item);
5266}
5267
5268/*
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00005269 * Remove a list item from a List and free it. Also clears the value.
5270 */
5271 static void
5272listitem_remove(l, item)
Bram Moolenaar33570922005-01-25 22:26:29 +00005273 list_T *l;
5274 listitem_T *item;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00005275{
5276 list_remove(l, item, item);
5277 listitem_free(item);
5278}
5279
5280/*
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005281 * Get the number of items in a list.
5282 */
5283 static long
5284list_len(l)
Bram Moolenaar33570922005-01-25 22:26:29 +00005285 list_T *l;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005286{
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005287 if (l == NULL)
5288 return 0L;
Bram Moolenaar758711c2005-02-02 23:11:38 +00005289 return l->lv_len;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005290}
5291
5292/*
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005293 * Return TRUE when two lists have exactly the same values.
5294 */
5295 static int
5296list_equal(l1, l2, ic)
Bram Moolenaar33570922005-01-25 22:26:29 +00005297 list_T *l1;
5298 list_T *l2;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005299 int ic; /* ignore case for strings */
5300{
Bram Moolenaar33570922005-01-25 22:26:29 +00005301 listitem_T *item1, *item2;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005302
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00005303 if (list_len(l1) != list_len(l2))
5304 return FALSE;
5305
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005306 for (item1 = l1->lv_first, item2 = l2->lv_first;
5307 item1 != NULL && item2 != NULL;
5308 item1 = item1->li_next, item2 = item2->li_next)
5309 if (!tv_equal(&item1->li_tv, &item2->li_tv, ic))
5310 return FALSE;
5311 return item1 == NULL && item2 == NULL;
5312}
5313
5314/*
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00005315 * Return TRUE when two dictionaries have exactly the same key/values.
5316 */
5317 static int
5318dict_equal(d1, d2, ic)
Bram Moolenaar33570922005-01-25 22:26:29 +00005319 dict_T *d1;
5320 dict_T *d2;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00005321 int ic; /* ignore case for strings */
5322{
Bram Moolenaar33570922005-01-25 22:26:29 +00005323 hashitem_T *hi;
5324 dictitem_T *item2;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005325 int todo;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00005326
5327 if (dict_len(d1) != dict_len(d2))
5328 return FALSE;
5329
Bram Moolenaar33570922005-01-25 22:26:29 +00005330 todo = d1->dv_hashtab.ht_used;
5331 for (hi = d1->dv_hashtab.ht_array; todo > 0; ++hi)
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00005332 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005333 if (!HASHITEM_EMPTY(hi))
5334 {
5335 item2 = dict_find(d2, hi->hi_key, -1);
5336 if (item2 == NULL)
5337 return FALSE;
5338 if (!tv_equal(&HI2DI(hi)->di_tv, &item2->di_tv, ic))
5339 return FALSE;
5340 --todo;
5341 }
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00005342 }
5343 return TRUE;
5344}
5345
5346/*
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005347 * Return TRUE if "tv1" and "tv2" have the same value.
Bram Moolenaar7d1f5db2005-07-03 21:39:27 +00005348 * Compares the items just like "==" would compare them, but strings and
5349 * numbers are different.
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005350 */
5351 static int
5352tv_equal(tv1, tv2, ic)
Bram Moolenaar33570922005-01-25 22:26:29 +00005353 typval_T *tv1;
5354 typval_T *tv2;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005355 int ic; /* ignore case */
5356{
5357 char_u buf1[NUMBUFLEN], buf2[NUMBUFLEN];
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00005358 char_u *s1, *s2;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005359
Bram Moolenaar7d1f5db2005-07-03 21:39:27 +00005360 if (tv1->v_type != tv2->v_type)
5361 return FALSE;
5362
5363 switch (tv1->v_type)
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005364 {
Bram Moolenaar7d1f5db2005-07-03 21:39:27 +00005365 case VAR_LIST:
5366 /* recursive! */
5367 return list_equal(tv1->vval.v_list, tv2->vval.v_list, ic);
5368
5369 case VAR_DICT:
5370 /* recursive! */
5371 return dict_equal(tv1->vval.v_dict, tv2->vval.v_dict, ic);
5372
5373 case VAR_FUNC:
5374 return (tv1->vval.v_string != NULL
5375 && tv2->vval.v_string != NULL
5376 && STRCMP(tv1->vval.v_string, tv2->vval.v_string) == 0);
5377
5378 case VAR_NUMBER:
5379 return tv1->vval.v_number == tv2->vval.v_number;
5380
5381 case VAR_STRING:
5382 s1 = get_tv_string_buf(tv1, buf1);
5383 s2 = get_tv_string_buf(tv2, buf2);
5384 return ((ic ? MB_STRICMP(s1, s2) : STRCMP(s1, s2)) == 0);
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005385 }
Bram Moolenaar7d1f5db2005-07-03 21:39:27 +00005386
5387 EMSG2(_(e_intern2), "tv_equal()");
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005388 return TRUE;
5389}
5390
5391/*
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005392 * Locate item with index "n" in list "l" and return it.
5393 * A negative index is counted from the end; -1 is the last item.
5394 * Returns NULL when "n" is out of range.
5395 */
Bram Moolenaar33570922005-01-25 22:26:29 +00005396 static listitem_T *
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005397list_find(l, n)
Bram Moolenaar33570922005-01-25 22:26:29 +00005398 list_T *l;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005399 long n;
5400{
Bram Moolenaar33570922005-01-25 22:26:29 +00005401 listitem_T *item;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005402 long idx;
5403
5404 if (l == NULL)
5405 return NULL;
Bram Moolenaar758711c2005-02-02 23:11:38 +00005406
5407 /* Negative index is relative to the end. */
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005408 if (n < 0)
Bram Moolenaar758711c2005-02-02 23:11:38 +00005409 n = l->lv_len + n;
5410
5411 /* Check for index out of range. */
5412 if (n < 0 || n >= l->lv_len)
5413 return NULL;
5414
5415 /* When there is a cached index may start search from there. */
5416 if (l->lv_idx_item != NULL)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005417 {
Bram Moolenaar758711c2005-02-02 23:11:38 +00005418 if (n < l->lv_idx / 2)
5419 {
5420 /* closest to the start of the list */
5421 item = l->lv_first;
5422 idx = 0;
5423 }
5424 else if (n > (l->lv_idx + l->lv_len) / 2)
5425 {
5426 /* closest to the end of the list */
5427 item = l->lv_last;
5428 idx = l->lv_len - 1;
5429 }
5430 else
5431 {
5432 /* closest to the cached index */
5433 item = l->lv_idx_item;
5434 idx = l->lv_idx;
5435 }
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005436 }
5437 else
5438 {
Bram Moolenaar758711c2005-02-02 23:11:38 +00005439 if (n < l->lv_len / 2)
5440 {
5441 /* closest to the start of the list */
5442 item = l->lv_first;
5443 idx = 0;
5444 }
5445 else
5446 {
5447 /* closest to the end of the list */
5448 item = l->lv_last;
5449 idx = l->lv_len - 1;
5450 }
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005451 }
Bram Moolenaar758711c2005-02-02 23:11:38 +00005452
5453 while (n > idx)
5454 {
5455 /* search forward */
5456 item = item->li_next;
5457 ++idx;
5458 }
5459 while (n < idx)
5460 {
5461 /* search backward */
5462 item = item->li_prev;
5463 --idx;
5464 }
5465
5466 /* cache the used index */
5467 l->lv_idx = idx;
5468 l->lv_idx_item = item;
5469
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005470 return item;
5471}
5472
5473/*
Bram Moolenaar6cc16192005-01-08 21:49:45 +00005474 * Locate "item" list "l" and return its index.
5475 * Returns -1 when "item" is not in the list.
5476 */
5477 static long
5478list_idx_of_item(l, item)
Bram Moolenaar33570922005-01-25 22:26:29 +00005479 list_T *l;
5480 listitem_T *item;
Bram Moolenaar6cc16192005-01-08 21:49:45 +00005481{
5482 long idx = 0;
Bram Moolenaar33570922005-01-25 22:26:29 +00005483 listitem_T *li;
Bram Moolenaar6cc16192005-01-08 21:49:45 +00005484
5485 if (l == NULL)
5486 return -1;
5487 idx = 0;
5488 for (li = l->lv_first; li != NULL && li != item; li = li->li_next)
5489 ++idx;
5490 if (li == NULL)
5491 return -1;
Bram Moolenaar75c50c42005-06-04 22:06:24 +00005492 return idx;
Bram Moolenaar6cc16192005-01-08 21:49:45 +00005493}
5494
5495/*
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005496 * Append item "item" to the end of list "l".
5497 */
5498 static void
5499list_append(l, item)
Bram Moolenaar33570922005-01-25 22:26:29 +00005500 list_T *l;
5501 listitem_T *item;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005502{
5503 if (l->lv_last == NULL)
5504 {
5505 /* empty list */
5506 l->lv_first = item;
5507 l->lv_last = item;
5508 item->li_prev = NULL;
5509 }
5510 else
5511 {
5512 l->lv_last->li_next = item;
5513 item->li_prev = l->lv_last;
5514 l->lv_last = item;
5515 }
Bram Moolenaar758711c2005-02-02 23:11:38 +00005516 ++l->lv_len;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005517 item->li_next = NULL;
5518}
5519
5520/*
Bram Moolenaar33570922005-01-25 22:26:29 +00005521 * Append typval_T "tv" to the end of list "l".
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005522 * Return FAIL when out of memory.
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005523 */
5524 static int
5525list_append_tv(l, tv)
Bram Moolenaar33570922005-01-25 22:26:29 +00005526 list_T *l;
5527 typval_T *tv;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005528{
Bram Moolenaar05159a02005-02-26 23:04:13 +00005529 listitem_T *li = listitem_alloc();
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005530
Bram Moolenaar05159a02005-02-26 23:04:13 +00005531 if (li == NULL)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005532 return FAIL;
Bram Moolenaar05159a02005-02-26 23:04:13 +00005533 copy_tv(tv, &li->li_tv);
5534 list_append(l, li);
5535 return OK;
5536}
5537
5538/*
Bram Moolenaar2641f772005-03-25 21:58:17 +00005539 * Add a dictionary to a list. Used by getqflist().
Bram Moolenaar05159a02005-02-26 23:04:13 +00005540 * Return FAIL when out of memory.
5541 */
5542 int
5543list_append_dict(list, dict)
5544 list_T *list;
5545 dict_T *dict;
5546{
5547 listitem_T *li = listitem_alloc();
5548
5549 if (li == NULL)
5550 return FAIL;
5551 li->li_tv.v_type = VAR_DICT;
5552 li->li_tv.v_lock = 0;
5553 li->li_tv.vval.v_dict = dict;
5554 list_append(list, li);
5555 ++dict->dv_refcount;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005556 return OK;
5557}
5558
5559/*
Bram Moolenaard43b6cf2005-09-09 19:53:42 +00005560 * Make a copy of "str" and append it as an item to list "l".
Bram Moolenaar4463f292005-09-25 22:20:24 +00005561 * When "len" >= 0 use "str[len]".
Bram Moolenaard43b6cf2005-09-09 19:53:42 +00005562 * Returns FAIL when out of memory.
5563 */
5564 static int
Bram Moolenaar4463f292005-09-25 22:20:24 +00005565list_append_string(l, str, len)
Bram Moolenaard43b6cf2005-09-09 19:53:42 +00005566 list_T *l;
5567 char_u *str;
Bram Moolenaar4463f292005-09-25 22:20:24 +00005568 int len;
Bram Moolenaard43b6cf2005-09-09 19:53:42 +00005569{
5570 listitem_T *li = listitem_alloc();
5571
5572 if (li == NULL)
5573 return FAIL;
5574 list_append(l, li);
5575 li->li_tv.v_type = VAR_STRING;
5576 li->li_tv.v_lock = 0;
Bram Moolenaar482aaeb2005-09-29 18:26:07 +00005577 if ((li->li_tv.vval.v_string = (len >= 0 ? vim_strnsave(str, len)
5578 : vim_strsave(str))) == NULL)
Bram Moolenaard43b6cf2005-09-09 19:53:42 +00005579 return FAIL;
5580 return OK;
5581}
5582
5583/*
Bram Moolenaar4463f292005-09-25 22:20:24 +00005584 * Append "n" to list "l".
5585 * Returns FAIL when out of memory.
5586 */
5587 static int
5588list_append_number(l, n)
5589 list_T *l;
5590 varnumber_T n;
5591{
5592 listitem_T *li;
5593
5594 li = listitem_alloc();
5595 if (li == NULL)
5596 return FAIL;
5597 li->li_tv.v_type = VAR_NUMBER;
5598 li->li_tv.v_lock = 0;
5599 li->li_tv.vval.v_number = n;
5600 list_append(l, li);
5601 return OK;
5602}
5603
5604/*
Bram Moolenaar33570922005-01-25 22:26:29 +00005605 * Insert typval_T "tv" in list "l" before "item".
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005606 * If "item" is NULL append at the end.
5607 * Return FAIL when out of memory.
5608 */
5609 static int
5610list_insert_tv(l, tv, item)
Bram Moolenaar33570922005-01-25 22:26:29 +00005611 list_T *l;
5612 typval_T *tv;
5613 listitem_T *item;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005614{
Bram Moolenaar33570922005-01-25 22:26:29 +00005615 listitem_T *ni = listitem_alloc();
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005616
5617 if (ni == NULL)
5618 return FAIL;
5619 copy_tv(tv, &ni->li_tv);
5620 if (item == NULL)
5621 /* Append new item at end of list. */
5622 list_append(l, ni);
5623 else
5624 {
5625 /* Insert new item before existing item. */
5626 ni->li_prev = item->li_prev;
5627 ni->li_next = item;
5628 if (item->li_prev == NULL)
Bram Moolenaar758711c2005-02-02 23:11:38 +00005629 {
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005630 l->lv_first = ni;
Bram Moolenaar758711c2005-02-02 23:11:38 +00005631 ++l->lv_idx;
5632 }
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005633 else
Bram Moolenaar758711c2005-02-02 23:11:38 +00005634 {
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005635 item->li_prev->li_next = ni;
Bram Moolenaar758711c2005-02-02 23:11:38 +00005636 l->lv_idx_item = NULL;
5637 }
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005638 item->li_prev = ni;
Bram Moolenaar758711c2005-02-02 23:11:38 +00005639 ++l->lv_len;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005640 }
5641 return OK;
5642}
5643
5644/*
5645 * Extend "l1" with "l2".
5646 * If "bef" is NULL append at the end, otherwise insert before this item.
5647 * Returns FAIL when out of memory.
5648 */
5649 static int
5650list_extend(l1, l2, bef)
Bram Moolenaar33570922005-01-25 22:26:29 +00005651 list_T *l1;
5652 list_T *l2;
5653 listitem_T *bef;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005654{
Bram Moolenaar33570922005-01-25 22:26:29 +00005655 listitem_T *item;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005656
5657 for (item = l2->lv_first; item != NULL; item = item->li_next)
5658 if (list_insert_tv(l1, &item->li_tv, bef) == FAIL)
5659 return FAIL;
5660 return OK;
5661}
5662
5663/*
5664 * Concatenate lists "l1" and "l2" into a new list, stored in "tv".
5665 * Return FAIL when out of memory.
5666 */
5667 static int
5668list_concat(l1, l2, tv)
Bram Moolenaar33570922005-01-25 22:26:29 +00005669 list_T *l1;
5670 list_T *l2;
5671 typval_T *tv;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005672{
Bram Moolenaar33570922005-01-25 22:26:29 +00005673 list_T *l;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005674
5675 /* make a copy of the first list. */
Bram Moolenaar81bf7082005-02-12 14:31:42 +00005676 l = list_copy(l1, FALSE, 0);
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005677 if (l == NULL)
5678 return FAIL;
5679 tv->v_type = VAR_LIST;
5680 tv->vval.v_list = l;
5681
5682 /* append all items from the second list */
5683 return list_extend(l, l2, NULL);
5684}
5685
5686/*
Bram Moolenaare9a41262005-01-15 22:18:47 +00005687 * Make a copy of list "orig". Shallow if "deep" is FALSE.
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005688 * The refcount of the new list is set to 1.
Bram Moolenaar81bf7082005-02-12 14:31:42 +00005689 * See item_copy() for "copyID".
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005690 * Returns NULL when out of memory.
5691 */
Bram Moolenaar33570922005-01-25 22:26:29 +00005692 static list_T *
Bram Moolenaar81bf7082005-02-12 14:31:42 +00005693list_copy(orig, deep, copyID)
Bram Moolenaar33570922005-01-25 22:26:29 +00005694 list_T *orig;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005695 int deep;
Bram Moolenaar81bf7082005-02-12 14:31:42 +00005696 int copyID;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005697{
Bram Moolenaar33570922005-01-25 22:26:29 +00005698 list_T *copy;
5699 listitem_T *item;
5700 listitem_T *ni;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005701
5702 if (orig == NULL)
5703 return NULL;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005704
5705 copy = list_alloc();
5706 if (copy != NULL)
5707 {
Bram Moolenaar81bf7082005-02-12 14:31:42 +00005708 if (copyID != 0)
5709 {
5710 /* Do this before adding the items, because one of the items may
5711 * refer back to this list. */
5712 orig->lv_copyID = copyID;
5713 orig->lv_copylist = copy;
5714 }
5715 for (item = orig->lv_first; item != NULL && !got_int;
5716 item = item->li_next)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005717 {
5718 ni = listitem_alloc();
5719 if (ni == NULL)
5720 break;
Bram Moolenaare9a41262005-01-15 22:18:47 +00005721 if (deep)
Bram Moolenaar81bf7082005-02-12 14:31:42 +00005722 {
5723 if (item_copy(&item->li_tv, &ni->li_tv, deep, copyID) == FAIL)
5724 {
5725 vim_free(ni);
5726 break;
5727 }
5728 }
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005729 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005730 copy_tv(&item->li_tv, &ni->li_tv);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005731 list_append(copy, ni);
5732 }
5733 ++copy->lv_refcount;
Bram Moolenaar81bf7082005-02-12 14:31:42 +00005734 if (item != NULL)
5735 {
5736 list_unref(copy);
5737 copy = NULL;
5738 }
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005739 }
5740
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005741 return copy;
5742}
5743
5744/*
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005745 * Remove items "item" to "item2" from list "l".
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00005746 * Does not free the listitem or the value!
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005747 */
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005748 static void
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00005749list_remove(l, item, item2)
Bram Moolenaar33570922005-01-25 22:26:29 +00005750 list_T *l;
5751 listitem_T *item;
5752 listitem_T *item2;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005753{
Bram Moolenaar33570922005-01-25 22:26:29 +00005754 listitem_T *ip;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005755
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005756 /* notify watchers */
5757 for (ip = item; ip != NULL; ip = ip->li_next)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005758 {
Bram Moolenaar758711c2005-02-02 23:11:38 +00005759 --l->lv_len;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005760 list_fix_watch(l, ip);
5761 if (ip == item2)
5762 break;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005763 }
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005764
5765 if (item2->li_next == NULL)
5766 l->lv_last = item->li_prev;
5767 else
5768 item2->li_next->li_prev = item->li_prev;
5769 if (item->li_prev == NULL)
5770 l->lv_first = item2->li_next;
5771 else
5772 item->li_prev->li_next = item2->li_next;
Bram Moolenaar758711c2005-02-02 23:11:38 +00005773 l->lv_idx_item = NULL;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005774}
5775
5776/*
5777 * Return an allocated string with the string representation of a list.
5778 * May return NULL.
5779 */
5780 static char_u *
5781list2string(tv)
Bram Moolenaar33570922005-01-25 22:26:29 +00005782 typval_T *tv;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005783{
5784 garray_T ga;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005785
5786 if (tv->vval.v_list == NULL)
5787 return NULL;
5788 ga_init2(&ga, (int)sizeof(char), 80);
5789 ga_append(&ga, '[');
Bram Moolenaar81bf7082005-02-12 14:31:42 +00005790 if (list_join(&ga, tv->vval.v_list, (char_u *)", ", FALSE) == FAIL)
5791 {
5792 vim_free(ga.ga_data);
5793 return NULL;
5794 }
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005795 ga_append(&ga, ']');
5796 ga_append(&ga, NUL);
5797 return (char_u *)ga.ga_data;
5798}
5799
5800/*
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005801 * Join list "l" into a string in "*gap", using separator "sep".
5802 * When "echo" is TRUE use String as echoed, otherwise as inside a List.
Bram Moolenaar81bf7082005-02-12 14:31:42 +00005803 * Return FAIL or OK.
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005804 */
Bram Moolenaar81bf7082005-02-12 14:31:42 +00005805 static int
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005806list_join(gap, l, sep, echo)
5807 garray_T *gap;
Bram Moolenaar33570922005-01-25 22:26:29 +00005808 list_T *l;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005809 char_u *sep;
5810 int echo;
5811{
5812 int first = TRUE;
5813 char_u *tofree;
5814 char_u numbuf[NUMBUFLEN];
Bram Moolenaar33570922005-01-25 22:26:29 +00005815 listitem_T *item;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005816 char_u *s;
5817
Bram Moolenaar81bf7082005-02-12 14:31:42 +00005818 for (item = l->lv_first; item != NULL && !got_int; item = item->li_next)
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005819 {
5820 if (first)
5821 first = FALSE;
5822 else
5823 ga_concat(gap, sep);
5824
5825 if (echo)
5826 s = echo_string(&item->li_tv, &tofree, numbuf);
5827 else
5828 s = tv2string(&item->li_tv, &tofree, numbuf);
5829 if (s != NULL)
5830 ga_concat(gap, s);
5831 vim_free(tofree);
Bram Moolenaar81bf7082005-02-12 14:31:42 +00005832 if (s == NULL)
5833 return FAIL;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005834 }
Bram Moolenaar81bf7082005-02-12 14:31:42 +00005835 return OK;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005836}
5837
5838/*
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00005839 * Garbage collection for lists and dictionaries.
5840 *
5841 * We use reference counts to be able to free most items right away when they
5842 * are no longer used. But for composite items it's possible that it becomes
5843 * unused while the reference count is > 0: When there is a recursive
5844 * reference. Example:
5845 * :let l = [1, 2, 3]
5846 * :let d = {9: l}
5847 * :let l[1] = d
5848 *
5849 * Since this is quite unusual we handle this with garbage collection: every
5850 * once in a while find out which lists and dicts are not referenced from any
5851 * variable.
5852 *
5853 * Here is a good reference text about garbage collection (refers to Python
5854 * but it applies to all reference-counting mechanisms):
5855 * http://python.ca/nas/python/gc/
Bram Moolenaard9fba312005-06-26 22:34:35 +00005856 */
Bram Moolenaard9fba312005-06-26 22:34:35 +00005857
5858/*
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00005859 * Do garbage collection for lists and dicts.
5860 * Return TRUE if some memory was freed.
Bram Moolenaard9fba312005-06-26 22:34:35 +00005861 */
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00005862 int
5863garbage_collect()
Bram Moolenaard9fba312005-06-26 22:34:35 +00005864{
5865 dict_T *dd;
5866 list_T *ll;
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00005867 int copyID = ++current_copyID;
5868 buf_T *buf;
5869 win_T *wp;
5870 int i;
5871 funccall_T *fc;
5872 int did_free = FALSE;
5873
5874 /*
5875 * 1. Go through all accessible variables and mark all lists and dicts
5876 * with copyID.
5877 */
5878 /* script-local variables */
5879 for (i = 1; i <= ga_scripts.ga_len; ++i)
5880 set_ref_in_ht(&SCRIPT_VARS(i), copyID);
5881
5882 /* buffer-local variables */
5883 for (buf = firstbuf; buf != NULL; buf = buf->b_next)
5884 set_ref_in_ht(&buf->b_vars.dv_hashtab, copyID);
5885
5886 /* window-local variables */
5887 FOR_ALL_WINDOWS(wp)
5888 set_ref_in_ht(&wp->w_vars.dv_hashtab, copyID);
5889
5890 /* global variables */
5891 set_ref_in_ht(&globvarht, copyID);
5892
5893 /* function-local variables */
5894 for (fc = current_funccal; fc != NULL; fc = fc->caller)
5895 {
5896 set_ref_in_ht(&fc->l_vars.dv_hashtab, copyID);
5897 set_ref_in_ht(&fc->l_avars.dv_hashtab, copyID);
5898 }
5899
5900 /*
5901 * 2. Go through the list of dicts and free items without the copyID.
5902 */
5903 for (dd = first_dict; dd != NULL; )
5904 if (dd->dv_copyID != copyID)
5905 {
5906 dict_free(dd);
5907 did_free = TRUE;
5908
5909 /* restart, next dict may also have been freed */
5910 dd = first_dict;
5911 }
5912 else
5913 dd = dd->dv_used_next;
5914
5915 /*
5916 * 3. Go through the list of lists and free items without the copyID.
Bram Moolenaar7bb4c6e2005-09-07 21:22:27 +00005917 * But don't free a list that has a watcher (used in a for loop), these
5918 * are not referenced anywhere.
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00005919 */
5920 for (ll = first_list; ll != NULL; )
Bram Moolenaar7bb4c6e2005-09-07 21:22:27 +00005921 if (ll->lv_copyID != copyID && ll->lv_watch == NULL)
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00005922 {
5923 list_free(ll);
5924 did_free = TRUE;
5925
Bram Moolenaar7bb4c6e2005-09-07 21:22:27 +00005926 /* restart, next list may also have been freed */
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00005927 ll = first_list;
5928 }
5929 else
5930 ll = ll->lv_used_next;
5931
5932 return did_free;
5933}
5934
5935/*
5936 * Mark all lists and dicts referenced through hashtab "ht" with "copyID".
5937 */
5938 static void
5939set_ref_in_ht(ht, copyID)
5940 hashtab_T *ht;
5941 int copyID;
5942{
5943 int todo;
5944 hashitem_T *hi;
5945
5946 todo = ht->ht_used;
5947 for (hi = ht->ht_array; todo > 0; ++hi)
5948 if (!HASHITEM_EMPTY(hi))
5949 {
5950 --todo;
5951 set_ref_in_item(&HI2DI(hi)->di_tv, copyID);
5952 }
5953}
5954
5955/*
5956 * Mark all lists and dicts referenced through list "l" with "copyID".
5957 */
5958 static void
5959set_ref_in_list(l, copyID)
5960 list_T *l;
5961 int copyID;
5962{
5963 listitem_T *li;
5964
5965 for (li = l->lv_first; li != NULL; li = li->li_next)
5966 set_ref_in_item(&li->li_tv, copyID);
5967}
5968
5969/*
5970 * Mark all lists and dicts referenced through typval "tv" with "copyID".
5971 */
5972 static void
5973set_ref_in_item(tv, copyID)
5974 typval_T *tv;
5975 int copyID;
5976{
5977 dict_T *dd;
5978 list_T *ll;
Bram Moolenaard9fba312005-06-26 22:34:35 +00005979
5980 switch (tv->v_type)
5981 {
5982 case VAR_DICT:
5983 dd = tv->vval.v_dict;
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00005984 if (dd->dv_copyID != copyID)
Bram Moolenaard9fba312005-06-26 22:34:35 +00005985 {
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00005986 /* Didn't see this dict yet. */
5987 dd->dv_copyID = copyID;
5988 set_ref_in_ht(&dd->dv_hashtab, copyID);
Bram Moolenaard9fba312005-06-26 22:34:35 +00005989 }
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00005990 break;
Bram Moolenaard9fba312005-06-26 22:34:35 +00005991
5992 case VAR_LIST:
5993 ll = tv->vval.v_list;
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00005994 if (ll->lv_copyID != copyID)
Bram Moolenaard9fba312005-06-26 22:34:35 +00005995 {
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00005996 /* Didn't see this list yet. */
5997 ll->lv_copyID = copyID;
5998 set_ref_in_list(ll, copyID);
Bram Moolenaard9fba312005-06-26 22:34:35 +00005999 }
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00006000 break;
Bram Moolenaard9fba312005-06-26 22:34:35 +00006001 }
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00006002 return;
Bram Moolenaard9fba312005-06-26 22:34:35 +00006003}
6004
6005/*
Bram Moolenaar8c711452005-01-14 21:53:12 +00006006 * Allocate an empty header for a dictionary.
6007 */
Bram Moolenaar05159a02005-02-26 23:04:13 +00006008 dict_T *
Bram Moolenaar8c711452005-01-14 21:53:12 +00006009dict_alloc()
6010{
Bram Moolenaar33570922005-01-25 22:26:29 +00006011 dict_T *d;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00006012
Bram Moolenaar33570922005-01-25 22:26:29 +00006013 d = (dict_T *)alloc(sizeof(dict_T));
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00006014 if (d != NULL)
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00006015 {
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00006016 /* Add the list to the hashtable for garbage collection. */
6017 if (first_dict != NULL)
6018 first_dict->dv_used_prev = d;
6019 d->dv_used_next = first_dict;
6020 d->dv_used_prev = NULL;
6021
Bram Moolenaar33570922005-01-25 22:26:29 +00006022 hash_init(&d->dv_hashtab);
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00006023 d->dv_lock = 0;
6024 d->dv_refcount = 0;
Bram Moolenaar81bf7082005-02-12 14:31:42 +00006025 d->dv_copyID = 0;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00006026 }
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00006027 return d;
Bram Moolenaar8c711452005-01-14 21:53:12 +00006028}
6029
6030/*
6031 * Unreference a Dictionary: decrement the reference count and free it when it
6032 * becomes zero.
6033 */
6034 static void
6035dict_unref(d)
Bram Moolenaar33570922005-01-25 22:26:29 +00006036 dict_T *d;
Bram Moolenaar8c711452005-01-14 21:53:12 +00006037{
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00006038 if (d != NULL && d->dv_refcount != DEL_REFCOUNT && --d->dv_refcount <= 0)
6039 dict_free(d);
Bram Moolenaar8c711452005-01-14 21:53:12 +00006040}
6041
6042/*
6043 * Free a Dictionary, including all items it contains.
6044 * Ignores the reference count.
6045 */
6046 static void
6047dict_free(d)
Bram Moolenaar33570922005-01-25 22:26:29 +00006048 dict_T *d;
Bram Moolenaar8c711452005-01-14 21:53:12 +00006049{
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00006050 int todo;
Bram Moolenaar33570922005-01-25 22:26:29 +00006051 hashitem_T *hi;
Bram Moolenaard9fba312005-06-26 22:34:35 +00006052 dictitem_T *di;
Bram Moolenaar8c711452005-01-14 21:53:12 +00006053
Bram Moolenaard9fba312005-06-26 22:34:35 +00006054 /* Avoid that recursive reference to the dict frees us again. */
6055 d->dv_refcount = DEL_REFCOUNT;
6056
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00006057 /* Remove the dict from the list of dicts for garbage collection. */
6058 if (d->dv_used_prev == NULL)
6059 first_dict = d->dv_used_next;
6060 else
6061 d->dv_used_prev->dv_used_next = d->dv_used_next;
6062 if (d->dv_used_next != NULL)
6063 d->dv_used_next->dv_used_prev = d->dv_used_prev;
6064
6065 /* Lock the hashtab, we don't want it to resize while freeing items. */
Bram Moolenaard9fba312005-06-26 22:34:35 +00006066 hash_lock(&d->dv_hashtab);
Bram Moolenaar33570922005-01-25 22:26:29 +00006067 todo = d->dv_hashtab.ht_used;
6068 for (hi = d->dv_hashtab.ht_array; todo > 0; ++hi)
Bram Moolenaar8c711452005-01-14 21:53:12 +00006069 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00006070 if (!HASHITEM_EMPTY(hi))
6071 {
Bram Moolenaard9fba312005-06-26 22:34:35 +00006072 /* Remove the item before deleting it, just in case there is
6073 * something recursive causing trouble. */
6074 di = HI2DI(hi);
6075 hash_remove(&d->dv_hashtab, hi);
6076 dictitem_free(di);
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00006077 --todo;
6078 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00006079 }
Bram Moolenaar33570922005-01-25 22:26:29 +00006080 hash_clear(&d->dv_hashtab);
Bram Moolenaar8c711452005-01-14 21:53:12 +00006081 vim_free(d);
6082}
6083
6084/*
6085 * Allocate a Dictionary item.
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00006086 * The "key" is copied to the new item.
6087 * Note that the value of the item "di_tv" still needs to be initialized!
6088 * Returns NULL when out of memory.
Bram Moolenaar8c711452005-01-14 21:53:12 +00006089 */
Bram Moolenaar33570922005-01-25 22:26:29 +00006090 static dictitem_T *
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00006091dictitem_alloc(key)
6092 char_u *key;
Bram Moolenaar8c711452005-01-14 21:53:12 +00006093{
Bram Moolenaar33570922005-01-25 22:26:29 +00006094 dictitem_T *di;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00006095
Bram Moolenaar33570922005-01-25 22:26:29 +00006096 di = (dictitem_T *)alloc(sizeof(dictitem_T) + STRLEN(key));
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00006097 if (di != NULL)
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00006098 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00006099 STRCPY(di->di_key, key);
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00006100 di->di_flags = 0;
6101 }
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00006102 return di;
Bram Moolenaar8c711452005-01-14 21:53:12 +00006103}
6104
6105/*
Bram Moolenaare9a41262005-01-15 22:18:47 +00006106 * Make a copy of a Dictionary item.
6107 */
Bram Moolenaar33570922005-01-25 22:26:29 +00006108 static dictitem_T *
Bram Moolenaare9a41262005-01-15 22:18:47 +00006109dictitem_copy(org)
Bram Moolenaar33570922005-01-25 22:26:29 +00006110 dictitem_T *org;
Bram Moolenaare9a41262005-01-15 22:18:47 +00006111{
Bram Moolenaar33570922005-01-25 22:26:29 +00006112 dictitem_T *di;
Bram Moolenaare9a41262005-01-15 22:18:47 +00006113
Bram Moolenaar33570922005-01-25 22:26:29 +00006114 di = (dictitem_T *)alloc(sizeof(dictitem_T) + STRLEN(org->di_key));
Bram Moolenaare9a41262005-01-15 22:18:47 +00006115 if (di != NULL)
6116 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00006117 STRCPY(di->di_key, org->di_key);
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00006118 di->di_flags = 0;
Bram Moolenaare9a41262005-01-15 22:18:47 +00006119 copy_tv(&org->di_tv, &di->di_tv);
6120 }
6121 return di;
6122}
6123
6124/*
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00006125 * Remove item "item" from Dictionary "dict" and free it.
6126 */
6127 static void
6128dictitem_remove(dict, item)
Bram Moolenaar33570922005-01-25 22:26:29 +00006129 dict_T *dict;
6130 dictitem_T *item;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00006131{
Bram Moolenaar33570922005-01-25 22:26:29 +00006132 hashitem_T *hi;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00006133
Bram Moolenaar33570922005-01-25 22:26:29 +00006134 hi = hash_find(&dict->dv_hashtab, item->di_key);
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00006135 if (HASHITEM_EMPTY(hi))
6136 EMSG2(_(e_intern2), "dictitem_remove()");
6137 else
Bram Moolenaar33570922005-01-25 22:26:29 +00006138 hash_remove(&dict->dv_hashtab, hi);
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00006139 dictitem_free(item);
6140}
6141
6142/*
Bram Moolenaar8c711452005-01-14 21:53:12 +00006143 * Free a dict item. Also clears the value.
6144 */
6145 static void
6146dictitem_free(item)
Bram Moolenaar33570922005-01-25 22:26:29 +00006147 dictitem_T *item;
Bram Moolenaar8c711452005-01-14 21:53:12 +00006148{
Bram Moolenaar8c711452005-01-14 21:53:12 +00006149 clear_tv(&item->di_tv);
6150 vim_free(item);
6151}
6152
6153/*
Bram Moolenaare9a41262005-01-15 22:18:47 +00006154 * Make a copy of dict "d". Shallow if "deep" is FALSE.
6155 * The refcount of the new dict is set to 1.
Bram Moolenaar81bf7082005-02-12 14:31:42 +00006156 * See item_copy() for "copyID".
Bram Moolenaare9a41262005-01-15 22:18:47 +00006157 * Returns NULL when out of memory.
6158 */
Bram Moolenaar33570922005-01-25 22:26:29 +00006159 static dict_T *
Bram Moolenaar81bf7082005-02-12 14:31:42 +00006160dict_copy(orig, deep, copyID)
Bram Moolenaar33570922005-01-25 22:26:29 +00006161 dict_T *orig;
Bram Moolenaare9a41262005-01-15 22:18:47 +00006162 int deep;
Bram Moolenaar81bf7082005-02-12 14:31:42 +00006163 int copyID;
Bram Moolenaare9a41262005-01-15 22:18:47 +00006164{
Bram Moolenaar33570922005-01-25 22:26:29 +00006165 dict_T *copy;
6166 dictitem_T *di;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00006167 int todo;
Bram Moolenaar33570922005-01-25 22:26:29 +00006168 hashitem_T *hi;
Bram Moolenaare9a41262005-01-15 22:18:47 +00006169
6170 if (orig == NULL)
6171 return NULL;
6172
6173 copy = dict_alloc();
6174 if (copy != NULL)
6175 {
Bram Moolenaar81bf7082005-02-12 14:31:42 +00006176 if (copyID != 0)
6177 {
6178 orig->dv_copyID = copyID;
6179 orig->dv_copydict = copy;
6180 }
Bram Moolenaar33570922005-01-25 22:26:29 +00006181 todo = orig->dv_hashtab.ht_used;
Bram Moolenaar81bf7082005-02-12 14:31:42 +00006182 for (hi = orig->dv_hashtab.ht_array; todo > 0 && !got_int; ++hi)
Bram Moolenaare9a41262005-01-15 22:18:47 +00006183 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00006184 if (!HASHITEM_EMPTY(hi))
Bram Moolenaare9a41262005-01-15 22:18:47 +00006185 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00006186 --todo;
6187
6188 di = dictitem_alloc(hi->hi_key);
6189 if (di == NULL)
6190 break;
6191 if (deep)
Bram Moolenaar81bf7082005-02-12 14:31:42 +00006192 {
6193 if (item_copy(&HI2DI(hi)->di_tv, &di->di_tv, deep,
6194 copyID) == FAIL)
6195 {
6196 vim_free(di);
6197 break;
6198 }
6199 }
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00006200 else
6201 copy_tv(&HI2DI(hi)->di_tv, &di->di_tv);
6202 if (dict_add(copy, di) == FAIL)
6203 {
6204 dictitem_free(di);
6205 break;
6206 }
Bram Moolenaare9a41262005-01-15 22:18:47 +00006207 }
Bram Moolenaare9a41262005-01-15 22:18:47 +00006208 }
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00006209
Bram Moolenaare9a41262005-01-15 22:18:47 +00006210 ++copy->dv_refcount;
Bram Moolenaar81bf7082005-02-12 14:31:42 +00006211 if (todo > 0)
6212 {
6213 dict_unref(copy);
6214 copy = NULL;
6215 }
Bram Moolenaare9a41262005-01-15 22:18:47 +00006216 }
6217
6218 return copy;
6219}
6220
6221/*
Bram Moolenaar8c711452005-01-14 21:53:12 +00006222 * Add item "item" to Dictionary "d".
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00006223 * Returns FAIL when out of memory and when key already existed.
Bram Moolenaar8c711452005-01-14 21:53:12 +00006224 */
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00006225 static int
Bram Moolenaar8c711452005-01-14 21:53:12 +00006226dict_add(d, item)
Bram Moolenaar33570922005-01-25 22:26:29 +00006227 dict_T *d;
6228 dictitem_T *item;
Bram Moolenaar8c711452005-01-14 21:53:12 +00006229{
Bram Moolenaar33570922005-01-25 22:26:29 +00006230 return hash_add(&d->dv_hashtab, item->di_key);
Bram Moolenaar8c711452005-01-14 21:53:12 +00006231}
6232
Bram Moolenaar8c711452005-01-14 21:53:12 +00006233/*
Bram Moolenaar05159a02005-02-26 23:04:13 +00006234 * Add a number or string entry to dictionary "d".
6235 * When "str" is NULL use number "nr", otherwise use "str".
6236 * Returns FAIL when out of memory and when key already exists.
6237 */
6238 int
6239dict_add_nr_str(d, key, nr, str)
6240 dict_T *d;
6241 char *key;
6242 long nr;
6243 char_u *str;
6244{
6245 dictitem_T *item;
6246
6247 item = dictitem_alloc((char_u *)key);
6248 if (item == NULL)
6249 return FAIL;
6250 item->di_tv.v_lock = 0;
6251 if (str == NULL)
6252 {
6253 item->di_tv.v_type = VAR_NUMBER;
6254 item->di_tv.vval.v_number = nr;
6255 }
6256 else
6257 {
6258 item->di_tv.v_type = VAR_STRING;
6259 item->di_tv.vval.v_string = vim_strsave(str);
6260 }
6261 if (dict_add(d, item) == FAIL)
6262 {
6263 dictitem_free(item);
6264 return FAIL;
6265 }
6266 return OK;
6267}
6268
6269/*
Bram Moolenaare9a41262005-01-15 22:18:47 +00006270 * Get the number of items in a Dictionary.
6271 */
6272 static long
6273dict_len(d)
Bram Moolenaar33570922005-01-25 22:26:29 +00006274 dict_T *d;
Bram Moolenaare9a41262005-01-15 22:18:47 +00006275{
Bram Moolenaare9a41262005-01-15 22:18:47 +00006276 if (d == NULL)
6277 return 0L;
Bram Moolenaar33570922005-01-25 22:26:29 +00006278 return d->dv_hashtab.ht_used;
Bram Moolenaare9a41262005-01-15 22:18:47 +00006279}
6280
6281/*
Bram Moolenaar8c711452005-01-14 21:53:12 +00006282 * Find item "key[len]" in Dictionary "d".
6283 * If "len" is negative use strlen(key).
6284 * Returns NULL when not found.
6285 */
Bram Moolenaar33570922005-01-25 22:26:29 +00006286 static dictitem_T *
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00006287dict_find(d, key, len)
Bram Moolenaar33570922005-01-25 22:26:29 +00006288 dict_T *d;
Bram Moolenaar8c711452005-01-14 21:53:12 +00006289 char_u *key;
6290 int len;
6291{
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00006292#define AKEYLEN 200
6293 char_u buf[AKEYLEN];
6294 char_u *akey;
6295 char_u *tofree = NULL;
Bram Moolenaar33570922005-01-25 22:26:29 +00006296 hashitem_T *hi;
Bram Moolenaar8c711452005-01-14 21:53:12 +00006297
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00006298 if (len < 0)
6299 akey = key;
6300 else if (len >= AKEYLEN)
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00006301 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00006302 tofree = akey = vim_strnsave(key, len);
6303 if (akey == NULL)
6304 return NULL;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00006305 }
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00006306 else
6307 {
6308 /* Avoid a malloc/free by using buf[]. */
Bram Moolenaarce0842a2005-07-18 21:58:11 +00006309 vim_strncpy(buf, key, len);
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00006310 akey = buf;
6311 }
6312
Bram Moolenaar33570922005-01-25 22:26:29 +00006313 hi = hash_find(&d->dv_hashtab, akey);
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00006314 vim_free(tofree);
6315 if (HASHITEM_EMPTY(hi))
6316 return NULL;
6317 return HI2DI(hi);
Bram Moolenaar8c711452005-01-14 21:53:12 +00006318}
6319
6320/*
Bram Moolenaar2641f772005-03-25 21:58:17 +00006321 * Get a string item from a dictionary in allocated memory.
6322 * Returns NULL if the entry doesn't exist or out of memory.
6323 */
6324 char_u *
6325get_dict_string(d, key)
6326 dict_T *d;
6327 char_u *key;
6328{
6329 dictitem_T *di;
6330
6331 di = dict_find(d, key, -1);
6332 if (di == NULL)
6333 return NULL;
6334 return vim_strsave(get_tv_string(&di->di_tv));
6335}
6336
6337/*
6338 * Get a number item from a dictionary.
6339 * Returns 0 if the entry doesn't exist or out of memory.
6340 */
6341 long
6342get_dict_number(d, key)
6343 dict_T *d;
6344 char_u *key;
6345{
6346 dictitem_T *di;
6347
6348 di = dict_find(d, key, -1);
6349 if (di == NULL)
6350 return 0;
6351 return get_tv_number(&di->di_tv);
6352}
6353
6354/*
Bram Moolenaar8c711452005-01-14 21:53:12 +00006355 * Return an allocated string with the string representation of a Dictionary.
6356 * May return NULL.
6357 */
6358 static char_u *
6359dict2string(tv)
Bram Moolenaar33570922005-01-25 22:26:29 +00006360 typval_T *tv;
Bram Moolenaar8c711452005-01-14 21:53:12 +00006361{
6362 garray_T ga;
6363 int first = TRUE;
6364 char_u *tofree;
6365 char_u numbuf[NUMBUFLEN];
Bram Moolenaar33570922005-01-25 22:26:29 +00006366 hashitem_T *hi;
Bram Moolenaar8c711452005-01-14 21:53:12 +00006367 char_u *s;
Bram Moolenaar33570922005-01-25 22:26:29 +00006368 dict_T *d;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00006369 int todo;
Bram Moolenaar8c711452005-01-14 21:53:12 +00006370
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00006371 if ((d = tv->vval.v_dict) == NULL)
Bram Moolenaar8c711452005-01-14 21:53:12 +00006372 return NULL;
6373 ga_init2(&ga, (int)sizeof(char), 80);
6374 ga_append(&ga, '{');
6375
Bram Moolenaar33570922005-01-25 22:26:29 +00006376 todo = d->dv_hashtab.ht_used;
Bram Moolenaar81bf7082005-02-12 14:31:42 +00006377 for (hi = d->dv_hashtab.ht_array; todo > 0 && !got_int; ++hi)
Bram Moolenaar8c711452005-01-14 21:53:12 +00006378 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00006379 if (!HASHITEM_EMPTY(hi))
Bram Moolenaar8c711452005-01-14 21:53:12 +00006380 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00006381 --todo;
6382
6383 if (first)
6384 first = FALSE;
6385 else
6386 ga_concat(&ga, (char_u *)", ");
6387
6388 tofree = string_quote(hi->hi_key, FALSE);
6389 if (tofree != NULL)
6390 {
6391 ga_concat(&ga, tofree);
6392 vim_free(tofree);
6393 }
6394 ga_concat(&ga, (char_u *)": ");
6395 s = tv2string(&HI2DI(hi)->di_tv, &tofree, numbuf);
6396 if (s != NULL)
6397 ga_concat(&ga, s);
Bram Moolenaar8c711452005-01-14 21:53:12 +00006398 vim_free(tofree);
Bram Moolenaar81bf7082005-02-12 14:31:42 +00006399 if (s == NULL)
6400 break;
Bram Moolenaar8c711452005-01-14 21:53:12 +00006401 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00006402 }
Bram Moolenaar81bf7082005-02-12 14:31:42 +00006403 if (todo > 0)
6404 {
6405 vim_free(ga.ga_data);
6406 return NULL;
6407 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00006408
6409 ga_append(&ga, '}');
6410 ga_append(&ga, NUL);
6411 return (char_u *)ga.ga_data;
6412}
6413
6414/*
6415 * Allocate a variable for a Dictionary and fill it from "*arg".
6416 * Return OK or FAIL. Returns NOTDONE for {expr}.
6417 */
6418 static int
6419get_dict_tv(arg, rettv, evaluate)
6420 char_u **arg;
Bram Moolenaar33570922005-01-25 22:26:29 +00006421 typval_T *rettv;
Bram Moolenaar8c711452005-01-14 21:53:12 +00006422 int evaluate;
6423{
Bram Moolenaar33570922005-01-25 22:26:29 +00006424 dict_T *d = NULL;
6425 typval_T tvkey;
6426 typval_T tv;
Bram Moolenaar8c711452005-01-14 21:53:12 +00006427 char_u *key;
Bram Moolenaar33570922005-01-25 22:26:29 +00006428 dictitem_T *item;
Bram Moolenaar8c711452005-01-14 21:53:12 +00006429 char_u *start = skipwhite(*arg + 1);
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00006430 char_u buf[NUMBUFLEN];
Bram Moolenaar8c711452005-01-14 21:53:12 +00006431
6432 /*
6433 * First check if it's not a curly-braces thing: {expr}.
6434 * Must do this without evaluating, otherwise a function may be called
6435 * twice. Unfortunately this means we need to call eval1() twice for the
6436 * first item.
Bram Moolenaare9a41262005-01-15 22:18:47 +00006437 * But {} is an empty Dictionary.
Bram Moolenaar8c711452005-01-14 21:53:12 +00006438 */
Bram Moolenaare9a41262005-01-15 22:18:47 +00006439 if (*start != '}')
6440 {
6441 if (eval1(&start, &tv, FALSE) == FAIL) /* recursive! */
6442 return FAIL;
6443 if (*start == '}')
6444 return NOTDONE;
6445 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00006446
6447 if (evaluate)
6448 {
6449 d = dict_alloc();
6450 if (d == NULL)
6451 return FAIL;
6452 }
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00006453 tvkey.v_type = VAR_UNKNOWN;
6454 tv.v_type = VAR_UNKNOWN;
Bram Moolenaar8c711452005-01-14 21:53:12 +00006455
6456 *arg = skipwhite(*arg + 1);
6457 while (**arg != '}' && **arg != NUL)
6458 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00006459 if (eval1(arg, &tvkey, evaluate) == FAIL) /* recursive! */
Bram Moolenaar8c711452005-01-14 21:53:12 +00006460 goto failret;
6461 if (**arg != ':')
6462 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00006463 EMSG2(_("E720: Missing colon in Dictionary: %s"), *arg);
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00006464 clear_tv(&tvkey);
Bram Moolenaar8c711452005-01-14 21:53:12 +00006465 goto failret;
6466 }
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00006467 key = get_tv_string_buf_chk(&tvkey, buf);
6468 if (key == NULL || *key == NUL)
Bram Moolenaar8c711452005-01-14 21:53:12 +00006469 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00006470 /* "key" is NULL when get_tv_string_buf_chk() gave an errmsg */
6471 if (key != NULL)
6472 EMSG(_(e_emptykey));
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00006473 clear_tv(&tvkey);
Bram Moolenaar8c711452005-01-14 21:53:12 +00006474 goto failret;
6475 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00006476
6477 *arg = skipwhite(*arg + 1);
6478 if (eval1(arg, &tv, evaluate) == FAIL) /* recursive! */
6479 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00006480 clear_tv(&tvkey);
Bram Moolenaar8c711452005-01-14 21:53:12 +00006481 goto failret;
6482 }
6483 if (evaluate)
6484 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00006485 item = dict_find(d, key, -1);
Bram Moolenaar8c711452005-01-14 21:53:12 +00006486 if (item != NULL)
6487 {
Bram Moolenaarb982ca52005-03-28 21:02:15 +00006488 EMSG2(_("E721: Duplicate key in Dictionary: \"%s\""), key);
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00006489 clear_tv(&tvkey);
Bram Moolenaar8c711452005-01-14 21:53:12 +00006490 clear_tv(&tv);
6491 goto failret;
6492 }
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00006493 item = dictitem_alloc(key);
6494 clear_tv(&tvkey);
6495 if (item != NULL)
Bram Moolenaar8c711452005-01-14 21:53:12 +00006496 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00006497 item->di_tv = tv;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00006498 item->di_tv.v_lock = 0;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00006499 if (dict_add(d, item) == FAIL)
6500 dictitem_free(item);
Bram Moolenaar8c711452005-01-14 21:53:12 +00006501 }
6502 }
6503
6504 if (**arg == '}')
6505 break;
6506 if (**arg != ',')
6507 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00006508 EMSG2(_("E722: Missing comma in Dictionary: %s"), *arg);
Bram Moolenaar8c711452005-01-14 21:53:12 +00006509 goto failret;
6510 }
6511 *arg = skipwhite(*arg + 1);
6512 }
6513
6514 if (**arg != '}')
6515 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00006516 EMSG2(_("E723: Missing end of Dictionary '}': %s"), *arg);
Bram Moolenaar8c711452005-01-14 21:53:12 +00006517failret:
6518 if (evaluate)
6519 dict_free(d);
6520 return FAIL;
6521 }
6522
6523 *arg = skipwhite(*arg + 1);
6524 if (evaluate)
6525 {
6526 rettv->v_type = VAR_DICT;
6527 rettv->vval.v_dict = d;
6528 ++d->dv_refcount;
6529 }
6530
6531 return OK;
6532}
6533
Bram Moolenaar8c711452005-01-14 21:53:12 +00006534/*
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006535 * Return a string with the string representation of a variable.
6536 * If the memory is allocated "tofree" is set to it, otherwise NULL.
Bram Moolenaar8a283e52005-01-06 23:28:25 +00006537 * "numbuf" is used for a number.
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00006538 * Does not put quotes around strings, as ":echo" displays values.
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006539 * May return NULL;
6540 */
6541 static char_u *
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00006542echo_string(tv, tofree, numbuf)
Bram Moolenaar33570922005-01-25 22:26:29 +00006543 typval_T *tv;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006544 char_u **tofree;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00006545 char_u *numbuf;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006546{
Bram Moolenaare9a41262005-01-15 22:18:47 +00006547 static int recurse = 0;
6548 char_u *r = NULL;
6549
Bram Moolenaar33570922005-01-25 22:26:29 +00006550 if (recurse >= DICT_MAXNEST)
Bram Moolenaare9a41262005-01-15 22:18:47 +00006551 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00006552 EMSG(_("E724: variable nested too deep for displaying"));
Bram Moolenaare9a41262005-01-15 22:18:47 +00006553 *tofree = NULL;
6554 return NULL;
6555 }
6556 ++recurse;
6557
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006558 switch (tv->v_type)
6559 {
6560 case VAR_FUNC:
6561 *tofree = NULL;
Bram Moolenaare9a41262005-01-15 22:18:47 +00006562 r = tv->vval.v_string;
6563 break;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006564 case VAR_LIST:
6565 *tofree = list2string(tv);
Bram Moolenaare9a41262005-01-15 22:18:47 +00006566 r = *tofree;
6567 break;
Bram Moolenaar8c711452005-01-14 21:53:12 +00006568 case VAR_DICT:
6569 *tofree = dict2string(tv);
Bram Moolenaare9a41262005-01-15 22:18:47 +00006570 r = *tofree;
6571 break;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006572 case VAR_STRING:
6573 case VAR_NUMBER:
Bram Moolenaare9a41262005-01-15 22:18:47 +00006574 *tofree = NULL;
6575 r = get_tv_string_buf(tv, numbuf);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006576 break;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006577 default:
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00006578 EMSG2(_(e_intern2), "echo_string()");
Bram Moolenaare9a41262005-01-15 22:18:47 +00006579 *tofree = NULL;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00006580 }
Bram Moolenaare9a41262005-01-15 22:18:47 +00006581
6582 --recurse;
6583 return r;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00006584}
6585
6586/*
6587 * Return a string with the string representation of a variable.
6588 * If the memory is allocated "tofree" is set to it, otherwise NULL.
6589 * "numbuf" is used for a number.
6590 * Puts quotes around strings, so that they can be parsed back by eval().
6591 * May return NULL;
6592 */
6593 static char_u *
6594tv2string(tv, tofree, numbuf)
Bram Moolenaar33570922005-01-25 22:26:29 +00006595 typval_T *tv;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00006596 char_u **tofree;
6597 char_u *numbuf;
6598{
6599 switch (tv->v_type)
6600 {
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00006601 case VAR_FUNC:
6602 *tofree = string_quote(tv->vval.v_string, TRUE);
6603 return *tofree;
6604 case VAR_STRING:
6605 *tofree = string_quote(tv->vval.v_string, FALSE);
6606 return *tofree;
Bram Moolenaare9a41262005-01-15 22:18:47 +00006607 case VAR_NUMBER:
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00006608 case VAR_LIST:
Bram Moolenaar8c711452005-01-14 21:53:12 +00006609 case VAR_DICT:
Bram Moolenaare9a41262005-01-15 22:18:47 +00006610 break;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00006611 default:
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006612 EMSG2(_(e_intern2), "tv2string()");
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006613 }
Bram Moolenaare9a41262005-01-15 22:18:47 +00006614 return echo_string(tv, tofree, numbuf);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006615}
6616
6617/*
Bram Moolenaar33570922005-01-25 22:26:29 +00006618 * Return string "str" in ' quotes, doubling ' characters.
6619 * If "str" is NULL an empty string is assumed.
Bram Moolenaar8c711452005-01-14 21:53:12 +00006620 * If "function" is TRUE make it function('string').
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00006621 */
6622 static char_u *
6623string_quote(str, function)
6624 char_u *str;
6625 int function;
6626{
Bram Moolenaar33570922005-01-25 22:26:29 +00006627 unsigned len;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00006628 char_u *p, *r, *s;
6629
Bram Moolenaar33570922005-01-25 22:26:29 +00006630 len = (function ? 13 : 3);
6631 if (str != NULL)
6632 {
6633 len += STRLEN(str);
6634 for (p = str; *p != NUL; mb_ptr_adv(p))
6635 if (*p == '\'')
6636 ++len;
6637 }
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00006638 s = r = alloc(len);
6639 if (r != NULL)
6640 {
6641 if (function)
6642 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00006643 STRCPY(r, "function('");
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00006644 r += 10;
6645 }
6646 else
Bram Moolenaar8c711452005-01-14 21:53:12 +00006647 *r++ = '\'';
Bram Moolenaar33570922005-01-25 22:26:29 +00006648 if (str != NULL)
6649 for (p = str; *p != NUL; )
6650 {
6651 if (*p == '\'')
6652 *r++ = '\'';
6653 MB_COPY_CHAR(p, r);
6654 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00006655 *r++ = '\'';
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00006656 if (function)
6657 *r++ = ')';
6658 *r++ = NUL;
6659 }
6660 return s;
6661}
6662
6663/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00006664 * Get the value of an environment variable.
6665 * "arg" is pointing to the '$'. It is advanced to after the name.
6666 * If the environment variable was not set, silently assume it is empty.
6667 * Always return OK.
6668 */
6669 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006670get_env_tv(arg, rettv, evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006671 char_u **arg;
Bram Moolenaar33570922005-01-25 22:26:29 +00006672 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006673 int evaluate;
6674{
6675 char_u *string = NULL;
6676 int len;
6677 int cc;
6678 char_u *name;
Bram Moolenaar05159a02005-02-26 23:04:13 +00006679 int mustfree = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006680
6681 ++*arg;
6682 name = *arg;
6683 len = get_env_len(arg);
6684 if (evaluate)
6685 {
6686 if (len != 0)
6687 {
6688 cc = name[len];
6689 name[len] = NUL;
Bram Moolenaar05159a02005-02-26 23:04:13 +00006690 /* first try vim_getenv(), fast for normal environment vars */
6691 string = vim_getenv(name, &mustfree);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006692 if (string != NULL && *string != NUL)
Bram Moolenaar05159a02005-02-26 23:04:13 +00006693 {
6694 if (!mustfree)
6695 string = vim_strsave(string);
6696 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00006697 else
6698 {
Bram Moolenaar05159a02005-02-26 23:04:13 +00006699 if (mustfree)
6700 vim_free(string);
6701
Bram Moolenaar071d4272004-06-13 20:20:40 +00006702 /* next try expanding things like $VIM and ${HOME} */
6703 string = expand_env_save(name - 1);
6704 if (string != NULL && *string == '$')
6705 {
6706 vim_free(string);
6707 string = NULL;
6708 }
6709 }
6710 name[len] = cc;
6711 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006712 rettv->v_type = VAR_STRING;
6713 rettv->vval.v_string = string;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006714 }
6715
6716 return OK;
6717}
6718
6719/*
6720 * Array with names and number of arguments of all internal functions
6721 * MUST BE KEPT SORTED IN strcmp() ORDER FOR BINARY SEARCH!
6722 */
6723static struct fst
6724{
6725 char *f_name; /* function name */
6726 char f_min_argc; /* minimal number of arguments */
6727 char f_max_argc; /* maximal number of arguments */
Bram Moolenaar33570922005-01-25 22:26:29 +00006728 void (*f_func) __ARGS((typval_T *args, typval_T *rvar));
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006729 /* implemenation of function */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006730} functions[] =
6731{
Bram Moolenaar0d660222005-01-07 21:51:51 +00006732 {"add", 2, 2, f_add},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006733 {"append", 2, 2, f_append},
6734 {"argc", 0, 0, f_argc},
6735 {"argidx", 0, 0, f_argidx},
6736 {"argv", 1, 1, f_argv},
6737 {"browse", 4, 4, f_browse},
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00006738 {"browsedir", 2, 2, f_browsedir},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006739 {"bufexists", 1, 1, f_bufexists},
6740 {"buffer_exists", 1, 1, f_bufexists}, /* obsolete */
6741 {"buffer_name", 1, 1, f_bufname}, /* obsolete */
6742 {"buffer_number", 1, 1, f_bufnr}, /* obsolete */
6743 {"buflisted", 1, 1, f_buflisted},
6744 {"bufloaded", 1, 1, f_bufloaded},
6745 {"bufname", 1, 1, f_bufname},
6746 {"bufnr", 1, 1, f_bufnr},
6747 {"bufwinnr", 1, 1, f_bufwinnr},
6748 {"byte2line", 1, 1, f_byte2line},
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00006749 {"byteidx", 2, 2, f_byteidx},
Bram Moolenaare9a41262005-01-15 22:18:47 +00006750 {"call", 2, 3, f_call},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006751 {"char2nr", 1, 1, f_char2nr},
6752 {"cindent", 1, 1, f_cindent},
6753 {"col", 1, 1, f_col},
Bram Moolenaar572cb562005-08-05 21:35:02 +00006754#if defined(FEAT_INS_EXPAND)
6755 {"complete_add", 1, 1, f_complete_add},
6756 {"complete_check", 0, 0, f_complete_check},
6757#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00006758 {"confirm", 1, 4, f_confirm},
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006759 {"copy", 1, 1, f_copy},
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00006760 {"count", 2, 4, f_count},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006761 {"cscope_connection",0,3, f_cscope_connection},
6762 {"cursor", 2, 2, f_cursor},
Bram Moolenaar81bf7082005-02-12 14:31:42 +00006763 {"deepcopy", 1, 2, f_deepcopy},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006764 {"delete", 1, 1, f_delete},
6765 {"did_filetype", 0, 0, f_did_filetype},
Bram Moolenaar47136d72004-10-12 20:02:24 +00006766 {"diff_filler", 1, 1, f_diff_filler},
6767 {"diff_hlID", 2, 2, f_diff_hlID},
Bram Moolenaare49b69a2005-01-08 16:11:57 +00006768 {"empty", 1, 1, f_empty},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006769 {"escape", 2, 2, f_escape},
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00006770 {"eval", 1, 1, f_eval},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006771 {"eventhandler", 0, 0, f_eventhandler},
6772 {"executable", 1, 1, f_executable},
6773 {"exists", 1, 1, f_exists},
6774 {"expand", 1, 2, f_expand},
Bram Moolenaar8a283e52005-01-06 23:28:25 +00006775 {"extend", 2, 3, f_extend},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006776 {"file_readable", 1, 1, f_filereadable}, /* obsolete */
6777 {"filereadable", 1, 1, f_filereadable},
6778 {"filewritable", 1, 1, f_filewritable},
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00006779 {"filter", 2, 2, f_filter},
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00006780 {"finddir", 1, 3, f_finddir},
6781 {"findfile", 1, 3, f_findfile},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006782 {"fnamemodify", 2, 2, f_fnamemodify},
6783 {"foldclosed", 1, 1, f_foldclosed},
6784 {"foldclosedend", 1, 1, f_foldclosedend},
6785 {"foldlevel", 1, 1, f_foldlevel},
6786 {"foldtext", 0, 0, f_foldtext},
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00006787 {"foldtextresult", 1, 1, f_foldtextresult},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006788 {"foreground", 0, 0, f_foreground},
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006789 {"function", 1, 1, f_function},
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00006790 {"garbagecollect", 0, 0, f_garbagecollect},
Bram Moolenaar0d660222005-01-07 21:51:51 +00006791 {"get", 2, 3, f_get},
Bram Moolenaar80fc0432005-07-20 22:06:07 +00006792 {"getbufline", 2, 3, f_getbufline},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006793 {"getbufvar", 2, 2, f_getbufvar},
6794 {"getchar", 0, 1, f_getchar},
6795 {"getcharmod", 0, 0, f_getcharmod},
6796 {"getcmdline", 0, 0, f_getcmdline},
6797 {"getcmdpos", 0, 0, f_getcmdpos},
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +00006798 {"getcmdtype", 0, 0, f_getcmdtype},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006799 {"getcwd", 0, 0, f_getcwd},
Bram Moolenaar46c9c732004-12-12 11:37:09 +00006800 {"getfontname", 0, 1, f_getfontname},
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00006801 {"getfperm", 1, 1, f_getfperm},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006802 {"getfsize", 1, 1, f_getfsize},
6803 {"getftime", 1, 1, f_getftime},
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00006804 {"getftype", 1, 1, f_getftype},
Bram Moolenaar0d660222005-01-07 21:51:51 +00006805 {"getline", 1, 2, f_getline},
Bram Moolenaar2641f772005-03-25 21:58:17 +00006806 {"getqflist", 0, 0, f_getqflist},
Bram Moolenaar67fe1a12005-05-22 22:12:58 +00006807 {"getreg", 0, 2, f_getreg},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006808 {"getregtype", 0, 1, f_getregtype},
6809 {"getwinposx", 0, 0, f_getwinposx},
6810 {"getwinposy", 0, 0, f_getwinposy},
6811 {"getwinvar", 2, 2, f_getwinvar},
6812 {"glob", 1, 1, f_glob},
6813 {"globpath", 2, 2, f_globpath},
6814 {"has", 1, 1, f_has},
Bram Moolenaare9a41262005-01-15 22:18:47 +00006815 {"has_key", 2, 2, f_has_key},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006816 {"hasmapto", 1, 2, f_hasmapto},
6817 {"highlightID", 1, 1, f_hlID}, /* obsolete */
6818 {"highlight_exists",1, 1, f_hlexists}, /* obsolete */
6819 {"histadd", 2, 2, f_histadd},
6820 {"histdel", 1, 2, f_histdel},
6821 {"histget", 1, 2, f_histget},
6822 {"histnr", 1, 1, f_histnr},
6823 {"hlID", 1, 1, f_hlID},
6824 {"hlexists", 1, 1, f_hlexists},
6825 {"hostname", 0, 0, f_hostname},
6826 {"iconv", 3, 3, f_iconv},
6827 {"indent", 1, 1, f_indent},
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00006828 {"index", 2, 4, f_index},
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +00006829 {"input", 1, 3, f_input},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006830 {"inputdialog", 1, 3, f_inputdialog},
Bram Moolenaar6efa2b32005-09-10 19:26:26 +00006831 {"inputlist", 1, 1, f_inputlist},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006832 {"inputrestore", 0, 0, f_inputrestore},
6833 {"inputsave", 0, 0, f_inputsave},
6834 {"inputsecret", 1, 2, f_inputsecret},
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006835 {"insert", 2, 3, f_insert},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006836 {"isdirectory", 1, 1, f_isdirectory},
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00006837 {"islocked", 1, 1, f_islocked},
Bram Moolenaar8c711452005-01-14 21:53:12 +00006838 {"items", 1, 1, f_items},
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00006839 {"join", 1, 2, f_join},
Bram Moolenaar8c711452005-01-14 21:53:12 +00006840 {"keys", 1, 1, f_keys},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006841 {"last_buffer_nr", 0, 0, f_last_buffer_nr},/* obsolete */
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006842 {"len", 1, 1, f_len},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006843 {"libcall", 3, 3, f_libcall},
6844 {"libcallnr", 3, 3, f_libcallnr},
6845 {"line", 1, 1, f_line},
6846 {"line2byte", 1, 1, f_line2byte},
6847 {"lispindent", 1, 1, f_lispindent},
6848 {"localtime", 0, 0, f_localtime},
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00006849 {"map", 2, 2, f_map},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006850 {"maparg", 1, 2, f_maparg},
6851 {"mapcheck", 1, 2, f_mapcheck},
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00006852 {"match", 2, 4, f_match},
6853 {"matchend", 2, 4, f_matchend},
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00006854 {"matchlist", 2, 4, f_matchlist},
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00006855 {"matchstr", 2, 4, f_matchstr},
Bram Moolenaar6cc16192005-01-08 21:49:45 +00006856 {"max", 1, 1, f_max},
6857 {"min", 1, 1, f_min},
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00006858#ifdef vim_mkdir
6859 {"mkdir", 1, 3, f_mkdir},
6860#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00006861 {"mode", 0, 0, f_mode},
6862 {"nextnonblank", 1, 1, f_nextnonblank},
6863 {"nr2char", 1, 1, f_nr2char},
6864 {"prevnonblank", 1, 1, f_prevnonblank},
Bram Moolenaar4be06f92005-07-29 22:36:03 +00006865 {"printf", 2, 19, f_printf},
Bram Moolenaar8c711452005-01-14 21:53:12 +00006866 {"range", 1, 3, f_range},
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00006867 {"readfile", 1, 3, f_readfile},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006868 {"remote_expr", 2, 3, f_remote_expr},
6869 {"remote_foreground", 1, 1, f_remote_foreground},
6870 {"remote_peek", 1, 2, f_remote_peek},
6871 {"remote_read", 1, 1, f_remote_read},
6872 {"remote_send", 2, 3, f_remote_send},
Bram Moolenaar8a283e52005-01-06 23:28:25 +00006873 {"remove", 2, 3, f_remove},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006874 {"rename", 2, 2, f_rename},
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00006875 {"repeat", 2, 2, f_repeat},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006876 {"resolve", 1, 1, f_resolve},
Bram Moolenaar0d660222005-01-07 21:51:51 +00006877 {"reverse", 1, 1, f_reverse},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006878 {"search", 1, 2, f_search},
Bram Moolenaare6facf92005-09-13 21:22:27 +00006879 {"searchdecl", 1, 3, f_searchdecl},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006880 {"searchpair", 3, 5, f_searchpair},
6881 {"server2client", 2, 2, f_server2client},
6882 {"serverlist", 0, 0, f_serverlist},
6883 {"setbufvar", 3, 3, f_setbufvar},
6884 {"setcmdpos", 1, 1, f_setcmdpos},
6885 {"setline", 2, 2, f_setline},
Bram Moolenaarf4630b62005-05-20 21:31:17 +00006886 {"setqflist", 1, 2, f_setqflist},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006887 {"setreg", 2, 3, f_setreg},
6888 {"setwinvar", 3, 3, f_setwinvar},
6889 {"simplify", 1, 1, f_simplify},
Bram Moolenaar0d660222005-01-07 21:51:51 +00006890 {"sort", 1, 2, f_sort},
Bram Moolenaar24bbcfe2005-06-28 23:32:02 +00006891 {"soundfold", 1, 1, f_soundfold},
Bram Moolenaar4463f292005-09-25 22:20:24 +00006892 {"spellbadword", 0, 1, f_spellbadword},
Bram Moolenaar69e0ff92005-09-30 21:23:56 +00006893 {"spellsuggest", 1, 3, f_spellsuggest},
Bram Moolenaar67fe1a12005-05-22 22:12:58 +00006894 {"split", 1, 3, f_split},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006895#ifdef HAVE_STRFTIME
6896 {"strftime", 1, 2, f_strftime},
6897#endif
Bram Moolenaar33570922005-01-25 22:26:29 +00006898 {"stridx", 2, 3, f_stridx},
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006899 {"string", 1, 1, f_string},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006900 {"strlen", 1, 1, f_strlen},
6901 {"strpart", 2, 3, f_strpart},
Bram Moolenaar532c7802005-01-27 14:44:31 +00006902 {"strridx", 2, 3, f_strridx},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006903 {"strtrans", 1, 1, f_strtrans},
6904 {"submatch", 1, 1, f_submatch},
6905 {"substitute", 4, 4, f_substitute},
6906 {"synID", 3, 3, f_synID},
6907 {"synIDattr", 2, 3, f_synIDattr},
6908 {"synIDtrans", 1, 1, f_synIDtrans},
Bram Moolenaarc0197e22004-09-13 20:26:32 +00006909 {"system", 1, 2, f_system},
Bram Moolenaard43b6cf2005-09-09 19:53:42 +00006910 {"tagfiles", 0, 0, f_tagfiles},
Bram Moolenaar19a09a12005-03-04 23:39:37 +00006911 {"taglist", 1, 1, f_taglist},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006912 {"tempname", 0, 0, f_tempname},
Bram Moolenaard52d9742005-08-21 22:20:28 +00006913 {"test", 1, 1, f_test},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006914 {"tolower", 1, 1, f_tolower},
6915 {"toupper", 1, 1, f_toupper},
Bram Moolenaar8299df92004-07-10 09:47:34 +00006916 {"tr", 3, 3, f_tr},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006917 {"type", 1, 1, f_type},
Bram Moolenaar8c711452005-01-14 21:53:12 +00006918 {"values", 1, 1, f_values},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006919 {"virtcol", 1, 1, f_virtcol},
6920 {"visualmode", 0, 1, f_visualmode},
6921 {"winbufnr", 1, 1, f_winbufnr},
6922 {"wincol", 0, 0, f_wincol},
6923 {"winheight", 1, 1, f_winheight},
6924 {"winline", 0, 0, f_winline},
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00006925 {"winnr", 0, 1, f_winnr},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006926 {"winrestcmd", 0, 0, f_winrestcmd},
6927 {"winwidth", 1, 1, f_winwidth},
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00006928 {"writefile", 2, 3, f_writefile},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006929};
6930
6931#if defined(FEAT_CMDL_COMPL) || defined(PROTO)
6932
6933/*
6934 * Function given to ExpandGeneric() to obtain the list of internal
6935 * or user defined function names.
6936 */
6937 char_u *
6938get_function_name(xp, idx)
6939 expand_T *xp;
6940 int idx;
6941{
6942 static int intidx = -1;
6943 char_u *name;
6944
6945 if (idx == 0)
6946 intidx = -1;
6947 if (intidx < 0)
6948 {
6949 name = get_user_func_name(xp, idx);
6950 if (name != NULL)
6951 return name;
6952 }
6953 if (++intidx < (int)(sizeof(functions) / sizeof(struct fst)))
6954 {
6955 STRCPY(IObuff, functions[intidx].f_name);
6956 STRCAT(IObuff, "(");
6957 if (functions[intidx].f_max_argc == 0)
6958 STRCAT(IObuff, ")");
6959 return IObuff;
6960 }
6961
6962 return NULL;
6963}
6964
6965/*
6966 * Function given to ExpandGeneric() to obtain the list of internal or
6967 * user defined variable or function names.
6968 */
6969/*ARGSUSED*/
6970 char_u *
6971get_expr_name(xp, idx)
6972 expand_T *xp;
6973 int idx;
6974{
6975 static int intidx = -1;
6976 char_u *name;
6977
6978 if (idx == 0)
6979 intidx = -1;
6980 if (intidx < 0)
6981 {
6982 name = get_function_name(xp, idx);
6983 if (name != NULL)
6984 return name;
6985 }
6986 return get_user_var_name(xp, ++intidx);
6987}
6988
6989#endif /* FEAT_CMDL_COMPL */
6990
6991/*
6992 * Find internal function in table above.
6993 * Return index, or -1 if not found
6994 */
6995 static int
6996find_internal_func(name)
6997 char_u *name; /* name of the function */
6998{
6999 int first = 0;
7000 int last = (int)(sizeof(functions) / sizeof(struct fst)) - 1;
7001 int cmp;
7002 int x;
7003
7004 /*
7005 * Find the function name in the table. Binary search.
7006 */
7007 while (first <= last)
7008 {
7009 x = first + ((unsigned)(last - first) >> 1);
7010 cmp = STRCMP(name, functions[x].f_name);
7011 if (cmp < 0)
7012 last = x - 1;
7013 else if (cmp > 0)
7014 first = x + 1;
7015 else
7016 return x;
7017 }
7018 return -1;
7019}
7020
7021/*
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007022 * Check if "name" is a variable of type VAR_FUNC. If so, return the function
7023 * name it contains, otherwise return "name".
7024 */
7025 static char_u *
7026deref_func_name(name, lenp)
7027 char_u *name;
7028 int *lenp;
7029{
Bram Moolenaar33570922005-01-25 22:26:29 +00007030 dictitem_T *v;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007031 int cc;
7032
7033 cc = name[*lenp];
7034 name[*lenp] = NUL;
Bram Moolenaara7043832005-01-21 11:56:39 +00007035 v = find_var(name, NULL);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007036 name[*lenp] = cc;
Bram Moolenaar33570922005-01-25 22:26:29 +00007037 if (v != NULL && v->di_tv.v_type == VAR_FUNC)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007038 {
Bram Moolenaar33570922005-01-25 22:26:29 +00007039 if (v->di_tv.vval.v_string == NULL)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007040 {
7041 *lenp = 0;
7042 return (char_u *)""; /* just in case */
7043 }
Bram Moolenaar33570922005-01-25 22:26:29 +00007044 *lenp = STRLEN(v->di_tv.vval.v_string);
7045 return v->di_tv.vval.v_string;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007046 }
7047
7048 return name;
7049}
7050
7051/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00007052 * Allocate a variable for the result of a function.
7053 * Return OK or FAIL.
7054 */
7055 static int
Bram Moolenaare9a41262005-01-15 22:18:47 +00007056get_func_tv(name, len, rettv, arg, firstline, lastline, doesrange,
7057 evaluate, selfdict)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007058 char_u *name; /* name of the function */
7059 int len; /* length of "name" */
Bram Moolenaar33570922005-01-25 22:26:29 +00007060 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007061 char_u **arg; /* argument, pointing to the '(' */
7062 linenr_T firstline; /* first line of range */
7063 linenr_T lastline; /* last line of range */
7064 int *doesrange; /* return: function handled range */
7065 int evaluate;
Bram Moolenaar33570922005-01-25 22:26:29 +00007066 dict_T *selfdict; /* Dictionary for "self" */
Bram Moolenaar071d4272004-06-13 20:20:40 +00007067{
7068 char_u *argp;
7069 int ret = OK;
Bram Moolenaar33570922005-01-25 22:26:29 +00007070 typval_T argvars[MAX_FUNC_ARGS]; /* vars for arguments */
Bram Moolenaar071d4272004-06-13 20:20:40 +00007071 int argcount = 0; /* number of arguments found */
7072
7073 /*
7074 * Get the arguments.
7075 */
7076 argp = *arg;
7077 while (argcount < MAX_FUNC_ARGS)
7078 {
7079 argp = skipwhite(argp + 1); /* skip the '(' or ',' */
7080 if (*argp == ')' || *argp == ',' || *argp == NUL)
7081 break;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007082 if (eval1(&argp, &argvars[argcount], evaluate) == FAIL)
7083 {
7084 ret = FAIL;
7085 break;
7086 }
7087 ++argcount;
7088 if (*argp != ',')
7089 break;
7090 }
7091 if (*argp == ')')
7092 ++argp;
7093 else
7094 ret = FAIL;
7095
7096 if (ret == OK)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007097 ret = call_func(name, len, rettv, argcount, argvars,
Bram Moolenaare9a41262005-01-15 22:18:47 +00007098 firstline, lastline, doesrange, evaluate, selfdict);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007099 else if (!aborting())
Bram Moolenaar33570922005-01-25 22:26:29 +00007100 {
7101 if (argcount == MAX_FUNC_ARGS)
Bram Moolenaar81bf7082005-02-12 14:31:42 +00007102 emsg_funcname("E740: Too many arguments for function %s", name);
Bram Moolenaar33570922005-01-25 22:26:29 +00007103 else
Bram Moolenaar81bf7082005-02-12 14:31:42 +00007104 emsg_funcname("E116: Invalid arguments for function %s", name);
Bram Moolenaar33570922005-01-25 22:26:29 +00007105 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00007106
7107 while (--argcount >= 0)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007108 clear_tv(&argvars[argcount]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007109
7110 *arg = skipwhite(argp);
7111 return ret;
7112}
7113
7114
7115/*
7116 * Call a function with its resolved parameters
7117 * Return OK or FAIL.
7118 */
7119 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007120call_func(name, len, rettv, argcount, argvars, firstline, lastline,
Bram Moolenaare9a41262005-01-15 22:18:47 +00007121 doesrange, evaluate, selfdict)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007122 char_u *name; /* name of the function */
7123 int len; /* length of "name" */
Bram Moolenaar33570922005-01-25 22:26:29 +00007124 typval_T *rettv; /* return value goes here */
Bram Moolenaar071d4272004-06-13 20:20:40 +00007125 int argcount; /* number of "argvars" */
Bram Moolenaar33570922005-01-25 22:26:29 +00007126 typval_T *argvars; /* vars for arguments */
Bram Moolenaar071d4272004-06-13 20:20:40 +00007127 linenr_T firstline; /* first line of range */
7128 linenr_T lastline; /* last line of range */
7129 int *doesrange; /* return: function handled range */
7130 int evaluate;
Bram Moolenaar33570922005-01-25 22:26:29 +00007131 dict_T *selfdict; /* Dictionary for "self" */
Bram Moolenaar071d4272004-06-13 20:20:40 +00007132{
7133 int ret = FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007134#define ERROR_UNKNOWN 0
7135#define ERROR_TOOMANY 1
7136#define ERROR_TOOFEW 2
7137#define ERROR_SCRIPT 3
Bram Moolenaare9a41262005-01-15 22:18:47 +00007138#define ERROR_DICT 4
7139#define ERROR_NONE 5
7140#define ERROR_OTHER 6
Bram Moolenaar071d4272004-06-13 20:20:40 +00007141 int error = ERROR_NONE;
7142 int i;
7143 int llen;
7144 ufunc_T *fp;
7145 int cc;
7146#define FLEN_FIXED 40
7147 char_u fname_buf[FLEN_FIXED + 1];
7148 char_u *fname;
7149
7150 /*
7151 * In a script change <SID>name() and s:name() to K_SNR 123_name().
7152 * Change <SNR>123_name() to K_SNR 123_name().
7153 * Use fname_buf[] when it fits, otherwise allocate memory (slow).
7154 */
7155 cc = name[len];
7156 name[len] = NUL;
7157 llen = eval_fname_script(name);
7158 if (llen > 0)
7159 {
7160 fname_buf[0] = K_SPECIAL;
7161 fname_buf[1] = KS_EXTRA;
7162 fname_buf[2] = (int)KE_SNR;
7163 i = 3;
7164 if (eval_fname_sid(name)) /* "<SID>" or "s:" */
7165 {
7166 if (current_SID <= 0)
7167 error = ERROR_SCRIPT;
7168 else
7169 {
7170 sprintf((char *)fname_buf + 3, "%ld_", (long)current_SID);
7171 i = (int)STRLEN(fname_buf);
7172 }
7173 }
7174 if (i + STRLEN(name + llen) < FLEN_FIXED)
7175 {
7176 STRCPY(fname_buf + i, name + llen);
7177 fname = fname_buf;
7178 }
7179 else
7180 {
7181 fname = alloc((unsigned)(i + STRLEN(name + llen) + 1));
7182 if (fname == NULL)
7183 error = ERROR_OTHER;
7184 else
7185 {
7186 mch_memmove(fname, fname_buf, (size_t)i);
7187 STRCPY(fname + i, name + llen);
7188 }
7189 }
7190 }
7191 else
7192 fname = name;
7193
7194 *doesrange = FALSE;
7195
7196
7197 /* execute the function if no errors detected and executing */
7198 if (evaluate && error == ERROR_NONE)
7199 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007200 rettv->v_type = VAR_NUMBER; /* default is number rettv */
Bram Moolenaar071d4272004-06-13 20:20:40 +00007201 error = ERROR_UNKNOWN;
7202
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +00007203 if (!builtin_function(fname))
Bram Moolenaar071d4272004-06-13 20:20:40 +00007204 {
7205 /*
7206 * User defined function.
7207 */
7208 fp = find_func(fname);
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +00007209
Bram Moolenaar071d4272004-06-13 20:20:40 +00007210#ifdef FEAT_AUTOCMD
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +00007211 /* Trigger FuncUndefined event, may load the function. */
7212 if (fp == NULL
7213 && apply_autocmds(EVENT_FUNCUNDEFINED,
7214 fname, fname, TRUE, NULL)
7215 && !aborting())
Bram Moolenaar071d4272004-06-13 20:20:40 +00007216 {
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +00007217 /* executed an autocommand, search for the function again */
Bram Moolenaar071d4272004-06-13 20:20:40 +00007218 fp = find_func(fname);
7219 }
7220#endif
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +00007221 /* Try loading a package. */
Bram Moolenaar87e25fd2005-07-27 21:13:01 +00007222 if (fp == NULL && script_autoload(fname, TRUE) && !aborting())
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +00007223 {
7224 /* loaded a package, search for the function again */
7225 fp = find_func(fname);
7226 }
7227
Bram Moolenaar071d4272004-06-13 20:20:40 +00007228 if (fp != NULL)
7229 {
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00007230 if (fp->uf_flags & FC_RANGE)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007231 *doesrange = TRUE;
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00007232 if (argcount < fp->uf_args.ga_len)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007233 error = ERROR_TOOFEW;
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00007234 else if (!fp->uf_varargs && argcount > fp->uf_args.ga_len)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007235 error = ERROR_TOOMANY;
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00007236 else if ((fp->uf_flags & FC_DICT) && selfdict == NULL)
Bram Moolenaare9a41262005-01-15 22:18:47 +00007237 error = ERROR_DICT;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007238 else
7239 {
7240 /*
7241 * Call the user function.
7242 * Save and restore search patterns, script variables and
7243 * redo buffer.
7244 */
7245 save_search_patterns();
7246 saveRedobuff();
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00007247 ++fp->uf_calls;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007248 call_user_func(fp, argcount, argvars, rettv,
Bram Moolenaare9a41262005-01-15 22:18:47 +00007249 firstline, lastline,
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00007250 (fp->uf_flags & FC_DICT) ? selfdict : NULL);
7251 if (--fp->uf_calls <= 0 && isdigit(*fp->uf_name)
7252 && fp->uf_refcount <= 0)
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00007253 /* Function was unreferenced while being used, free it
7254 * now. */
7255 func_free(fp);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007256 restoreRedobuff();
7257 restore_search_patterns();
7258 error = ERROR_NONE;
7259 }
7260 }
7261 }
7262 else
7263 {
7264 /*
7265 * Find the function name in the table, call its implementation.
7266 */
7267 i = find_internal_func(fname);
7268 if (i >= 0)
7269 {
7270 if (argcount < functions[i].f_min_argc)
7271 error = ERROR_TOOFEW;
7272 else if (argcount > functions[i].f_max_argc)
7273 error = ERROR_TOOMANY;
7274 else
7275 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007276 argvars[argcount].v_type = VAR_UNKNOWN;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007277 functions[i].f_func(argvars, rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007278 error = ERROR_NONE;
7279 }
7280 }
7281 }
7282 /*
7283 * The function call (or "FuncUndefined" autocommand sequence) might
7284 * have been aborted by an error, an interrupt, or an explicitly thrown
7285 * exception that has not been caught so far. This situation can be
7286 * tested for by calling aborting(). For an error in an internal
7287 * function or for the "E132" error in call_user_func(), however, the
7288 * throw point at which the "force_abort" flag (temporarily reset by
7289 * emsg()) is normally updated has not been reached yet. We need to
7290 * update that flag first to make aborting() reliable.
7291 */
7292 update_force_abort();
7293 }
7294 if (error == ERROR_NONE)
7295 ret = OK;
7296
7297 /*
7298 * Report an error unless the argument evaluation or function call has been
7299 * cancelled due to an aborting error, an interrupt, or an exception.
7300 */
Bram Moolenaar8c711452005-01-14 21:53:12 +00007301 if (!aborting())
7302 {
7303 switch (error)
7304 {
7305 case ERROR_UNKNOWN:
Bram Moolenaar81bf7082005-02-12 14:31:42 +00007306 emsg_funcname("E117: Unknown function: %s", name);
Bram Moolenaar8c711452005-01-14 21:53:12 +00007307 break;
7308 case ERROR_TOOMANY:
Bram Moolenaar81bf7082005-02-12 14:31:42 +00007309 emsg_funcname(e_toomanyarg, name);
Bram Moolenaar8c711452005-01-14 21:53:12 +00007310 break;
7311 case ERROR_TOOFEW:
Bram Moolenaar81bf7082005-02-12 14:31:42 +00007312 emsg_funcname("E119: Not enough arguments for function: %s",
Bram Moolenaar8c711452005-01-14 21:53:12 +00007313 name);
7314 break;
7315 case ERROR_SCRIPT:
Bram Moolenaar81bf7082005-02-12 14:31:42 +00007316 emsg_funcname("E120: Using <SID> not in a script context: %s",
Bram Moolenaar8c711452005-01-14 21:53:12 +00007317 name);
7318 break;
Bram Moolenaare9a41262005-01-15 22:18:47 +00007319 case ERROR_DICT:
Bram Moolenaar81bf7082005-02-12 14:31:42 +00007320 emsg_funcname("E725: Calling dict function without Dictionary: %s",
Bram Moolenaare9a41262005-01-15 22:18:47 +00007321 name);
7322 break;
Bram Moolenaar8c711452005-01-14 21:53:12 +00007323 }
7324 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00007325
7326 name[len] = cc;
7327 if (fname != name && fname != fname_buf)
7328 vim_free(fname);
7329
7330 return ret;
7331}
7332
Bram Moolenaar81bf7082005-02-12 14:31:42 +00007333/*
7334 * Give an error message with a function name. Handle <SNR> things.
7335 */
7336 static void
7337emsg_funcname(msg, name)
7338 char *msg;
7339 char_u *name;
7340{
7341 char_u *p;
7342
7343 if (*name == K_SPECIAL)
7344 p = concat_str((char_u *)"<SNR>", name + 3);
7345 else
7346 p = name;
7347 EMSG2(_(msg), p);
7348 if (p != name)
7349 vim_free(p);
7350}
7351
Bram Moolenaar071d4272004-06-13 20:20:40 +00007352/*********************************************
7353 * Implementation of the built-in functions
7354 */
7355
7356/*
Bram Moolenaar0d660222005-01-07 21:51:51 +00007357 * "add(list, item)" function
Bram Moolenaar071d4272004-06-13 20:20:40 +00007358 */
7359 static void
Bram Moolenaar0d660222005-01-07 21:51:51 +00007360f_add(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007361 typval_T *argvars;
7362 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007363{
Bram Moolenaar33570922005-01-25 22:26:29 +00007364 list_T *l;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007365
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007366 rettv->vval.v_number = 1; /* Default: Failed */
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007367 if (argvars[0].v_type == VAR_LIST)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007368 {
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00007369 if ((l = argvars[0].vval.v_list) != NULL
7370 && !tv_check_lock(l->lv_lock, (char_u *)"add()")
7371 && list_append_tv(l, &argvars[1]) == OK)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007372 copy_tv(&argvars[0], rettv);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007373 }
7374 else
Bram Moolenaar0d660222005-01-07 21:51:51 +00007375 EMSG(_(e_listreq));
7376}
7377
7378/*
7379 * "append(lnum, string/list)" function
7380 */
7381 static void
7382f_append(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007383 typval_T *argvars;
7384 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +00007385{
7386 long lnum;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00007387 char_u *line;
Bram Moolenaar33570922005-01-25 22:26:29 +00007388 list_T *l = NULL;
7389 listitem_T *li = NULL;
7390 typval_T *tv;
Bram Moolenaar0d660222005-01-07 21:51:51 +00007391 long added = 0;
7392
Bram Moolenaar0d660222005-01-07 21:51:51 +00007393 lnum = get_tv_lnum(argvars);
7394 if (lnum >= 0
7395 && lnum <= curbuf->b_ml.ml_line_count
7396 && u_save(lnum, lnum + 1) == OK)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007397 {
Bram Moolenaar0d660222005-01-07 21:51:51 +00007398 if (argvars[1].v_type == VAR_LIST)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007399 {
Bram Moolenaar0d660222005-01-07 21:51:51 +00007400 l = argvars[1].vval.v_list;
7401 if (l == NULL)
7402 return;
7403 li = l->lv_first;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007404 }
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00007405 rettv->vval.v_number = 0; /* Default: Success */
Bram Moolenaar0d660222005-01-07 21:51:51 +00007406 for (;;)
7407 {
7408 if (l == NULL)
7409 tv = &argvars[1]; /* append a string */
7410 else if (li == NULL)
7411 break; /* end of list */
7412 else
7413 tv = &li->li_tv; /* append item from list */
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00007414 line = get_tv_string_chk(tv);
7415 if (line == NULL) /* type error */
7416 {
7417 rettv->vval.v_number = 1; /* Failed */
7418 break;
7419 }
7420 ml_append(lnum + added, line, (colnr_T)0, FALSE);
Bram Moolenaar0d660222005-01-07 21:51:51 +00007421 ++added;
7422 if (l == NULL)
7423 break;
7424 li = li->li_next;
7425 }
7426
7427 appended_lines_mark(lnum, added);
7428 if (curwin->w_cursor.lnum > lnum)
7429 curwin->w_cursor.lnum += added;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007430 }
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00007431 else
7432 rettv->vval.v_number = 1; /* Failed */
Bram Moolenaar071d4272004-06-13 20:20:40 +00007433}
7434
7435/*
7436 * "argc()" function
7437 */
7438/* ARGSUSED */
7439 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007440f_argc(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007441 typval_T *argvars;
7442 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007443{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007444 rettv->vval.v_number = ARGCOUNT;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007445}
7446
7447/*
7448 * "argidx()" function
7449 */
7450/* ARGSUSED */
7451 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007452f_argidx(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007453 typval_T *argvars;
7454 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007455{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007456 rettv->vval.v_number = curwin->w_arg_idx;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007457}
7458
7459/*
7460 * "argv(nr)" function
7461 */
7462 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007463f_argv(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007464 typval_T *argvars;
7465 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007466{
7467 int idx;
7468
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00007469 idx = get_tv_number_chk(&argvars[0], NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007470 if (idx >= 0 && idx < ARGCOUNT)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007471 rettv->vval.v_string = vim_strsave(alist_name(&ARGLIST[idx]));
Bram Moolenaar071d4272004-06-13 20:20:40 +00007472 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007473 rettv->vval.v_string = NULL;
7474 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007475}
7476
7477/*
7478 * "browse(save, title, initdir, default)" function
7479 */
7480/* ARGSUSED */
7481 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007482f_browse(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007483 typval_T *argvars;
7484 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007485{
7486#ifdef FEAT_BROWSE
7487 int save;
7488 char_u *title;
7489 char_u *initdir;
7490 char_u *defname;
7491 char_u buf[NUMBUFLEN];
7492 char_u buf2[NUMBUFLEN];
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00007493 int error = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007494
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00007495 save = get_tv_number_chk(&argvars[0], &error);
7496 title = get_tv_string_chk(&argvars[1]);
7497 initdir = get_tv_string_buf_chk(&argvars[2], buf);
7498 defname = get_tv_string_buf_chk(&argvars[3], buf2);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007499
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00007500 if (error || title == NULL || initdir == NULL || defname == NULL)
7501 rettv->vval.v_string = NULL;
7502 else
7503 rettv->vval.v_string =
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00007504 do_browse(save ? BROWSE_SAVE : 0,
7505 title, defname, NULL, initdir, NULL, curbuf);
7506#else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007507 rettv->vval.v_string = NULL;
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00007508#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007509 rettv->v_type = VAR_STRING;
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00007510}
7511
7512/*
7513 * "browsedir(title, initdir)" function
7514 */
7515/* ARGSUSED */
7516 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007517f_browsedir(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007518 typval_T *argvars;
7519 typval_T *rettv;
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00007520{
7521#ifdef FEAT_BROWSE
7522 char_u *title;
7523 char_u *initdir;
7524 char_u buf[NUMBUFLEN];
7525
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00007526 title = get_tv_string_chk(&argvars[0]);
7527 initdir = get_tv_string_buf_chk(&argvars[1], buf);
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00007528
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00007529 if (title == NULL || initdir == NULL)
7530 rettv->vval.v_string = NULL;
7531 else
7532 rettv->vval.v_string = do_browse(BROWSE_DIR,
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00007533 title, NULL, NULL, initdir, NULL, curbuf);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007534#else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007535 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007536#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007537 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007538}
7539
Bram Moolenaar33570922005-01-25 22:26:29 +00007540static buf_T *find_buffer __ARGS((typval_T *avar));
Bram Moolenaar0d660222005-01-07 21:51:51 +00007541
Bram Moolenaar071d4272004-06-13 20:20:40 +00007542/*
7543 * Find a buffer by number or exact name.
7544 */
7545 static buf_T *
7546find_buffer(avar)
Bram Moolenaar33570922005-01-25 22:26:29 +00007547 typval_T *avar;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007548{
7549 buf_T *buf = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007550
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007551 if (avar->v_type == VAR_NUMBER)
7552 buf = buflist_findnr((int)avar->vval.v_number);
Bram Moolenaar758711c2005-02-02 23:11:38 +00007553 else if (avar->v_type == VAR_STRING && avar->vval.v_string != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007554 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007555 buf = buflist_findname_exp(avar->vval.v_string);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00007556 if (buf == NULL)
7557 {
7558 /* No full path name match, try a match with a URL or a "nofile"
7559 * buffer, these don't use the full path. */
7560 for (buf = firstbuf; buf != NULL; buf = buf->b_next)
7561 if (buf->b_fname != NULL
7562 && (path_with_url(buf->b_fname)
7563#ifdef FEAT_QUICKFIX
7564 || bt_nofile(buf)
7565#endif
7566 )
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007567 && STRCMP(buf->b_fname, avar->vval.v_string) == 0)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00007568 break;
7569 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00007570 }
7571 return buf;
7572}
7573
7574/*
7575 * "bufexists(expr)" function
7576 */
7577 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007578f_bufexists(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007579 typval_T *argvars;
7580 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007581{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007582 rettv->vval.v_number = (find_buffer(&argvars[0]) != NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007583}
7584
7585/*
7586 * "buflisted(expr)" function
7587 */
7588 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007589f_buflisted(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007590 typval_T *argvars;
7591 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007592{
7593 buf_T *buf;
7594
7595 buf = find_buffer(&argvars[0]);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007596 rettv->vval.v_number = (buf != NULL && buf->b_p_bl);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007597}
7598
7599/*
7600 * "bufloaded(expr)" function
7601 */
7602 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007603f_bufloaded(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007604 typval_T *argvars;
7605 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007606{
7607 buf_T *buf;
7608
7609 buf = find_buffer(&argvars[0]);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007610 rettv->vval.v_number = (buf != NULL && buf->b_ml.ml_mfp != NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007611}
7612
Bram Moolenaar33570922005-01-25 22:26:29 +00007613static buf_T *get_buf_tv __ARGS((typval_T *tv));
Bram Moolenaar0d660222005-01-07 21:51:51 +00007614
Bram Moolenaar071d4272004-06-13 20:20:40 +00007615/*
7616 * Get buffer by number or pattern.
7617 */
7618 static buf_T *
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007619get_buf_tv(tv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007620 typval_T *tv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007621{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007622 char_u *name = tv->vval.v_string;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007623 int save_magic;
7624 char_u *save_cpo;
7625 buf_T *buf;
7626
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007627 if (tv->v_type == VAR_NUMBER)
7628 return buflist_findnr((int)tv->vval.v_number);
Bram Moolenaar758711c2005-02-02 23:11:38 +00007629 if (tv->v_type != VAR_STRING)
7630 return NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007631 if (name == NULL || *name == NUL)
7632 return curbuf;
7633 if (name[0] == '$' && name[1] == NUL)
7634 return lastbuf;
7635
7636 /* Ignore 'magic' and 'cpoptions' here to make scripts portable */
7637 save_magic = p_magic;
7638 p_magic = TRUE;
7639 save_cpo = p_cpo;
7640 p_cpo = (char_u *)"";
7641
7642 buf = buflist_findnr(buflist_findpat(name, name + STRLEN(name),
7643 TRUE, FALSE));
7644
7645 p_magic = save_magic;
7646 p_cpo = save_cpo;
7647
7648 /* If not found, try expanding the name, like done for bufexists(). */
7649 if (buf == NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007650 buf = find_buffer(tv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007651
7652 return buf;
7653}
7654
7655/*
7656 * "bufname(expr)" function
7657 */
7658 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007659f_bufname(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007660 typval_T *argvars;
7661 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007662{
7663 buf_T *buf;
7664
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00007665 (void)get_tv_number(&argvars[0]); /* issue errmsg if type error */
Bram Moolenaar071d4272004-06-13 20:20:40 +00007666 ++emsg_off;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007667 buf = get_buf_tv(&argvars[0]);
7668 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007669 if (buf != NULL && buf->b_fname != NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007670 rettv->vval.v_string = vim_strsave(buf->b_fname);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007671 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007672 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007673 --emsg_off;
7674}
7675
7676/*
7677 * "bufnr(expr)" function
7678 */
7679 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007680f_bufnr(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007681 typval_T *argvars;
7682 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007683{
7684 buf_T *buf;
7685
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00007686 (void)get_tv_number(&argvars[0]); /* issue errmsg if type error */
Bram Moolenaar071d4272004-06-13 20:20:40 +00007687 ++emsg_off;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007688 buf = get_buf_tv(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007689 if (buf != NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007690 rettv->vval.v_number = buf->b_fnum;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007691 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007692 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007693 --emsg_off;
7694}
7695
7696/*
7697 * "bufwinnr(nr)" function
7698 */
7699 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007700f_bufwinnr(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007701 typval_T *argvars;
7702 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007703{
7704#ifdef FEAT_WINDOWS
7705 win_T *wp;
7706 int winnr = 0;
7707#endif
7708 buf_T *buf;
7709
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00007710 (void)get_tv_number(&argvars[0]); /* issue errmsg if type error */
Bram Moolenaar071d4272004-06-13 20:20:40 +00007711 ++emsg_off;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007712 buf = get_buf_tv(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007713#ifdef FEAT_WINDOWS
7714 for (wp = firstwin; wp; wp = wp->w_next)
7715 {
7716 ++winnr;
7717 if (wp->w_buffer == buf)
7718 break;
7719 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007720 rettv->vval.v_number = (wp != NULL ? winnr : -1);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007721#else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007722 rettv->vval.v_number = (curwin->w_buffer == buf ? 1 : -1);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007723#endif
7724 --emsg_off;
7725}
7726
7727/*
7728 * "byte2line(byte)" function
7729 */
7730/*ARGSUSED*/
7731 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007732f_byte2line(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007733 typval_T *argvars;
7734 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007735{
7736#ifndef FEAT_BYTEOFF
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007737 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007738#else
7739 long boff = 0;
7740
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00007741 boff = get_tv_number(&argvars[0]) - 1; /* boff gets -1 on type error */
Bram Moolenaar071d4272004-06-13 20:20:40 +00007742 if (boff < 0)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007743 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007744 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007745 rettv->vval.v_number = ml_find_line_or_offset(curbuf,
Bram Moolenaar071d4272004-06-13 20:20:40 +00007746 (linenr_T)0, &boff);
7747#endif
7748}
7749
7750/*
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00007751 * "byteidx()" function
7752 */
7753/*ARGSUSED*/
7754 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007755f_byteidx(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007756 typval_T *argvars;
7757 typval_T *rettv;
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00007758{
7759#ifdef FEAT_MBYTE
7760 char_u *t;
7761#endif
7762 char_u *str;
7763 long idx;
7764
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00007765 str = get_tv_string_chk(&argvars[0]);
7766 idx = get_tv_number_chk(&argvars[1], NULL);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007767 rettv->vval.v_number = -1;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00007768 if (str == NULL || idx < 0)
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00007769 return;
7770
7771#ifdef FEAT_MBYTE
7772 t = str;
7773 for ( ; idx > 0; idx--)
7774 {
7775 if (*t == NUL) /* EOL reached */
7776 return;
Bram Moolenaar0fa313a2005-08-10 21:07:57 +00007777 t += (*mb_ptr2len)(t);
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00007778 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007779 rettv->vval.v_number = t - str;
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00007780#else
7781 if (idx <= STRLEN(str))
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007782 rettv->vval.v_number = idx;
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00007783#endif
7784}
7785
7786/*
Bram Moolenaar8a283e52005-01-06 23:28:25 +00007787 * "call(func, arglist)" function
7788 */
7789 static void
7790f_call(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007791 typval_T *argvars;
7792 typval_T *rettv;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00007793{
7794 char_u *func;
Bram Moolenaar33570922005-01-25 22:26:29 +00007795 typval_T argv[MAX_FUNC_ARGS];
Bram Moolenaar8a283e52005-01-06 23:28:25 +00007796 int argc = 0;
Bram Moolenaar33570922005-01-25 22:26:29 +00007797 listitem_T *item;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00007798 int dummy;
Bram Moolenaar33570922005-01-25 22:26:29 +00007799 dict_T *selfdict = NULL;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00007800
7801 rettv->vval.v_number = 0;
7802 if (argvars[1].v_type != VAR_LIST)
7803 {
7804 EMSG(_(e_listreq));
7805 return;
7806 }
7807 if (argvars[1].vval.v_list == NULL)
7808 return;
7809
7810 if (argvars[0].v_type == VAR_FUNC)
7811 func = argvars[0].vval.v_string;
7812 else
7813 func = get_tv_string(&argvars[0]);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00007814 if (*func == NUL)
7815 return; /* type error or empty name */
Bram Moolenaar8a283e52005-01-06 23:28:25 +00007816
Bram Moolenaare9a41262005-01-15 22:18:47 +00007817 if (argvars[2].v_type != VAR_UNKNOWN)
7818 {
7819 if (argvars[2].v_type != VAR_DICT)
7820 {
7821 EMSG(_(e_dictreq));
7822 return;
7823 }
7824 selfdict = argvars[2].vval.v_dict;
7825 }
7826
Bram Moolenaar8a283e52005-01-06 23:28:25 +00007827 for (item = argvars[1].vval.v_list->lv_first; item != NULL;
7828 item = item->li_next)
7829 {
7830 if (argc == MAX_FUNC_ARGS)
7831 {
Bram Moolenaare49b69a2005-01-08 16:11:57 +00007832 EMSG(_("E699: Too many arguments"));
Bram Moolenaar8a283e52005-01-06 23:28:25 +00007833 break;
7834 }
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00007835 /* Make a copy of each argument. This is needed to be able to set
7836 * v_lock to VAR_FIXED in the copy without changing the original list.
7837 */
Bram Moolenaar8a283e52005-01-06 23:28:25 +00007838 copy_tv(&item->li_tv, &argv[argc++]);
7839 }
7840
7841 if (item == NULL)
7842 (void)call_func(func, STRLEN(func), rettv, argc, argv,
Bram Moolenaare9a41262005-01-15 22:18:47 +00007843 curwin->w_cursor.lnum, curwin->w_cursor.lnum,
7844 &dummy, TRUE, selfdict);
Bram Moolenaar8a283e52005-01-06 23:28:25 +00007845
7846 /* Free the arguments. */
7847 while (argc > 0)
7848 clear_tv(&argv[--argc]);
7849}
7850
7851/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00007852 * "char2nr(string)" function
7853 */
7854 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007855f_char2nr(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007856 typval_T *argvars;
7857 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007858{
7859#ifdef FEAT_MBYTE
7860 if (has_mbyte)
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00007861 rettv->vval.v_number = (*mb_ptr2char)(get_tv_string(&argvars[0]));
Bram Moolenaar071d4272004-06-13 20:20:40 +00007862 else
7863#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007864 rettv->vval.v_number = get_tv_string(&argvars[0])[0];
Bram Moolenaar071d4272004-06-13 20:20:40 +00007865}
7866
7867/*
7868 * "cindent(lnum)" function
7869 */
7870 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007871f_cindent(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007872 typval_T *argvars;
7873 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007874{
7875#ifdef FEAT_CINDENT
7876 pos_T pos;
7877 linenr_T lnum;
7878
7879 pos = curwin->w_cursor;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007880 lnum = get_tv_lnum(argvars);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007881 if (lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count)
7882 {
7883 curwin->w_cursor.lnum = lnum;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007884 rettv->vval.v_number = get_c_indent();
Bram Moolenaar071d4272004-06-13 20:20:40 +00007885 curwin->w_cursor = pos;
7886 }
7887 else
7888#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007889 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007890}
7891
7892/*
7893 * "col(string)" function
7894 */
7895 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007896f_col(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007897 typval_T *argvars;
7898 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007899{
7900 colnr_T col = 0;
7901 pos_T *fp;
7902
7903 fp = var2fpos(&argvars[0], FALSE);
7904 if (fp != NULL)
7905 {
7906 if (fp->col == MAXCOL)
7907 {
7908 /* '> can be MAXCOL, get the length of the line then */
7909 if (fp->lnum <= curbuf->b_ml.ml_line_count)
7910 col = STRLEN(ml_get(fp->lnum)) + 1;
7911 else
7912 col = MAXCOL;
7913 }
7914 else
7915 {
7916 col = fp->col + 1;
7917#ifdef FEAT_VIRTUALEDIT
7918 /* col(".") when the cursor is on the NUL at the end of the line
7919 * because of "coladd" can be seen as an extra column. */
7920 if (virtual_active() && fp == &curwin->w_cursor)
7921 {
7922 char_u *p = ml_get_cursor();
7923
7924 if (curwin->w_cursor.coladd >= (colnr_T)chartabsize(p,
7925 curwin->w_virtcol - curwin->w_cursor.coladd))
7926 {
7927# ifdef FEAT_MBYTE
7928 int l;
7929
Bram Moolenaar0fa313a2005-08-10 21:07:57 +00007930 if (*p != NUL && p[(l = (*mb_ptr2len)(p))] == NUL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007931 col += l;
7932# else
7933 if (*p != NUL && p[1] == NUL)
7934 ++col;
7935# endif
7936 }
7937 }
7938#endif
7939 }
7940 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007941 rettv->vval.v_number = col;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007942}
7943
Bram Moolenaar572cb562005-08-05 21:35:02 +00007944#if defined(FEAT_INS_EXPAND)
7945/*
7946 * "complete_add()" function
7947 */
7948/*ARGSUSED*/
7949 static void
7950f_complete_add(argvars, rettv)
7951 typval_T *argvars;
7952 typval_T *rettv;
7953{
7954 char_u *s;
7955
7956 s = get_tv_string_chk(&argvars[0]);
7957 if (s != NULL)
7958 rettv->vval.v_number = ins_compl_add(s, -1, NULL, FORWARD, 0);
7959}
7960
7961/*
7962 * "complete_check()" function
7963 */
7964/*ARGSUSED*/
7965 static void
7966f_complete_check(argvars, rettv)
7967 typval_T *argvars;
7968 typval_T *rettv;
7969{
7970 int saved = RedrawingDisabled;
7971
7972 RedrawingDisabled = 0;
7973 ins_compl_check_keys(0);
7974 rettv->vval.v_number = compl_interrupted;
7975 RedrawingDisabled = saved;
7976}
7977#endif
7978
Bram Moolenaar071d4272004-06-13 20:20:40 +00007979/*
7980 * "confirm(message, buttons[, default [, type]])" function
7981 */
7982/*ARGSUSED*/
7983 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007984f_confirm(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007985 typval_T *argvars;
7986 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007987{
7988#if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
7989 char_u *message;
7990 char_u *buttons = NULL;
7991 char_u buf[NUMBUFLEN];
7992 char_u buf2[NUMBUFLEN];
7993 int def = 1;
7994 int type = VIM_GENERIC;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00007995 char_u *typestr;
7996 int error = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007997
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00007998 message = get_tv_string_chk(&argvars[0]);
7999 if (message == NULL)
8000 error = TRUE;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008001 if (argvars[1].v_type != VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008002 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00008003 buttons = get_tv_string_buf_chk(&argvars[1], buf);
8004 if (buttons == NULL)
8005 error = TRUE;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008006 if (argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008007 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00008008 def = get_tv_number_chk(&argvars[2], &error);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008009 if (argvars[3].v_type != VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008010 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00008011 typestr = get_tv_string_buf_chk(&argvars[3], buf2);
8012 if (typestr == NULL)
8013 error = TRUE;
8014 else
Bram Moolenaar071d4272004-06-13 20:20:40 +00008015 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00008016 switch (TOUPPER_ASC(*typestr))
8017 {
8018 case 'E': type = VIM_ERROR; break;
8019 case 'Q': type = VIM_QUESTION; break;
8020 case 'I': type = VIM_INFO; break;
8021 case 'W': type = VIM_WARNING; break;
8022 case 'G': type = VIM_GENERIC; break;
8023 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00008024 }
8025 }
8026 }
8027 }
8028
8029 if (buttons == NULL || *buttons == NUL)
8030 buttons = (char_u *)_("&Ok");
8031
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00008032 if (error)
8033 rettv->vval.v_number = 0;
8034 else
8035 rettv->vval.v_number = do_dialog(type, NULL, message, buttons,
Bram Moolenaar071d4272004-06-13 20:20:40 +00008036 def, NULL);
8037#else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008038 rettv->vval.v_number = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008039#endif
8040}
8041
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008042/*
8043 * "copy()" function
8044 */
8045 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008046f_copy(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008047 typval_T *argvars;
8048 typval_T *rettv;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008049{
Bram Moolenaar81bf7082005-02-12 14:31:42 +00008050 item_copy(&argvars[0], rettv, FALSE, 0);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008051}
Bram Moolenaar071d4272004-06-13 20:20:40 +00008052
8053/*
Bram Moolenaar8a283e52005-01-06 23:28:25 +00008054 * "count()" function
8055 */
8056 static void
8057f_count(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008058 typval_T *argvars;
8059 typval_T *rettv;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00008060{
Bram Moolenaar8a283e52005-01-06 23:28:25 +00008061 long n = 0;
8062 int ic = FALSE;
8063
Bram Moolenaare9a41262005-01-15 22:18:47 +00008064 if (argvars[0].v_type == VAR_LIST)
Bram Moolenaar8a283e52005-01-06 23:28:25 +00008065 {
Bram Moolenaar33570922005-01-25 22:26:29 +00008066 listitem_T *li;
8067 list_T *l;
Bram Moolenaare9a41262005-01-15 22:18:47 +00008068 long idx;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00008069
Bram Moolenaare9a41262005-01-15 22:18:47 +00008070 if ((l = argvars[0].vval.v_list) != NULL)
8071 {
8072 li = l->lv_first;
8073 if (argvars[2].v_type != VAR_UNKNOWN)
8074 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00008075 int error = FALSE;
8076
8077 ic = get_tv_number_chk(&argvars[2], &error);
Bram Moolenaare9a41262005-01-15 22:18:47 +00008078 if (argvars[3].v_type != VAR_UNKNOWN)
8079 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00008080 idx = get_tv_number_chk(&argvars[3], &error);
8081 if (!error)
8082 {
8083 li = list_find(l, idx);
8084 if (li == NULL)
8085 EMSGN(_(e_listidx), idx);
8086 }
Bram Moolenaare9a41262005-01-15 22:18:47 +00008087 }
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00008088 if (error)
8089 li = NULL;
Bram Moolenaare9a41262005-01-15 22:18:47 +00008090 }
8091
8092 for ( ; li != NULL; li = li->li_next)
8093 if (tv_equal(&li->li_tv, &argvars[1], ic))
8094 ++n;
8095 }
Bram Moolenaar8a283e52005-01-06 23:28:25 +00008096 }
Bram Moolenaare9a41262005-01-15 22:18:47 +00008097 else if (argvars[0].v_type == VAR_DICT)
8098 {
Bram Moolenaar33570922005-01-25 22:26:29 +00008099 int todo;
8100 dict_T *d;
8101 hashitem_T *hi;
Bram Moolenaare9a41262005-01-15 22:18:47 +00008102
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00008103 if ((d = argvars[0].vval.v_dict) != NULL)
8104 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00008105 int error = FALSE;
8106
Bram Moolenaare9a41262005-01-15 22:18:47 +00008107 if (argvars[2].v_type != VAR_UNKNOWN)
8108 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00008109 ic = get_tv_number_chk(&argvars[2], &error);
Bram Moolenaare9a41262005-01-15 22:18:47 +00008110 if (argvars[3].v_type != VAR_UNKNOWN)
8111 EMSG(_(e_invarg));
8112 }
8113
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00008114 todo = error ? 0 : d->dv_hashtab.ht_used;
Bram Moolenaar33570922005-01-25 22:26:29 +00008115 for (hi = d->dv_hashtab.ht_array; todo > 0; ++hi)
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00008116 {
8117 if (!HASHITEM_EMPTY(hi))
8118 {
8119 --todo;
8120 if (tv_equal(&HI2DI(hi)->di_tv, &argvars[1], ic))
8121 ++n;
8122 }
8123 }
Bram Moolenaare9a41262005-01-15 22:18:47 +00008124 }
8125 }
8126 else
8127 EMSG2(_(e_listdictarg), "count()");
Bram Moolenaar8a283e52005-01-06 23:28:25 +00008128 rettv->vval.v_number = n;
8129}
8130
8131/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00008132 * "cscope_connection([{num} , {dbpath} [, {prepend}]])" function
8133 *
8134 * Checks the existence of a cscope connection.
8135 */
8136/*ARGSUSED*/
8137 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008138f_cscope_connection(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008139 typval_T *argvars;
8140 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008141{
8142#ifdef FEAT_CSCOPE
8143 int num = 0;
8144 char_u *dbpath = NULL;
8145 char_u *prepend = NULL;
8146 char_u buf[NUMBUFLEN];
8147
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008148 if (argvars[0].v_type != VAR_UNKNOWN
8149 && argvars[1].v_type != VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008150 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008151 num = (int)get_tv_number(&argvars[0]);
8152 dbpath = get_tv_string(&argvars[1]);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008153 if (argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008154 prepend = get_tv_string_buf(&argvars[2], buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008155 }
8156
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008157 rettv->vval.v_number = cs_connection(num, dbpath, prepend);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008158#else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008159 rettv->vval.v_number = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008160#endif
8161}
8162
8163/*
8164 * "cursor(lnum, col)" function
8165 *
8166 * Moves the cursor to the specified line and column
8167 */
8168/*ARGSUSED*/
8169 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008170f_cursor(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008171 typval_T *argvars;
8172 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008173{
8174 long line, col;
8175
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008176 line = get_tv_lnum(argvars);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00008177 col = get_tv_number_chk(&argvars[1], NULL);
8178 if (line < 0 || col < 0)
8179 return; /* type error; errmsg already given */
Bram Moolenaar071d4272004-06-13 20:20:40 +00008180 if (line > 0)
8181 curwin->w_cursor.lnum = line;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008182 if (col > 0)
8183 curwin->w_cursor.col = col - 1;
8184#ifdef FEAT_VIRTUALEDIT
8185 curwin->w_cursor.coladd = 0;
8186#endif
8187
8188 /* Make sure the cursor is in a valid position. */
8189 check_cursor();
8190#ifdef FEAT_MBYTE
8191 /* Correct cursor for multi-byte character. */
8192 if (has_mbyte)
8193 mb_adjust_cursor();
8194#endif
Bram Moolenaarf4b8e572004-06-24 15:53:16 +00008195
8196 curwin->w_set_curswant = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008197}
8198
8199/*
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008200 * "deepcopy()" function
Bram Moolenaar071d4272004-06-13 20:20:40 +00008201 */
8202 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008203f_deepcopy(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008204 typval_T *argvars;
8205 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008206{
Bram Moolenaar81bf7082005-02-12 14:31:42 +00008207 int noref = 0;
8208
8209 if (argvars[1].v_type != VAR_UNKNOWN)
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00008210 noref = get_tv_number_chk(&argvars[1], NULL);
Bram Moolenaar81bf7082005-02-12 14:31:42 +00008211 if (noref < 0 || noref > 1)
8212 EMSG(_(e_invarg));
8213 else
Bram Moolenaard9fba312005-06-26 22:34:35 +00008214 item_copy(&argvars[0], rettv, TRUE, noref == 0 ? ++current_copyID : 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008215}
8216
8217/*
8218 * "delete()" function
8219 */
8220 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008221f_delete(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008222 typval_T *argvars;
8223 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008224{
8225 if (check_restricted() || check_secure())
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008226 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008227 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008228 rettv->vval.v_number = mch_remove(get_tv_string(&argvars[0]));
Bram Moolenaar071d4272004-06-13 20:20:40 +00008229}
8230
8231/*
8232 * "did_filetype()" function
8233 */
8234/*ARGSUSED*/
8235 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008236f_did_filetype(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008237 typval_T *argvars;
8238 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008239{
8240#ifdef FEAT_AUTOCMD
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008241 rettv->vval.v_number = did_filetype;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008242#else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008243 rettv->vval.v_number = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008244#endif
8245}
8246
8247/*
Bram Moolenaar47136d72004-10-12 20:02:24 +00008248 * "diff_filler()" function
8249 */
8250/*ARGSUSED*/
8251 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008252f_diff_filler(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008253 typval_T *argvars;
8254 typval_T *rettv;
Bram Moolenaar47136d72004-10-12 20:02:24 +00008255{
8256#ifdef FEAT_DIFF
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008257 rettv->vval.v_number = diff_check_fill(curwin, get_tv_lnum(argvars));
Bram Moolenaar47136d72004-10-12 20:02:24 +00008258#endif
8259}
8260
8261/*
8262 * "diff_hlID()" function
8263 */
8264/*ARGSUSED*/
8265 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008266f_diff_hlID(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008267 typval_T *argvars;
8268 typval_T *rettv;
Bram Moolenaar47136d72004-10-12 20:02:24 +00008269{
8270#ifdef FEAT_DIFF
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008271 linenr_T lnum = get_tv_lnum(argvars);
Bram Moolenaar47136d72004-10-12 20:02:24 +00008272 static linenr_T prev_lnum = 0;
8273 static int changedtick = 0;
8274 static int fnum = 0;
8275 static int change_start = 0;
8276 static int change_end = 0;
Bram Moolenaar482aaeb2005-09-29 18:26:07 +00008277 static hlf_T hlID = 0;
Bram Moolenaar47136d72004-10-12 20:02:24 +00008278 int filler_lines;
8279 int col;
8280
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00008281 if (lnum < 0) /* ignore type error in {lnum} arg */
8282 lnum = 0;
Bram Moolenaar47136d72004-10-12 20:02:24 +00008283 if (lnum != prev_lnum
8284 || changedtick != curbuf->b_changedtick
8285 || fnum != curbuf->b_fnum)
8286 {
8287 /* New line, buffer, change: need to get the values. */
8288 filler_lines = diff_check(curwin, lnum);
8289 if (filler_lines < 0)
8290 {
8291 if (filler_lines == -1)
8292 {
8293 change_start = MAXCOL;
8294 change_end = -1;
8295 if (diff_find_change(curwin, lnum, &change_start, &change_end))
8296 hlID = HLF_ADD; /* added line */
8297 else
8298 hlID = HLF_CHD; /* changed line */
8299 }
8300 else
8301 hlID = HLF_ADD; /* added line */
8302 }
8303 else
Bram Moolenaar482aaeb2005-09-29 18:26:07 +00008304 hlID = (hlf_T)0;
Bram Moolenaar47136d72004-10-12 20:02:24 +00008305 prev_lnum = lnum;
8306 changedtick = curbuf->b_changedtick;
8307 fnum = curbuf->b_fnum;
8308 }
8309
8310 if (hlID == HLF_CHD || hlID == HLF_TXD)
8311 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00008312 col = get_tv_number(&argvars[1]) - 1; /* ignore type error in {col} */
Bram Moolenaar47136d72004-10-12 20:02:24 +00008313 if (col >= change_start && col <= change_end)
8314 hlID = HLF_TXD; /* changed text */
8315 else
8316 hlID = HLF_CHD; /* changed line */
8317 }
Bram Moolenaar482aaeb2005-09-29 18:26:07 +00008318 rettv->vval.v_number = hlID == (hlf_T)0 ? 0 : (int)hlID;
Bram Moolenaar47136d72004-10-12 20:02:24 +00008319#endif
8320}
8321
8322/*
Bram Moolenaare49b69a2005-01-08 16:11:57 +00008323 * "empty({expr})" function
8324 */
8325 static void
8326f_empty(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008327 typval_T *argvars;
8328 typval_T *rettv;
Bram Moolenaare49b69a2005-01-08 16:11:57 +00008329{
8330 int n;
8331
8332 switch (argvars[0].v_type)
8333 {
8334 case VAR_STRING:
8335 case VAR_FUNC:
8336 n = argvars[0].vval.v_string == NULL
8337 || *argvars[0].vval.v_string == NUL;
8338 break;
8339 case VAR_NUMBER:
8340 n = argvars[0].vval.v_number == 0;
8341 break;
8342 case VAR_LIST:
8343 n = argvars[0].vval.v_list == NULL
8344 || argvars[0].vval.v_list->lv_first == NULL;
8345 break;
Bram Moolenaare9a41262005-01-15 22:18:47 +00008346 case VAR_DICT:
8347 n = argvars[0].vval.v_dict == NULL
Bram Moolenaar33570922005-01-25 22:26:29 +00008348 || argvars[0].vval.v_dict->dv_hashtab.ht_used == 0;
Bram Moolenaare9a41262005-01-15 22:18:47 +00008349 break;
Bram Moolenaare49b69a2005-01-08 16:11:57 +00008350 default:
8351 EMSG2(_(e_intern2), "f_empty()");
8352 n = 0;
8353 }
8354
8355 rettv->vval.v_number = n;
8356}
8357
8358/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00008359 * "escape({string}, {chars})" function
8360 */
8361 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008362f_escape(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008363 typval_T *argvars;
8364 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008365{
8366 char_u buf[NUMBUFLEN];
8367
Bram Moolenaar758711c2005-02-02 23:11:38 +00008368 rettv->vval.v_string = vim_strsave_escaped(get_tv_string(&argvars[0]),
8369 get_tv_string_buf(&argvars[1], buf));
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008370 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008371}
8372
8373/*
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00008374 * "eval()" function
8375 */
8376/*ARGSUSED*/
8377 static void
8378f_eval(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008379 typval_T *argvars;
8380 typval_T *rettv;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00008381{
8382 char_u *s;
8383
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00008384 s = get_tv_string_chk(&argvars[0]);
8385 if (s != NULL)
8386 s = skipwhite(s);
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00008387
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00008388 if (s == NULL || eval1(&s, rettv, TRUE) == FAIL)
8389 {
8390 rettv->v_type = VAR_NUMBER;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00008391 rettv->vval.v_number = 0;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00008392 }
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00008393 else if (*s != NUL)
8394 EMSG(_(e_trailing));
8395}
8396
8397/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00008398 * "eventhandler()" function
8399 */
8400/*ARGSUSED*/
8401 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008402f_eventhandler(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008403 typval_T *argvars;
8404 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008405{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008406 rettv->vval.v_number = vgetc_busy;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008407}
8408
8409/*
8410 * "executable()" function
8411 */
8412 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008413f_executable(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008414 typval_T *argvars;
8415 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008416{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008417 rettv->vval.v_number = mch_can_exe(get_tv_string(&argvars[0]));
Bram Moolenaar071d4272004-06-13 20:20:40 +00008418}
8419
8420/*
8421 * "exists()" function
8422 */
8423 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008424f_exists(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008425 typval_T *argvars;
8426 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008427{
8428 char_u *p;
8429 char_u *name;
8430 int n = FALSE;
8431 int len = 0;
8432
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008433 p = get_tv_string(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008434 if (*p == '$') /* environment variable */
8435 {
8436 /* first try "normal" environment variables (fast) */
8437 if (mch_getenv(p + 1) != NULL)
8438 n = TRUE;
8439 else
8440 {
8441 /* try expanding things like $VIM and ${HOME} */
8442 p = expand_env_save(p);
8443 if (p != NULL && *p != '$')
8444 n = TRUE;
8445 vim_free(p);
8446 }
8447 }
8448 else if (*p == '&' || *p == '+') /* option */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008449 n = (get_option_tv(&p, NULL, TRUE) == OK);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008450 else if (*p == '*') /* internal or user defined function */
8451 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008452 n = function_exists(p + 1);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008453 }
8454 else if (*p == ':')
8455 {
8456 n = cmd_exists(p + 1);
8457 }
8458 else if (*p == '#')
8459 {
8460#ifdef FEAT_AUTOCMD
8461 name = p + 1;
8462 p = vim_strchr(name, '#');
8463 if (p != NULL)
8464 n = au_exists(name, p, p + 1);
8465 else
8466 n = au_exists(name, name + STRLEN(name), NULL);
8467#endif
8468 }
8469 else /* internal variable */
8470 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00008471 char_u *tofree;
8472 typval_T tv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008473
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00008474 /* get_name_len() takes care of expanding curly braces */
8475 name = p;
8476 len = get_name_len(&p, &tofree, TRUE, FALSE);
8477 if (len > 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008478 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00008479 if (tofree != NULL)
8480 name = tofree;
8481 n = (get_var_tv(name, len, &tv, FALSE) == OK);
8482 if (n)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008483 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00008484 /* handle d.key, l[idx], f(expr) */
8485 n = (handle_subscript(&p, &tv, TRUE, FALSE) == OK);
8486 if (n)
8487 clear_tv(&tv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008488 }
8489 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00008490
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00008491 vim_free(tofree);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008492 }
8493
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008494 rettv->vval.v_number = n;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008495}
8496
8497/*
8498 * "expand()" function
8499 */
8500 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008501f_expand(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008502 typval_T *argvars;
8503 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008504{
8505 char_u *s;
8506 int len;
8507 char_u *errormsg;
8508 int flags = WILD_SILENT|WILD_USE_NL|WILD_LIST_NOTFOUND;
8509 expand_T xpc;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00008510 int error = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008511
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008512 rettv->v_type = VAR_STRING;
8513 s = get_tv_string(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008514 if (*s == '%' || *s == '#' || *s == '<')
8515 {
8516 ++emsg_off;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008517 rettv->vval.v_string = eval_vars(s, &len, NULL, &errormsg, s);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008518 --emsg_off;
8519 }
8520 else
8521 {
8522 /* When the optional second argument is non-zero, don't remove matches
8523 * for 'suffixes' and 'wildignore' */
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00008524 if (argvars[1].v_type != VAR_UNKNOWN
8525 && get_tv_number_chk(&argvars[1], &error))
Bram Moolenaar071d4272004-06-13 20:20:40 +00008526 flags |= WILD_KEEP_ALL;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00008527 if (!error)
8528 {
8529 ExpandInit(&xpc);
8530 xpc.xp_context = EXPAND_FILES;
8531 rettv->vval.v_string = ExpandOne(&xpc, s, NULL, flags, WILD_ALL);
8532 ExpandCleanup(&xpc);
8533 }
8534 else
8535 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008536 }
8537}
8538
8539/*
Bram Moolenaar8a283e52005-01-06 23:28:25 +00008540 * "extend(list, list [, idx])" function
Bram Moolenaare9a41262005-01-15 22:18:47 +00008541 * "extend(dict, dict [, action])" function
Bram Moolenaar8a283e52005-01-06 23:28:25 +00008542 */
8543 static void
8544f_extend(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008545 typval_T *argvars;
8546 typval_T *rettv;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00008547{
Bram Moolenaar8a283e52005-01-06 23:28:25 +00008548 rettv->vval.v_number = 0;
Bram Moolenaare9a41262005-01-15 22:18:47 +00008549 if (argvars[0].v_type == VAR_LIST && argvars[1].v_type == VAR_LIST)
Bram Moolenaar8a283e52005-01-06 23:28:25 +00008550 {
Bram Moolenaar33570922005-01-25 22:26:29 +00008551 list_T *l1, *l2;
8552 listitem_T *item;
Bram Moolenaare9a41262005-01-15 22:18:47 +00008553 long before;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00008554 int error = FALSE;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00008555
Bram Moolenaare9a41262005-01-15 22:18:47 +00008556 l1 = argvars[0].vval.v_list;
8557 l2 = argvars[1].vval.v_list;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00008558 if (l1 != NULL && !tv_check_lock(l1->lv_lock, (char_u *)"extend()")
8559 && l2 != NULL)
Bram Moolenaare9a41262005-01-15 22:18:47 +00008560 {
8561 if (argvars[2].v_type != VAR_UNKNOWN)
8562 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00008563 before = get_tv_number_chk(&argvars[2], &error);
8564 if (error)
8565 return; /* type error; errmsg already given */
8566
Bram Moolenaar758711c2005-02-02 23:11:38 +00008567 if (before == l1->lv_len)
8568 item = NULL;
8569 else
Bram Moolenaare9a41262005-01-15 22:18:47 +00008570 {
Bram Moolenaar758711c2005-02-02 23:11:38 +00008571 item = list_find(l1, before);
8572 if (item == NULL)
8573 {
8574 EMSGN(_(e_listidx), before);
8575 return;
8576 }
Bram Moolenaare9a41262005-01-15 22:18:47 +00008577 }
8578 }
8579 else
8580 item = NULL;
8581 list_extend(l1, l2, item);
8582
Bram Moolenaare9a41262005-01-15 22:18:47 +00008583 copy_tv(&argvars[0], rettv);
8584 }
Bram Moolenaar8a283e52005-01-06 23:28:25 +00008585 }
Bram Moolenaare9a41262005-01-15 22:18:47 +00008586 else if (argvars[0].v_type == VAR_DICT && argvars[1].v_type == VAR_DICT)
8587 {
Bram Moolenaar33570922005-01-25 22:26:29 +00008588 dict_T *d1, *d2;
8589 dictitem_T *di1;
Bram Moolenaare9a41262005-01-15 22:18:47 +00008590 char_u *action;
8591 int i;
Bram Moolenaar33570922005-01-25 22:26:29 +00008592 hashitem_T *hi2;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00008593 int todo;
Bram Moolenaare9a41262005-01-15 22:18:47 +00008594
8595 d1 = argvars[0].vval.v_dict;
8596 d2 = argvars[1].vval.v_dict;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00008597 if (d1 != NULL && !tv_check_lock(d1->dv_lock, (char_u *)"extend()")
8598 && d2 != NULL)
Bram Moolenaare9a41262005-01-15 22:18:47 +00008599 {
8600 /* Check the third argument. */
8601 if (argvars[2].v_type != VAR_UNKNOWN)
8602 {
8603 static char *(av[]) = {"keep", "force", "error"};
8604
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00008605 action = get_tv_string_chk(&argvars[2]);
8606 if (action == NULL)
8607 return; /* type error; errmsg already given */
Bram Moolenaare9a41262005-01-15 22:18:47 +00008608 for (i = 0; i < 3; ++i)
8609 if (STRCMP(action, av[i]) == 0)
8610 break;
8611 if (i == 3)
8612 {
8613 EMSGN(_(e_invarg2), action);
8614 return;
8615 }
8616 }
8617 else
8618 action = (char_u *)"force";
8619
8620 /* Go over all entries in the second dict and add them to the
8621 * first dict. */
Bram Moolenaar33570922005-01-25 22:26:29 +00008622 todo = d2->dv_hashtab.ht_used;
8623 for (hi2 = d2->dv_hashtab.ht_array; todo > 0; ++hi2)
Bram Moolenaare9a41262005-01-15 22:18:47 +00008624 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00008625 if (!HASHITEM_EMPTY(hi2))
Bram Moolenaare9a41262005-01-15 22:18:47 +00008626 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00008627 --todo;
8628 di1 = dict_find(d1, hi2->hi_key, -1);
8629 if (di1 == NULL)
8630 {
8631 di1 = dictitem_copy(HI2DI(hi2));
8632 if (di1 != NULL && dict_add(d1, di1) == FAIL)
8633 dictitem_free(di1);
8634 }
8635 else if (*action == 'e')
8636 {
8637 EMSG2(_("E737: Key already exists: %s"), hi2->hi_key);
8638 break;
8639 }
8640 else if (*action == 'f')
8641 {
8642 clear_tv(&di1->di_tv);
8643 copy_tv(&HI2DI(hi2)->di_tv, &di1->di_tv);
8644 }
Bram Moolenaare9a41262005-01-15 22:18:47 +00008645 }
8646 }
8647
Bram Moolenaare9a41262005-01-15 22:18:47 +00008648 copy_tv(&argvars[0], rettv);
8649 }
8650 }
8651 else
8652 EMSG2(_(e_listdictarg), "extend()");
Bram Moolenaar8a283e52005-01-06 23:28:25 +00008653}
8654
8655/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00008656 * "filereadable()" function
8657 */
8658 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008659f_filereadable(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008660 typval_T *argvars;
8661 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008662{
8663 FILE *fd;
8664 char_u *p;
8665 int n;
8666
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008667 p = get_tv_string(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008668 if (*p && !mch_isdir(p) && (fd = mch_fopen((char *)p, "r")) != NULL)
8669 {
8670 n = TRUE;
8671 fclose(fd);
8672 }
8673 else
8674 n = FALSE;
8675
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008676 rettv->vval.v_number = n;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008677}
8678
8679/*
Bram Moolenaar0e4d8772005-06-07 21:12:49 +00008680 * Return 0 for not writable, 1 for writable file, 2 for a dir which we have
Bram Moolenaar071d4272004-06-13 20:20:40 +00008681 * rights to write into.
8682 */
8683 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008684f_filewritable(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008685 typval_T *argvars;
8686 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008687{
Bram Moolenaar0e4d8772005-06-07 21:12:49 +00008688 rettv->vval.v_number = filewritable(get_tv_string(&argvars[0]));
Bram Moolenaar071d4272004-06-13 20:20:40 +00008689}
8690
Bram Moolenaar33570922005-01-25 22:26:29 +00008691static void findfilendir __ARGS((typval_T *argvars, typval_T *rettv, int dir));
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00008692
8693 static void
Bram Moolenaar0d660222005-01-07 21:51:51 +00008694findfilendir(argvars, rettv, dir)
Bram Moolenaar33570922005-01-25 22:26:29 +00008695 typval_T *argvars;
8696 typval_T *rettv;
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00008697 int dir;
8698{
8699#ifdef FEAT_SEARCHPATH
8700 char_u *fname;
8701 char_u *fresult = NULL;
8702 char_u *path = *curbuf->b_p_path == NUL ? p_path : curbuf->b_p_path;
8703 char_u *p;
8704 char_u pathbuf[NUMBUFLEN];
8705 int count = 1;
8706 int first = TRUE;
8707
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008708 fname = get_tv_string(&argvars[0]);
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00008709
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008710 if (argvars[1].v_type != VAR_UNKNOWN)
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00008711 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00008712 p = get_tv_string_buf_chk(&argvars[1], pathbuf);
8713 if (p == NULL)
8714 count = -1; /* error */
8715 else
8716 {
8717 if (*p != NUL)
8718 path = p;
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00008719
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00008720 if (argvars[2].v_type != VAR_UNKNOWN)
8721 count = get_tv_number_chk(&argvars[2], NULL); /* -1: error */
8722 }
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00008723 }
8724
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00008725 if (*fname != NUL && count >= 0)
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00008726 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00008727 do
8728 {
8729 vim_free(fresult);
8730 fresult = find_file_in_path_option(first ? fname : NULL,
8731 first ? (int)STRLEN(fname) : 0,
8732 0, first, path, dir, NULL);
8733 first = FALSE;
8734 } while (--count > 0 && fresult != NULL);
8735 }
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00008736
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008737 rettv->vval.v_string = fresult;
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00008738#else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008739 rettv->vval.v_string = NULL;
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00008740#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008741 rettv->v_type = VAR_STRING;
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00008742}
8743
Bram Moolenaar33570922005-01-25 22:26:29 +00008744static void filter_map __ARGS((typval_T *argvars, typval_T *rettv, int map));
8745static int filter_map_one __ARGS((typval_T *tv, char_u *expr, int map, int *remp));
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00008746
8747/*
8748 * Implementation of map() and filter().
8749 */
8750 static void
8751filter_map(argvars, rettv, map)
Bram Moolenaar33570922005-01-25 22:26:29 +00008752 typval_T *argvars;
8753 typval_T *rettv;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00008754 int map;
8755{
8756 char_u buf[NUMBUFLEN];
Bram Moolenaare9a41262005-01-15 22:18:47 +00008757 char_u *expr;
Bram Moolenaar33570922005-01-25 22:26:29 +00008758 listitem_T *li, *nli;
8759 list_T *l = NULL;
8760 dictitem_T *di;
8761 hashtab_T *ht;
8762 hashitem_T *hi;
8763 dict_T *d = NULL;
8764 typval_T save_val;
8765 typval_T save_key;
Bram Moolenaare9a41262005-01-15 22:18:47 +00008766 int rem;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00008767 int todo;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00008768 char_u *msg = map ? (char_u *)"map()" : (char_u *)"filter()";
8769
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00008770
8771 rettv->vval.v_number = 0;
Bram Moolenaare9a41262005-01-15 22:18:47 +00008772 if (argvars[0].v_type == VAR_LIST)
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00008773 {
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00008774 if ((l = argvars[0].vval.v_list) == NULL
8775 || (map && tv_check_lock(l->lv_lock, msg)))
Bram Moolenaare9a41262005-01-15 22:18:47 +00008776 return;
8777 }
8778 else if (argvars[0].v_type == VAR_DICT)
8779 {
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00008780 if ((d = argvars[0].vval.v_dict) == NULL
8781 || (map && tv_check_lock(d->dv_lock, msg)))
Bram Moolenaare9a41262005-01-15 22:18:47 +00008782 return;
8783 }
8784 else
8785 {
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00008786 EMSG2(_(e_listdictarg), msg);
Bram Moolenaare9a41262005-01-15 22:18:47 +00008787 return;
8788 }
8789
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00008790 expr = get_tv_string_buf_chk(&argvars[1], buf);
8791 /* On type errors, the preceding call has already displayed an error
8792 * message. Avoid a misleading error message for an empty string that
8793 * was not passed as argument. */
8794 if (expr != NULL)
Bram Moolenaare9a41262005-01-15 22:18:47 +00008795 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00008796 prepare_vimvar(VV_VAL, &save_val);
8797 expr = skipwhite(expr);
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00008798
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00008799 if (argvars[0].v_type == VAR_DICT)
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00008800 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00008801 prepare_vimvar(VV_KEY, &save_key);
8802 vimvars[VV_KEY].vv_type = VAR_STRING;
8803
8804 ht = &d->dv_hashtab;
8805 hash_lock(ht);
8806 todo = ht->ht_used;
8807 for (hi = ht->ht_array; todo > 0; ++hi)
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00008808 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00008809 if (!HASHITEM_EMPTY(hi))
8810 {
8811 --todo;
8812 di = HI2DI(hi);
8813 if (tv_check_lock(di->di_tv.v_lock, msg))
8814 break;
8815 vimvars[VV_KEY].vv_str = vim_strsave(di->di_key);
8816 if (filter_map_one(&di->di_tv, expr, map, &rem) == FAIL)
8817 break;
8818 if (!map && rem)
8819 dictitem_remove(d, di);
8820 clear_tv(&vimvars[VV_KEY].vv_tv);
8821 }
8822 }
8823 hash_unlock(ht);
8824
8825 restore_vimvar(VV_KEY, &save_key);
8826 }
8827 else
8828 {
8829 for (li = l->lv_first; li != NULL; li = nli)
8830 {
8831 if (tv_check_lock(li->li_tv.v_lock, msg))
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00008832 break;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00008833 nli = li->li_next;
8834 if (filter_map_one(&li->li_tv, expr, map, &rem) == FAIL)
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00008835 break;
8836 if (!map && rem)
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00008837 listitem_remove(l, li);
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00008838 }
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00008839 }
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00008840
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00008841 restore_vimvar(VV_VAL, &save_val);
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00008842 }
Bram Moolenaare9a41262005-01-15 22:18:47 +00008843
8844 copy_tv(&argvars[0], rettv);
8845}
8846
8847 static int
8848filter_map_one(tv, expr, map, remp)
Bram Moolenaar33570922005-01-25 22:26:29 +00008849 typval_T *tv;
Bram Moolenaare9a41262005-01-15 22:18:47 +00008850 char_u *expr;
8851 int map;
8852 int *remp;
8853{
Bram Moolenaar33570922005-01-25 22:26:29 +00008854 typval_T rettv;
Bram Moolenaare9a41262005-01-15 22:18:47 +00008855 char_u *s;
8856
Bram Moolenaar33570922005-01-25 22:26:29 +00008857 copy_tv(tv, &vimvars[VV_VAL].vv_tv);
Bram Moolenaare9a41262005-01-15 22:18:47 +00008858 s = expr;
8859 if (eval1(&s, &rettv, TRUE) == FAIL)
8860 return FAIL;
8861 if (*s != NUL) /* check for trailing chars after expr */
8862 {
8863 EMSG2(_(e_invexpr2), s);
8864 return FAIL;
8865 }
8866 if (map)
8867 {
8868 /* map(): replace the list item value */
8869 clear_tv(tv);
Bram Moolenaar4463f292005-09-25 22:20:24 +00008870 rettv.v_lock = 0;
Bram Moolenaare9a41262005-01-15 22:18:47 +00008871 *tv = rettv;
8872 }
8873 else
8874 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00008875 int error = FALSE;
8876
Bram Moolenaare9a41262005-01-15 22:18:47 +00008877 /* filter(): when expr is zero remove the item */
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00008878 *remp = (get_tv_number_chk(&rettv, &error) == 0);
Bram Moolenaare9a41262005-01-15 22:18:47 +00008879 clear_tv(&rettv);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00008880 /* On type error, nothing has been removed; return FAIL to stop the
8881 * loop. The error message was given by get_tv_number_chk(). */
8882 if (error)
8883 return FAIL;
Bram Moolenaare9a41262005-01-15 22:18:47 +00008884 }
Bram Moolenaar33570922005-01-25 22:26:29 +00008885 clear_tv(&vimvars[VV_VAL].vv_tv);
Bram Moolenaare9a41262005-01-15 22:18:47 +00008886 return OK;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00008887}
8888
8889/*
8890 * "filter()" function
8891 */
8892 static void
8893f_filter(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008894 typval_T *argvars;
8895 typval_T *rettv;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00008896{
8897 filter_map(argvars, rettv, FALSE);
8898}
8899
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00008900/*
Bram Moolenaar0d660222005-01-07 21:51:51 +00008901 * "finddir({fname}[, {path}[, {count}]])" function
8902 */
8903 static void
8904f_finddir(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008905 typval_T *argvars;
8906 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +00008907{
8908 findfilendir(argvars, rettv, TRUE);
8909}
8910
8911/*
8912 * "findfile({fname}[, {path}[, {count}]])" function
8913 */
8914 static void
8915f_findfile(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008916 typval_T *argvars;
8917 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +00008918{
8919 findfilendir(argvars, rettv, FALSE);
8920}
8921
8922/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00008923 * "fnamemodify({fname}, {mods})" function
8924 */
8925 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008926f_fnamemodify(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008927 typval_T *argvars;
8928 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008929{
8930 char_u *fname;
8931 char_u *mods;
8932 int usedlen = 0;
8933 int len;
8934 char_u *fbuf = NULL;
8935 char_u buf[NUMBUFLEN];
8936
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00008937 fname = get_tv_string_chk(&argvars[0]);
8938 mods = get_tv_string_buf_chk(&argvars[1], buf);
8939 if (fname == NULL || mods == NULL)
8940 fname = NULL;
8941 else
8942 {
8943 len = (int)STRLEN(fname);
8944 (void)modify_fname(mods, &usedlen, &fname, &fbuf, &len);
8945 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00008946
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008947 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008948 if (fname == NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008949 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008950 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008951 rettv->vval.v_string = vim_strnsave(fname, len);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008952 vim_free(fbuf);
8953}
8954
Bram Moolenaar33570922005-01-25 22:26:29 +00008955static void foldclosed_both __ARGS((typval_T *argvars, typval_T *rettv, int end));
Bram Moolenaar071d4272004-06-13 20:20:40 +00008956
8957/*
8958 * "foldclosed()" function
8959 */
8960 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008961foldclosed_both(argvars, rettv, end)
Bram Moolenaar33570922005-01-25 22:26:29 +00008962 typval_T *argvars;
8963 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008964 int end;
8965{
8966#ifdef FEAT_FOLDING
8967 linenr_T lnum;
8968 linenr_T first, last;
8969
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008970 lnum = get_tv_lnum(argvars);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008971 if (lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count)
8972 {
8973 if (hasFoldingWin(curwin, lnum, &first, &last, FALSE, NULL))
8974 {
8975 if (end)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008976 rettv->vval.v_number = (varnumber_T)last;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008977 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008978 rettv->vval.v_number = (varnumber_T)first;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008979 return;
8980 }
8981 }
8982#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008983 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008984}
8985
8986/*
Bram Moolenaar0d660222005-01-07 21:51:51 +00008987 * "foldclosed()" function
8988 */
8989 static void
8990f_foldclosed(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008991 typval_T *argvars;
8992 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +00008993{
8994 foldclosed_both(argvars, rettv, FALSE);
8995}
8996
8997/*
8998 * "foldclosedend()" function
8999 */
9000 static void
9001f_foldclosedend(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00009002 typval_T *argvars;
9003 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +00009004{
9005 foldclosed_both(argvars, rettv, TRUE);
9006}
9007
9008/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00009009 * "foldlevel()" function
9010 */
9011 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009012f_foldlevel(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#ifdef FEAT_FOLDING
9017 linenr_T lnum;
9018
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009019 lnum = get_tv_lnum(argvars);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009020 if (lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009021 rettv->vval.v_number = foldLevel(lnum);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009022 else
9023#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009024 rettv->vval.v_number = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009025}
9026
9027/*
9028 * "foldtext()" function
9029 */
9030/*ARGSUSED*/
9031 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009032f_foldtext(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00009033 typval_T *argvars;
9034 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009035{
9036#ifdef FEAT_FOLDING
9037 linenr_T lnum;
9038 char_u *s;
9039 char_u *r;
9040 int len;
9041 char *txt;
9042#endif
9043
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009044 rettv->v_type = VAR_STRING;
9045 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009046#ifdef FEAT_FOLDING
Bram Moolenaare9a41262005-01-15 22:18:47 +00009047 if ((linenr_T)vimvars[VV_FOLDSTART].vv_nr > 0
9048 && (linenr_T)vimvars[VV_FOLDEND].vv_nr
9049 <= curbuf->b_ml.ml_line_count
9050 && vimvars[VV_FOLDDASHES].vv_str != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009051 {
9052 /* Find first non-empty line in the fold. */
Bram Moolenaare9a41262005-01-15 22:18:47 +00009053 lnum = (linenr_T)vimvars[VV_FOLDSTART].vv_nr;
9054 while (lnum < (linenr_T)vimvars[VV_FOLDEND].vv_nr)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009055 {
9056 if (!linewhite(lnum))
9057 break;
9058 ++lnum;
9059 }
9060
9061 /* Find interesting text in this line. */
9062 s = skipwhite(ml_get(lnum));
9063 /* skip C comment-start */
9064 if (s[0] == '/' && (s[1] == '*' || s[1] == '/'))
Bram Moolenaar293ee4d2004-12-09 21:34:53 +00009065 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00009066 s = skipwhite(s + 2);
Bram Moolenaar293ee4d2004-12-09 21:34:53 +00009067 if (*skipwhite(s) == NUL
Bram Moolenaare9a41262005-01-15 22:18:47 +00009068 && lnum + 1 < (linenr_T)vimvars[VV_FOLDEND].vv_nr)
Bram Moolenaar293ee4d2004-12-09 21:34:53 +00009069 {
9070 s = skipwhite(ml_get(lnum + 1));
9071 if (*s == '*')
9072 s = skipwhite(s + 1);
9073 }
9074 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00009075 txt = _("+-%s%3ld lines: ");
9076 r = alloc((unsigned)(STRLEN(txt)
Bram Moolenaare9a41262005-01-15 22:18:47 +00009077 + STRLEN(vimvars[VV_FOLDDASHES].vv_str) /* for %s */
Bram Moolenaar071d4272004-06-13 20:20:40 +00009078 + 20 /* for %3ld */
9079 + STRLEN(s))); /* concatenated */
9080 if (r != NULL)
9081 {
Bram Moolenaare9a41262005-01-15 22:18:47 +00009082 sprintf((char *)r, txt, vimvars[VV_FOLDDASHES].vv_str,
9083 (long)((linenr_T)vimvars[VV_FOLDEND].vv_nr
9084 - (linenr_T)vimvars[VV_FOLDSTART].vv_nr + 1));
Bram Moolenaar071d4272004-06-13 20:20:40 +00009085 len = (int)STRLEN(r);
9086 STRCAT(r, s);
9087 /* remove 'foldmarker' and 'commentstring' */
9088 foldtext_cleanup(r + len);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009089 rettv->vval.v_string = r;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009090 }
9091 }
9092#endif
9093}
9094
9095/*
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00009096 * "foldtextresult(lnum)" function
9097 */
9098/*ARGSUSED*/
9099 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009100f_foldtextresult(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00009101 typval_T *argvars;
9102 typval_T *rettv;
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00009103{
9104#ifdef FEAT_FOLDING
9105 linenr_T lnum;
9106 char_u *text;
9107 char_u buf[51];
9108 foldinfo_T foldinfo;
9109 int fold_count;
9110#endif
9111
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009112 rettv->v_type = VAR_STRING;
9113 rettv->vval.v_string = NULL;
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00009114#ifdef FEAT_FOLDING
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009115 lnum = get_tv_lnum(argvars);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00009116 /* treat illegal types and illegal string values for {lnum} the same */
9117 if (lnum < 0)
9118 lnum = 0;
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00009119 fold_count = foldedCount(curwin, lnum, &foldinfo);
9120 if (fold_count > 0)
9121 {
9122 text = get_foldtext(curwin, lnum, lnum + fold_count - 1,
9123 &foldinfo, buf);
9124 if (text == buf)
9125 text = vim_strsave(text);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009126 rettv->vval.v_string = text;
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00009127 }
9128#endif
9129}
9130
9131/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00009132 * "foreground()" function
9133 */
9134/*ARGSUSED*/
9135 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009136f_foreground(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00009137 typval_T *argvars;
9138 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009139{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009140 rettv->vval.v_number = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009141#ifdef FEAT_GUI
9142 if (gui.in_use)
9143 gui_mch_set_foreground();
9144#else
9145# ifdef WIN32
9146 win32_set_foreground();
9147# endif
9148#endif
9149}
9150
9151/*
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009152 * "function()" function
9153 */
9154/*ARGSUSED*/
9155 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009156f_function(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00009157 typval_T *argvars;
9158 typval_T *rettv;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009159{
9160 char_u *s;
9161
Bram Moolenaara7043832005-01-21 11:56:39 +00009162 rettv->vval.v_number = 0;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009163 s = get_tv_string(&argvars[0]);
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00009164 if (s == NULL || *s == NUL || VIM_ISDIGIT(*s))
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009165 EMSG2(_(e_invarg2), s);
9166 else if (!function_exists(s))
Bram Moolenaare49b69a2005-01-08 16:11:57 +00009167 EMSG2(_("E700: Unknown function: %s"), s);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009168 else
9169 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009170 rettv->vval.v_string = vim_strsave(s);
9171 rettv->v_type = VAR_FUNC;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009172 }
9173}
9174
9175/*
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +00009176 * "garbagecollect()" function
9177 */
9178/*ARGSUSED*/
9179 static void
9180f_garbagecollect(argvars, rettv)
9181 typval_T *argvars;
9182 typval_T *rettv;
9183{
9184 garbage_collect();
9185}
9186
9187/*
Bram Moolenaar0d660222005-01-07 21:51:51 +00009188 * "get()" function
9189 */
9190 static void
9191f_get(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00009192 typval_T *argvars;
9193 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +00009194{
Bram Moolenaar33570922005-01-25 22:26:29 +00009195 listitem_T *li;
9196 list_T *l;
9197 dictitem_T *di;
9198 dict_T *d;
9199 typval_T *tv = NULL;
Bram Moolenaar0d660222005-01-07 21:51:51 +00009200
Bram Moolenaare9a41262005-01-15 22:18:47 +00009201 if (argvars[0].v_type == VAR_LIST)
Bram Moolenaar0d660222005-01-07 21:51:51 +00009202 {
Bram Moolenaare9a41262005-01-15 22:18:47 +00009203 if ((l = argvars[0].vval.v_list) != NULL)
Bram Moolenaar0d660222005-01-07 21:51:51 +00009204 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00009205 int error = FALSE;
9206
9207 li = list_find(l, get_tv_number_chk(&argvars[1], &error));
9208 if (!error && li != NULL)
Bram Moolenaare9a41262005-01-15 22:18:47 +00009209 tv = &li->li_tv;
Bram Moolenaar0d660222005-01-07 21:51:51 +00009210 }
Bram Moolenaar0d660222005-01-07 21:51:51 +00009211 }
Bram Moolenaare9a41262005-01-15 22:18:47 +00009212 else if (argvars[0].v_type == VAR_DICT)
9213 {
9214 if ((d = argvars[0].vval.v_dict) != NULL)
9215 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00009216 di = dict_find(d, get_tv_string(&argvars[1]), -1);
Bram Moolenaare9a41262005-01-15 22:18:47 +00009217 if (di != NULL)
9218 tv = &di->di_tv;
9219 }
9220 }
9221 else
9222 EMSG2(_(e_listdictarg), "get()");
9223
9224 if (tv == NULL)
9225 {
9226 if (argvars[2].v_type == VAR_UNKNOWN)
9227 rettv->vval.v_number = 0;
9228 else
9229 copy_tv(&argvars[2], rettv);
9230 }
9231 else
9232 copy_tv(tv, rettv);
Bram Moolenaar0d660222005-01-07 21:51:51 +00009233}
9234
Bram Moolenaar342337a2005-07-21 21:11:17 +00009235static void get_buffer_lines __ARGS((buf_T *buf, linenr_T start, linenr_T end, int retlist, typval_T *rettv));
Bram Moolenaar80fc0432005-07-20 22:06:07 +00009236
9237/*
9238 * Get line or list of lines from buffer "buf" into "rettv".
Bram Moolenaar342337a2005-07-21 21:11:17 +00009239 * Return a range (from start to end) of lines in rettv from the specified
9240 * buffer.
9241 * If 'retlist' is TRUE, then the lines are returned as a Vim List.
Bram Moolenaar80fc0432005-07-20 22:06:07 +00009242 */
9243 static void
Bram Moolenaar342337a2005-07-21 21:11:17 +00009244get_buffer_lines(buf, start, end, retlist, rettv)
Bram Moolenaar80fc0432005-07-20 22:06:07 +00009245 buf_T *buf;
9246 linenr_T start;
9247 linenr_T end;
Bram Moolenaar342337a2005-07-21 21:11:17 +00009248 int retlist;
Bram Moolenaar80fc0432005-07-20 22:06:07 +00009249 typval_T *rettv;
9250{
9251 char_u *p;
Bram Moolenaar342337a2005-07-21 21:11:17 +00009252 list_T *l = NULL;
Bram Moolenaar80fc0432005-07-20 22:06:07 +00009253
Bram Moolenaar342337a2005-07-21 21:11:17 +00009254 if (retlist)
Bram Moolenaar80fc0432005-07-20 22:06:07 +00009255 {
Bram Moolenaar342337a2005-07-21 21:11:17 +00009256 l = list_alloc();
9257 if (l == NULL)
9258 return;
9259
9260 rettv->vval.v_list = l;
9261 rettv->v_type = VAR_LIST;
9262 ++l->lv_refcount;
9263 }
9264 else
9265 rettv->vval.v_number = 0;
9266
9267 if (buf == NULL || buf->b_ml.ml_mfp == NULL || start < 0)
9268 return;
9269
9270 if (!retlist)
9271 {
Bram Moolenaar80fc0432005-07-20 22:06:07 +00009272 if (start >= 1 && start <= buf->b_ml.ml_line_count)
9273 p = ml_get_buf(buf, start, FALSE);
9274 else
9275 p = (char_u *)"";
9276
9277 rettv->v_type = VAR_STRING;
9278 rettv->vval.v_string = vim_strsave(p);
9279 }
9280 else
9281 {
9282 if (end < start)
Bram Moolenaar342337a2005-07-21 21:11:17 +00009283 return;
9284
9285 if (start < 1)
9286 start = 1;
9287 if (end > buf->b_ml.ml_line_count)
9288 end = buf->b_ml.ml_line_count;
9289 while (start <= end)
Bram Moolenaar4463f292005-09-25 22:20:24 +00009290 if (list_append_string(l, ml_get_buf(buf, start++, FALSE), -1)
9291 == FAIL)
Bram Moolenaar342337a2005-07-21 21:11:17 +00009292 break;
Bram Moolenaar80fc0432005-07-20 22:06:07 +00009293 }
9294}
9295
9296/*
9297 * "getbufline()" function
9298 */
9299 static void
9300f_getbufline(argvars, rettv)
9301 typval_T *argvars;
9302 typval_T *rettv;
9303{
9304 linenr_T lnum;
9305 linenr_T end;
9306 buf_T *buf;
9307
9308 (void)get_tv_number(&argvars[0]); /* issue errmsg if type error */
9309 ++emsg_off;
9310 buf = get_buf_tv(&argvars[0]);
9311 --emsg_off;
9312
Bram Moolenaar661b1822005-07-28 22:36:45 +00009313 lnum = get_tv_lnum_buf(&argvars[1], buf);
Bram Moolenaar342337a2005-07-21 21:11:17 +00009314 if (argvars[2].v_type == VAR_UNKNOWN)
9315 end = lnum;
Bram Moolenaar80fc0432005-07-20 22:06:07 +00009316 else
Bram Moolenaar661b1822005-07-28 22:36:45 +00009317 end = get_tv_lnum_buf(&argvars[2], buf);
9318
Bram Moolenaar342337a2005-07-21 21:11:17 +00009319 get_buffer_lines(buf, lnum, end, TRUE, rettv);
Bram Moolenaar80fc0432005-07-20 22:06:07 +00009320}
9321
Bram Moolenaar0d660222005-01-07 21:51:51 +00009322/*
9323 * "getbufvar()" function
9324 */
9325 static void
9326f_getbufvar(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00009327 typval_T *argvars;
9328 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +00009329{
9330 buf_T *buf;
9331 buf_T *save_curbuf;
9332 char_u *varname;
Bram Moolenaar33570922005-01-25 22:26:29 +00009333 dictitem_T *v;
Bram Moolenaar0d660222005-01-07 21:51:51 +00009334
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00009335 (void)get_tv_number(&argvars[0]); /* issue errmsg if type error */
9336 varname = get_tv_string_chk(&argvars[1]);
Bram Moolenaar0d660222005-01-07 21:51:51 +00009337 ++emsg_off;
9338 buf = get_buf_tv(&argvars[0]);
Bram Moolenaar0d660222005-01-07 21:51:51 +00009339
9340 rettv->v_type = VAR_STRING;
9341 rettv->vval.v_string = NULL;
9342
9343 if (buf != NULL && varname != NULL)
9344 {
9345 if (*varname == '&') /* buffer-local-option */
9346 {
9347 /* set curbuf to be our buf, temporarily */
9348 save_curbuf = curbuf;
9349 curbuf = buf;
9350
9351 get_option_tv(&varname, rettv, TRUE);
9352
9353 /* restore previous notion of curbuf */
9354 curbuf = save_curbuf;
9355 }
9356 else
9357 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00009358 if (*varname == NUL)
9359 /* let getbufvar({nr}, "") return the "b:" dictionary. The
9360 * scope prefix before the NUL byte is required by
9361 * find_var_in_ht(). */
9362 varname = (char_u *)"b:" + 2;
Bram Moolenaar0d660222005-01-07 21:51:51 +00009363 /* look up the variable */
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00009364 v = find_var_in_ht(&buf->b_vars.dv_hashtab, varname, FALSE);
Bram Moolenaar0d660222005-01-07 21:51:51 +00009365 if (v != NULL)
Bram Moolenaar33570922005-01-25 22:26:29 +00009366 copy_tv(&v->di_tv, rettv);
Bram Moolenaar0d660222005-01-07 21:51:51 +00009367 }
9368 }
9369
9370 --emsg_off;
9371}
9372
9373/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00009374 * "getchar()" function
9375 */
9376 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009377f_getchar(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00009378 typval_T *argvars;
9379 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009380{
9381 varnumber_T n;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00009382 int error = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009383
9384 ++no_mapping;
9385 ++allow_keys;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009386 if (argvars[0].v_type == VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009387 /* getchar(): blocking wait. */
9388 n = safe_vgetc();
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00009389 else if (get_tv_number_chk(&argvars[0], &error) == 1)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009390 /* getchar(1): only check if char avail */
9391 n = vpeekc();
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00009392 else if (error || vpeekc() == NUL)
9393 /* illegal argument or getchar(0) and no char avail: return zero */
Bram Moolenaar071d4272004-06-13 20:20:40 +00009394 n = 0;
9395 else
9396 /* getchar(0) and char avail: return char */
9397 n = safe_vgetc();
9398 --no_mapping;
9399 --allow_keys;
9400
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009401 rettv->vval.v_number = n;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009402 if (IS_SPECIAL(n) || mod_mask != 0)
9403 {
9404 char_u temp[10]; /* modifier: 3, mbyte-char: 6, NUL: 1 */
9405 int i = 0;
9406
9407 /* Turn a special key into three bytes, plus modifier. */
9408 if (mod_mask != 0)
9409 {
9410 temp[i++] = K_SPECIAL;
9411 temp[i++] = KS_MODIFIER;
9412 temp[i++] = mod_mask;
9413 }
9414 if (IS_SPECIAL(n))
9415 {
9416 temp[i++] = K_SPECIAL;
9417 temp[i++] = K_SECOND(n);
9418 temp[i++] = K_THIRD(n);
9419 }
9420#ifdef FEAT_MBYTE
9421 else if (has_mbyte)
9422 i += (*mb_char2bytes)(n, temp + i);
9423#endif
9424 else
9425 temp[i++] = n;
9426 temp[i++] = NUL;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009427 rettv->v_type = VAR_STRING;
9428 rettv->vval.v_string = vim_strsave(temp);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009429 }
9430}
9431
9432/*
9433 * "getcharmod()" function
9434 */
9435/*ARGSUSED*/
9436 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009437f_getcharmod(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00009438 typval_T *argvars;
9439 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009440{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009441 rettv->vval.v_number = mod_mask;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009442}
9443
9444/*
9445 * "getcmdline()" function
9446 */
9447/*ARGSUSED*/
9448 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009449f_getcmdline(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00009450 typval_T *argvars;
9451 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009452{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009453 rettv->v_type = VAR_STRING;
9454 rettv->vval.v_string = get_cmdline_str();
Bram Moolenaar071d4272004-06-13 20:20:40 +00009455}
9456
9457/*
9458 * "getcmdpos()" function
9459 */
9460/*ARGSUSED*/
9461 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009462f_getcmdpos(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00009463 typval_T *argvars;
9464 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009465{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009466 rettv->vval.v_number = get_cmdline_pos() + 1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009467}
9468
9469/*
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +00009470 * "getcmdtype()" function
9471 */
9472/*ARGSUSED*/
9473 static void
9474f_getcmdtype(argvars, rettv)
9475 typval_T *argvars;
9476 typval_T *rettv;
9477{
9478 rettv->v_type = VAR_STRING;
9479 rettv->vval.v_string = alloc(2);
9480 if (rettv->vval.v_string != NULL)
9481 {
9482 rettv->vval.v_string[0] = get_cmdline_type();
9483 rettv->vval.v_string[1] = NUL;
9484 }
9485}
9486
9487/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00009488 * "getcwd()" function
9489 */
9490/*ARGSUSED*/
9491 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009492f_getcwd(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00009493 typval_T *argvars;
9494 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009495{
9496 char_u cwd[MAXPATHL];
9497
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009498 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009499 if (mch_dirname(cwd, MAXPATHL) == FAIL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009500 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009501 else
9502 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009503 rettv->vval.v_string = vim_strsave(cwd);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009504#ifdef BACKSLASH_IN_FILENAME
Bram Moolenaar342337a2005-07-21 21:11:17 +00009505 if (rettv->vval.v_string != NULL)
9506 slash_adjust(rettv->vval.v_string);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009507#endif
9508 }
9509}
9510
9511/*
Bram Moolenaar46c9c732004-12-12 11:37:09 +00009512 * "getfontname()" function
9513 */
Bram Moolenaar1cd871b2004-12-19 22:46:22 +00009514/*ARGSUSED*/
Bram Moolenaar46c9c732004-12-12 11:37:09 +00009515 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009516f_getfontname(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00009517 typval_T *argvars;
9518 typval_T *rettv;
Bram Moolenaar46c9c732004-12-12 11:37:09 +00009519{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009520 rettv->v_type = VAR_STRING;
9521 rettv->vval.v_string = NULL;
Bram Moolenaar46c9c732004-12-12 11:37:09 +00009522#ifdef FEAT_GUI
9523 if (gui.in_use)
9524 {
9525 GuiFont font;
9526 char_u *name = NULL;
9527
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009528 if (argvars[0].v_type == VAR_UNKNOWN)
Bram Moolenaar46c9c732004-12-12 11:37:09 +00009529 {
9530 /* Get the "Normal" font. Either the name saved by
9531 * hl_set_font_name() or from the font ID. */
9532 font = gui.norm_font;
9533 name = hl_get_font_name();
9534 }
9535 else
9536 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009537 name = get_tv_string(&argvars[0]);
Bram Moolenaar46c9c732004-12-12 11:37:09 +00009538 if (STRCMP(name, "*") == 0) /* don't use font dialog */
9539 return;
9540 font = gui_mch_get_font(name, FALSE);
9541 if (font == NOFONT)
9542 return; /* Invalid font name, return empty string. */
9543 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009544 rettv->vval.v_string = gui_mch_get_fontname(font, name);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009545 if (argvars[0].v_type != VAR_UNKNOWN)
Bram Moolenaar46c9c732004-12-12 11:37:09 +00009546 gui_mch_free_font(font);
9547 }
9548#endif
9549}
9550
9551/*
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00009552 * "getfperm({fname})" function
9553 */
9554 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009555f_getfperm(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00009556 typval_T *argvars;
9557 typval_T *rettv;
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00009558{
9559 char_u *fname;
9560 struct stat st;
9561 char_u *perm = NULL;
9562 char_u flags[] = "rwx";
9563 int i;
9564
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009565 fname = get_tv_string(&argvars[0]);
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00009566
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009567 rettv->v_type = VAR_STRING;
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00009568 if (mch_stat((char *)fname, &st) >= 0)
9569 {
9570 perm = vim_strsave((char_u *)"---------");
9571 if (perm != NULL)
9572 {
9573 for (i = 0; i < 9; i++)
9574 {
9575 if (st.st_mode & (1 << (8 - i)))
9576 perm[i] = flags[i % 3];
9577 }
9578 }
9579 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009580 rettv->vval.v_string = perm;
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00009581}
9582
9583/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00009584 * "getfsize({fname})" function
9585 */
9586 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009587f_getfsize(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00009588 typval_T *argvars;
9589 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009590{
9591 char_u *fname;
9592 struct stat st;
9593
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009594 fname = get_tv_string(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009595
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009596 rettv->v_type = VAR_NUMBER;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009597
9598 if (mch_stat((char *)fname, &st) >= 0)
9599 {
9600 if (mch_isdir(fname))
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009601 rettv->vval.v_number = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009602 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009603 rettv->vval.v_number = (varnumber_T)st.st_size;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009604 }
9605 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009606 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009607}
9608
9609/*
9610 * "getftime({fname})" function
9611 */
9612 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009613f_getftime(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00009614 typval_T *argvars;
9615 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009616{
9617 char_u *fname;
9618 struct stat st;
9619
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009620 fname = get_tv_string(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009621
9622 if (mch_stat((char *)fname, &st) >= 0)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009623 rettv->vval.v_number = (varnumber_T)st.st_mtime;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009624 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009625 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009626}
9627
9628/*
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00009629 * "getftype({fname})" function
9630 */
9631 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009632f_getftype(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00009633 typval_T *argvars;
9634 typval_T *rettv;
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00009635{
9636 char_u *fname;
9637 struct stat st;
9638 char_u *type = NULL;
9639 char *t;
9640
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009641 fname = get_tv_string(&argvars[0]);
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00009642
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009643 rettv->v_type = VAR_STRING;
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00009644 if (mch_lstat((char *)fname, &st) >= 0)
9645 {
9646#ifdef S_ISREG
9647 if (S_ISREG(st.st_mode))
9648 t = "file";
9649 else if (S_ISDIR(st.st_mode))
9650 t = "dir";
9651# ifdef S_ISLNK
9652 else if (S_ISLNK(st.st_mode))
9653 t = "link";
9654# endif
9655# ifdef S_ISBLK
9656 else if (S_ISBLK(st.st_mode))
9657 t = "bdev";
9658# endif
9659# ifdef S_ISCHR
9660 else if (S_ISCHR(st.st_mode))
9661 t = "cdev";
9662# endif
9663# ifdef S_ISFIFO
9664 else if (S_ISFIFO(st.st_mode))
9665 t = "fifo";
9666# endif
9667# ifdef S_ISSOCK
9668 else if (S_ISSOCK(st.st_mode))
9669 t = "fifo";
9670# endif
9671 else
9672 t = "other";
9673#else
9674# ifdef S_IFMT
9675 switch (st.st_mode & S_IFMT)
9676 {
9677 case S_IFREG: t = "file"; break;
9678 case S_IFDIR: t = "dir"; break;
9679# ifdef S_IFLNK
9680 case S_IFLNK: t = "link"; break;
9681# endif
9682# ifdef S_IFBLK
9683 case S_IFBLK: t = "bdev"; break;
9684# endif
9685# ifdef S_IFCHR
9686 case S_IFCHR: t = "cdev"; break;
9687# endif
9688# ifdef S_IFIFO
9689 case S_IFIFO: t = "fifo"; break;
9690# endif
9691# ifdef S_IFSOCK
9692 case S_IFSOCK: t = "socket"; break;
9693# endif
9694 default: t = "other";
9695 }
9696# else
9697 if (mch_isdir(fname))
9698 t = "dir";
9699 else
9700 t = "file";
9701# endif
9702#endif
9703 type = vim_strsave((char_u *)t);
9704 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009705 rettv->vval.v_string = type;
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00009706}
9707
9708/*
Bram Moolenaar80fc0432005-07-20 22:06:07 +00009709 * "getline(lnum, [end])" function
Bram Moolenaar0d660222005-01-07 21:51:51 +00009710 */
9711 static void
9712f_getline(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00009713 typval_T *argvars;
9714 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +00009715{
9716 linenr_T lnum;
9717 linenr_T end;
Bram Moolenaar342337a2005-07-21 21:11:17 +00009718 int retlist;
Bram Moolenaar0d660222005-01-07 21:51:51 +00009719
9720 lnum = get_tv_lnum(argvars);
Bram Moolenaar80fc0432005-07-20 22:06:07 +00009721 if (argvars[1].v_type == VAR_UNKNOWN)
Bram Moolenaar342337a2005-07-21 21:11:17 +00009722 {
Bram Moolenaar80fc0432005-07-20 22:06:07 +00009723 end = 0;
Bram Moolenaar342337a2005-07-21 21:11:17 +00009724 retlist = FALSE;
9725 }
Bram Moolenaar0d660222005-01-07 21:51:51 +00009726 else
Bram Moolenaar342337a2005-07-21 21:11:17 +00009727 {
Bram Moolenaar0d660222005-01-07 21:51:51 +00009728 end = get_tv_lnum(&argvars[1]);
Bram Moolenaar342337a2005-07-21 21:11:17 +00009729 retlist = TRUE;
9730 }
Bram Moolenaar80fc0432005-07-20 22:06:07 +00009731
Bram Moolenaar342337a2005-07-21 21:11:17 +00009732 get_buffer_lines(curbuf, lnum, end, retlist, rettv);
Bram Moolenaar0d660222005-01-07 21:51:51 +00009733}
9734
9735/*
Bram Moolenaar2641f772005-03-25 21:58:17 +00009736 * "getqflist()" function
9737 */
9738/*ARGSUSED*/
9739 static void
9740f_getqflist(argvars, rettv)
9741 typval_T *argvars;
9742 typval_T *rettv;
9743{
9744#ifdef FEAT_QUICKFIX
9745 list_T *l;
9746#endif
9747
9748 rettv->vval.v_number = FALSE;
9749#ifdef FEAT_QUICKFIX
9750 l = list_alloc();
9751 if (l != NULL)
9752 {
Bram Moolenaard43b6cf2005-09-09 19:53:42 +00009753 rettv->vval.v_list = l;
9754 rettv->v_type = VAR_LIST;
9755 ++l->lv_refcount;
9756 (void)get_errorlist(l);
Bram Moolenaar2641f772005-03-25 21:58:17 +00009757 }
9758#endif
9759}
9760
9761/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00009762 * "getreg()" function
9763 */
9764 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009765f_getreg(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00009766 typval_T *argvars;
9767 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009768{
9769 char_u *strregname;
9770 int regname;
Bram Moolenaar67fe1a12005-05-22 22:12:58 +00009771 int arg2 = FALSE;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00009772 int error = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009773
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009774 if (argvars[0].v_type != VAR_UNKNOWN)
Bram Moolenaar67fe1a12005-05-22 22:12:58 +00009775 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00009776 strregname = get_tv_string_chk(&argvars[0]);
9777 error = strregname == NULL;
Bram Moolenaar67fe1a12005-05-22 22:12:58 +00009778 if (argvars[1].v_type != VAR_UNKNOWN)
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00009779 arg2 = get_tv_number_chk(&argvars[1], &error);
Bram Moolenaar67fe1a12005-05-22 22:12:58 +00009780 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00009781 else
Bram Moolenaare9a41262005-01-15 22:18:47 +00009782 strregname = vimvars[VV_REG].vv_str;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009783 regname = (strregname == NULL ? '"' : *strregname);
9784 if (regname == 0)
9785 regname = '"';
9786
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009787 rettv->v_type = VAR_STRING;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00009788 rettv->vval.v_string = error ? NULL :
9789 get_reg_contents(regname, TRUE, arg2);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009790}
9791
9792/*
9793 * "getregtype()" function
9794 */
9795 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009796f_getregtype(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00009797 typval_T *argvars;
9798 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009799{
9800 char_u *strregname;
9801 int regname;
9802 char_u buf[NUMBUFLEN + 2];
9803 long reglen = 0;
9804
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009805 if (argvars[0].v_type != VAR_UNKNOWN)
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00009806 {
9807 strregname = get_tv_string_chk(&argvars[0]);
9808 if (strregname == NULL) /* type error; errmsg already given */
9809 {
9810 rettv->v_type = VAR_STRING;
9811 rettv->vval.v_string = NULL;
9812 return;
9813 }
9814 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00009815 else
9816 /* Default to v:register */
Bram Moolenaare9a41262005-01-15 22:18:47 +00009817 strregname = vimvars[VV_REG].vv_str;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009818
9819 regname = (strregname == NULL ? '"' : *strregname);
9820 if (regname == 0)
9821 regname = '"';
9822
9823 buf[0] = NUL;
9824 buf[1] = NUL;
9825 switch (get_reg_type(regname, &reglen))
9826 {
9827 case MLINE: buf[0] = 'V'; break;
9828 case MCHAR: buf[0] = 'v'; break;
9829#ifdef FEAT_VISUAL
9830 case MBLOCK:
9831 buf[0] = Ctrl_V;
9832 sprintf((char *)buf + 1, "%ld", reglen + 1);
9833 break;
9834#endif
9835 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009836 rettv->v_type = VAR_STRING;
9837 rettv->vval.v_string = vim_strsave(buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009838}
9839
9840/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00009841 * "getwinposx()" function
9842 */
9843/*ARGSUSED*/
9844 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009845f_getwinposx(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00009846 typval_T *argvars;
9847 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009848{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009849 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009850#ifdef FEAT_GUI
9851 if (gui.in_use)
9852 {
9853 int x, y;
9854
9855 if (gui_mch_get_winpos(&x, &y) == OK)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009856 rettv->vval.v_number = x;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009857 }
9858#endif
9859}
9860
9861/*
9862 * "getwinposy()" function
9863 */
9864/*ARGSUSED*/
9865 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009866f_getwinposy(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00009867 typval_T *argvars;
9868 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009869{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009870 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009871#ifdef FEAT_GUI
9872 if (gui.in_use)
9873 {
9874 int x, y;
9875
9876 if (gui_mch_get_winpos(&x, &y) == OK)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009877 rettv->vval.v_number = y;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009878 }
9879#endif
9880}
9881
Bram Moolenaara40058a2005-07-11 22:42:07 +00009882static win_T *find_win_by_nr __ARGS((typval_T *vp));
9883
9884 static win_T *
9885find_win_by_nr(vp)
9886 typval_T *vp;
9887{
9888#ifdef FEAT_WINDOWS
9889 win_T *wp;
9890#endif
9891 int nr;
9892
9893 nr = get_tv_number_chk(vp, NULL);
9894
9895#ifdef FEAT_WINDOWS
9896 if (nr < 0)
9897 return NULL;
9898 if (nr == 0)
9899 return curwin;
9900
9901 for (wp = firstwin; wp != NULL; wp = wp->w_next)
9902 if (--nr <= 0)
9903 break;
9904 return wp;
9905#else
9906 if (nr == 0 || nr == 1)
9907 return curwin;
9908 return NULL;
9909#endif
9910}
9911
Bram Moolenaar071d4272004-06-13 20:20:40 +00009912/*
9913 * "getwinvar()" function
9914 */
9915 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009916f_getwinvar(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00009917 typval_T *argvars;
9918 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009919{
9920 win_T *win, *oldcurwin;
9921 char_u *varname;
Bram Moolenaar33570922005-01-25 22:26:29 +00009922 dictitem_T *v;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009923
Bram Moolenaar071d4272004-06-13 20:20:40 +00009924 win = find_win_by_nr(&argvars[0]);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00009925 varname = get_tv_string_chk(&argvars[1]);
9926 ++emsg_off;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009927
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009928 rettv->v_type = VAR_STRING;
9929 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009930
9931 if (win != NULL && varname != NULL)
9932 {
9933 if (*varname == '&') /* window-local-option */
9934 {
Bram Moolenaarc0761132005-03-18 20:30:32 +00009935 /* Set curwin to be our win, temporarily. Also set curbuf, so
9936 * that we can get buffer-local options. */
Bram Moolenaar071d4272004-06-13 20:20:40 +00009937 oldcurwin = curwin;
9938 curwin = win;
Bram Moolenaarc0761132005-03-18 20:30:32 +00009939 curbuf = win->w_buffer;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009940
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009941 get_option_tv(&varname, rettv, 1);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009942
9943 /* restore previous notion of curwin */
9944 curwin = oldcurwin;
Bram Moolenaarc0761132005-03-18 20:30:32 +00009945 curbuf = curwin->w_buffer;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009946 }
9947 else
9948 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00009949 if (*varname == NUL)
9950 /* let getwinvar({nr}, "") return the "w:" dictionary. The
9951 * scope prefix before the NUL byte is required by
9952 * find_var_in_ht(). */
9953 varname = (char_u *)"w:" + 2;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009954 /* look up the variable */
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00009955 v = find_var_in_ht(&win->w_vars.dv_hashtab, varname, FALSE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009956 if (v != NULL)
Bram Moolenaar33570922005-01-25 22:26:29 +00009957 copy_tv(&v->di_tv, rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009958 }
9959 }
9960
9961 --emsg_off;
9962}
9963
9964/*
9965 * "glob()" function
9966 */
9967 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009968f_glob(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00009969 typval_T *argvars;
9970 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009971{
9972 expand_T xpc;
9973
9974 ExpandInit(&xpc);
9975 xpc.xp_context = EXPAND_FILES;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009976 rettv->v_type = VAR_STRING;
9977 rettv->vval.v_string = ExpandOne(&xpc, get_tv_string(&argvars[0]),
Bram Moolenaar071d4272004-06-13 20:20:40 +00009978 NULL, WILD_USE_NL|WILD_SILENT, WILD_ALL);
9979 ExpandCleanup(&xpc);
9980}
9981
9982/*
9983 * "globpath()" function
9984 */
9985 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009986f_globpath(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00009987 typval_T *argvars;
9988 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009989{
9990 char_u buf1[NUMBUFLEN];
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00009991 char_u *file = get_tv_string_buf_chk(&argvars[1], buf1);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009992
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009993 rettv->v_type = VAR_STRING;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +00009994 if (file == NULL)
9995 rettv->vval.v_string = NULL;
9996 else
9997 rettv->vval.v_string = globpath(get_tv_string(&argvars[0]), file);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009998}
9999
10000/*
10001 * "has()" function
10002 */
10003 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010004f_has(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010005 typval_T *argvars;
10006 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010007{
10008 int i;
10009 char_u *name;
10010 int n = FALSE;
10011 static char *(has_list[]) =
10012 {
10013#ifdef AMIGA
10014 "amiga",
10015# ifdef FEAT_ARP
10016 "arp",
10017# endif
10018#endif
10019#ifdef __BEOS__
10020 "beos",
10021#endif
10022#ifdef MSDOS
10023# ifdef DJGPP
10024 "dos32",
10025# else
10026 "dos16",
10027# endif
10028#endif
Bram Moolenaar241a8aa2005-12-06 20:04:44 +000010029#ifdef MACOS
Bram Moolenaar071d4272004-06-13 20:20:40 +000010030 "mac",
10031#endif
10032#if defined(MACOS_X_UNIX)
10033 "macunix",
10034#endif
10035#ifdef OS2
10036 "os2",
10037#endif
10038#ifdef __QNX__
10039 "qnx",
10040#endif
10041#ifdef RISCOS
10042 "riscos",
10043#endif
10044#ifdef UNIX
10045 "unix",
10046#endif
10047#ifdef VMS
10048 "vms",
10049#endif
10050#ifdef WIN16
10051 "win16",
10052#endif
10053#ifdef WIN32
10054 "win32",
10055#endif
10056#if defined(UNIX) && (defined(__CYGWIN32__) || defined(__CYGWIN__))
10057 "win32unix",
10058#endif
10059#ifdef WIN64
10060 "win64",
10061#endif
10062#ifdef EBCDIC
10063 "ebcdic",
10064#endif
10065#ifndef CASE_INSENSITIVE_FILENAME
10066 "fname_case",
10067#endif
10068#ifdef FEAT_ARABIC
10069 "arabic",
10070#endif
10071#ifdef FEAT_AUTOCMD
10072 "autocmd",
10073#endif
10074#ifdef FEAT_BEVAL
10075 "balloon_eval",
Bram Moolenaar342337a2005-07-21 21:11:17 +000010076# ifndef FEAT_GUI_W32 /* other GUIs always have multiline balloons */
10077 "balloon_multiline",
10078# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000010079#endif
10080#if defined(SOME_BUILTIN_TCAPS) || defined(ALL_BUILTIN_TCAPS)
10081 "builtin_terms",
10082# ifdef ALL_BUILTIN_TCAPS
10083 "all_builtin_terms",
10084# endif
10085#endif
10086#ifdef FEAT_BYTEOFF
10087 "byte_offset",
10088#endif
10089#ifdef FEAT_CINDENT
10090 "cindent",
10091#endif
10092#ifdef FEAT_CLIENTSERVER
10093 "clientserver",
10094#endif
10095#ifdef FEAT_CLIPBOARD
10096 "clipboard",
10097#endif
10098#ifdef FEAT_CMDL_COMPL
10099 "cmdline_compl",
10100#endif
10101#ifdef FEAT_CMDHIST
10102 "cmdline_hist",
10103#endif
10104#ifdef FEAT_COMMENTS
10105 "comments",
10106#endif
10107#ifdef FEAT_CRYPT
10108 "cryptv",
10109#endif
10110#ifdef FEAT_CSCOPE
10111 "cscope",
10112#endif
Bram Moolenaarac6e65f2005-08-29 22:25:38 +000010113#ifdef CURSOR_SHAPE
10114 "cursorshape",
10115#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000010116#ifdef DEBUG
10117 "debug",
10118#endif
10119#ifdef FEAT_CON_DIALOG
10120 "dialog_con",
10121#endif
10122#ifdef FEAT_GUI_DIALOG
10123 "dialog_gui",
10124#endif
10125#ifdef FEAT_DIFF
10126 "diff",
10127#endif
10128#ifdef FEAT_DIGRAPHS
10129 "digraphs",
10130#endif
10131#ifdef FEAT_DND
10132 "dnd",
10133#endif
10134#ifdef FEAT_EMACS_TAGS
10135 "emacs_tags",
10136#endif
10137 "eval", /* always present, of course! */
10138#ifdef FEAT_EX_EXTRA
10139 "ex_extra",
10140#endif
10141#ifdef FEAT_SEARCH_EXTRA
10142 "extra_search",
10143#endif
10144#ifdef FEAT_FKMAP
10145 "farsi",
10146#endif
10147#ifdef FEAT_SEARCHPATH
10148 "file_in_path",
10149#endif
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000010150#if defined(UNIX) && !defined(USE_SYSTEM)
10151 "filterpipe",
10152#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000010153#ifdef FEAT_FIND_ID
10154 "find_in_path",
10155#endif
10156#ifdef FEAT_FOLDING
10157 "folding",
10158#endif
10159#ifdef FEAT_FOOTER
10160 "footer",
10161#endif
10162#if !defined(USE_SYSTEM) && defined(UNIX)
10163 "fork",
10164#endif
10165#ifdef FEAT_GETTEXT
10166 "gettext",
10167#endif
10168#ifdef FEAT_GUI
10169 "gui",
10170#endif
10171#ifdef FEAT_GUI_ATHENA
10172# ifdef FEAT_GUI_NEXTAW
10173 "gui_neXtaw",
10174# else
10175 "gui_athena",
10176# endif
10177#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000010178#ifdef FEAT_GUI_GTK
10179 "gui_gtk",
10180# ifdef HAVE_GTK2
10181 "gui_gtk2",
10182# endif
10183#endif
10184#ifdef FEAT_GUI_MAC
10185 "gui_mac",
10186#endif
10187#ifdef FEAT_GUI_MOTIF
10188 "gui_motif",
10189#endif
10190#ifdef FEAT_GUI_PHOTON
10191 "gui_photon",
10192#endif
10193#ifdef FEAT_GUI_W16
10194 "gui_win16",
10195#endif
10196#ifdef FEAT_GUI_W32
10197 "gui_win32",
10198#endif
10199#ifdef FEAT_HANGULIN
10200 "hangul_input",
10201#endif
10202#if defined(HAVE_ICONV_H) && defined(USE_ICONV)
10203 "iconv",
10204#endif
10205#ifdef FEAT_INS_EXPAND
10206 "insert_expand",
10207#endif
10208#ifdef FEAT_JUMPLIST
10209 "jumplist",
10210#endif
10211#ifdef FEAT_KEYMAP
10212 "keymap",
10213#endif
10214#ifdef FEAT_LANGMAP
10215 "langmap",
10216#endif
10217#ifdef FEAT_LIBCALL
10218 "libcall",
10219#endif
10220#ifdef FEAT_LINEBREAK
10221 "linebreak",
10222#endif
10223#ifdef FEAT_LISP
10224 "lispindent",
10225#endif
10226#ifdef FEAT_LISTCMDS
10227 "listcmds",
10228#endif
10229#ifdef FEAT_LOCALMAP
10230 "localmap",
10231#endif
10232#ifdef FEAT_MENU
10233 "menu",
10234#endif
10235#ifdef FEAT_SESSION
10236 "mksession",
10237#endif
10238#ifdef FEAT_MODIFY_FNAME
10239 "modify_fname",
10240#endif
10241#ifdef FEAT_MOUSE
10242 "mouse",
10243#endif
10244#ifdef FEAT_MOUSESHAPE
10245 "mouseshape",
10246#endif
10247#if defined(UNIX) || defined(VMS)
10248# ifdef FEAT_MOUSE_DEC
10249 "mouse_dec",
10250# endif
10251# ifdef FEAT_MOUSE_GPM
10252 "mouse_gpm",
10253# endif
10254# ifdef FEAT_MOUSE_JSB
10255 "mouse_jsbterm",
10256# endif
10257# ifdef FEAT_MOUSE_NET
10258 "mouse_netterm",
10259# endif
10260# ifdef FEAT_MOUSE_PTERM
10261 "mouse_pterm",
10262# endif
10263# ifdef FEAT_MOUSE_XTERM
10264 "mouse_xterm",
10265# endif
10266#endif
10267#ifdef FEAT_MBYTE
10268 "multi_byte",
10269#endif
10270#ifdef FEAT_MBYTE_IME
10271 "multi_byte_ime",
10272#endif
10273#ifdef FEAT_MULTI_LANG
10274 "multi_lang",
10275#endif
Bram Moolenaar325b7a22004-07-05 15:58:32 +000010276#ifdef FEAT_MZSCHEME
Bram Moolenaar33570922005-01-25 22:26:29 +000010277#ifndef DYNAMIC_MZSCHEME
Bram Moolenaar325b7a22004-07-05 15:58:32 +000010278 "mzscheme",
10279#endif
Bram Moolenaar33570922005-01-25 22:26:29 +000010280#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000010281#ifdef FEAT_OLE
10282 "ole",
10283#endif
10284#ifdef FEAT_OSFILETYPE
10285 "osfiletype",
10286#endif
10287#ifdef FEAT_PATH_EXTRA
10288 "path_extra",
10289#endif
10290#ifdef FEAT_PERL
10291#ifndef DYNAMIC_PERL
10292 "perl",
10293#endif
10294#endif
10295#ifdef FEAT_PYTHON
10296#ifndef DYNAMIC_PYTHON
10297 "python",
10298#endif
10299#endif
10300#ifdef FEAT_POSTSCRIPT
10301 "postscript",
10302#endif
10303#ifdef FEAT_PRINTER
10304 "printer",
10305#endif
Bram Moolenaar05159a02005-02-26 23:04:13 +000010306#ifdef FEAT_PROFILE
10307 "profile",
10308#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000010309#ifdef FEAT_QUICKFIX
10310 "quickfix",
10311#endif
10312#ifdef FEAT_RIGHTLEFT
10313 "rightleft",
10314#endif
10315#if defined(FEAT_RUBY) && !defined(DYNAMIC_RUBY)
10316 "ruby",
10317#endif
10318#ifdef FEAT_SCROLLBIND
10319 "scrollbind",
10320#endif
10321#ifdef FEAT_CMDL_INFO
10322 "showcmd",
10323 "cmdline_info",
10324#endif
10325#ifdef FEAT_SIGNS
10326 "signs",
10327#endif
10328#ifdef FEAT_SMARTINDENT
10329 "smartindent",
10330#endif
10331#ifdef FEAT_SNIFF
10332 "sniff",
10333#endif
10334#ifdef FEAT_STL_OPT
10335 "statusline",
10336#endif
10337#ifdef FEAT_SUN_WORKSHOP
10338 "sun_workshop",
10339#endif
10340#ifdef FEAT_NETBEANS_INTG
10341 "netbeans_intg",
10342#endif
10343#ifdef FEAT_SYN_HL
Bram Moolenaar0e4d8772005-06-07 21:12:49 +000010344 "spell",
10345#endif
10346#ifdef FEAT_SYN_HL
Bram Moolenaar071d4272004-06-13 20:20:40 +000010347 "syntax",
10348#endif
10349#if defined(USE_SYSTEM) || !defined(UNIX)
10350 "system",
10351#endif
10352#ifdef FEAT_TAG_BINS
10353 "tag_binary",
10354#endif
10355#ifdef FEAT_TAG_OLDSTATIC
10356 "tag_old_static",
10357#endif
10358#ifdef FEAT_TAG_ANYWHITE
10359 "tag_any_white",
10360#endif
10361#ifdef FEAT_TCL
10362# ifndef DYNAMIC_TCL
10363 "tcl",
10364# endif
10365#endif
10366#ifdef TERMINFO
10367 "terminfo",
10368#endif
10369#ifdef FEAT_TERMRESPONSE
10370 "termresponse",
10371#endif
10372#ifdef FEAT_TEXTOBJ
10373 "textobjects",
10374#endif
10375#ifdef HAVE_TGETENT
10376 "tgetent",
10377#endif
10378#ifdef FEAT_TITLE
10379 "title",
10380#endif
10381#ifdef FEAT_TOOLBAR
10382 "toolbar",
10383#endif
10384#ifdef FEAT_USR_CMDS
10385 "user-commands", /* was accidentally included in 5.4 */
10386 "user_commands",
10387#endif
10388#ifdef FEAT_VIMINFO
10389 "viminfo",
10390#endif
10391#ifdef FEAT_VERTSPLIT
10392 "vertsplit",
10393#endif
10394#ifdef FEAT_VIRTUALEDIT
10395 "virtualedit",
10396#endif
10397#ifdef FEAT_VISUAL
10398 "visual",
10399#endif
10400#ifdef FEAT_VISUALEXTRA
10401 "visualextra",
10402#endif
10403#ifdef FEAT_VREPLACE
10404 "vreplace",
10405#endif
10406#ifdef FEAT_WILDIGN
10407 "wildignore",
10408#endif
10409#ifdef FEAT_WILDMENU
10410 "wildmenu",
10411#endif
10412#ifdef FEAT_WINDOWS
10413 "windows",
10414#endif
10415#ifdef FEAT_WAK
10416 "winaltkeys",
10417#endif
10418#ifdef FEAT_WRITEBACKUP
10419 "writebackup",
10420#endif
10421#ifdef FEAT_XIM
10422 "xim",
10423#endif
10424#ifdef FEAT_XFONTSET
10425 "xfontset",
10426#endif
10427#ifdef USE_XSMP
10428 "xsmp",
10429#endif
10430#ifdef USE_XSMP_INTERACT
10431 "xsmp_interact",
10432#endif
10433#ifdef FEAT_XCLIPBOARD
10434 "xterm_clipboard",
10435#endif
10436#ifdef FEAT_XTERM_SAVE
10437 "xterm_save",
10438#endif
10439#if defined(UNIX) && defined(FEAT_X11)
10440 "X11",
10441#endif
10442 NULL
10443 };
10444
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010445 name = get_tv_string(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010446 for (i = 0; has_list[i] != NULL; ++i)
10447 if (STRICMP(name, has_list[i]) == 0)
10448 {
10449 n = TRUE;
10450 break;
10451 }
10452
10453 if (n == FALSE)
10454 {
10455 if (STRNICMP(name, "patch", 5) == 0)
10456 n = has_patch(atoi((char *)name + 5));
10457 else if (STRICMP(name, "vim_starting") == 0)
10458 n = (starting != 0);
Bram Moolenaar342337a2005-07-21 21:11:17 +000010459#if defined(FEAT_BEVAL) && defined(FEAT_GUI_W32)
10460 else if (STRICMP(name, "balloon_multiline") == 0)
10461 n = multiline_balloon_available();
10462#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000010463#ifdef DYNAMIC_TCL
10464 else if (STRICMP(name, "tcl") == 0)
10465 n = tcl_enabled(FALSE);
10466#endif
10467#if defined(USE_ICONV) && defined(DYNAMIC_ICONV)
10468 else if (STRICMP(name, "iconv") == 0)
10469 n = iconv_enabled(FALSE);
10470#endif
Bram Moolenaar33570922005-01-25 22:26:29 +000010471#ifdef DYNAMIC_MZSCHEME
10472 else if (STRICMP(name, "mzscheme") == 0)
10473 n = mzscheme_enabled(FALSE);
10474#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000010475#ifdef DYNAMIC_RUBY
10476 else if (STRICMP(name, "ruby") == 0)
10477 n = ruby_enabled(FALSE);
10478#endif
10479#ifdef DYNAMIC_PYTHON
10480 else if (STRICMP(name, "python") == 0)
10481 n = python_enabled(FALSE);
10482#endif
10483#ifdef DYNAMIC_PERL
10484 else if (STRICMP(name, "perl") == 0)
10485 n = perl_enabled(FALSE);
10486#endif
10487#ifdef FEAT_GUI
10488 else if (STRICMP(name, "gui_running") == 0)
10489 n = (gui.in_use || gui.starting);
10490# ifdef FEAT_GUI_W32
10491 else if (STRICMP(name, "gui_win32s") == 0)
10492 n = gui_is_win32s();
10493# endif
10494# ifdef FEAT_BROWSE
10495 else if (STRICMP(name, "browse") == 0)
10496 n = gui.in_use; /* gui_mch_browse() works when GUI is running */
10497# endif
10498#endif
10499#ifdef FEAT_SYN_HL
10500 else if (STRICMP(name, "syntax_items") == 0)
10501 n = syntax_present(curbuf);
10502#endif
10503#if defined(WIN3264)
10504 else if (STRICMP(name, "win95") == 0)
10505 n = mch_windows95();
10506#endif
Bram Moolenaar35a9aaa2004-10-24 19:23:07 +000010507#ifdef FEAT_NETBEANS_INTG
10508 else if (STRICMP(name, "netbeans_enabled") == 0)
10509 n = usingNetbeans;
10510#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000010511 }
10512
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010513 rettv->vval.v_number = n;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010514}
10515
10516/*
Bram Moolenaare9a41262005-01-15 22:18:47 +000010517 * "has_key()" function
10518 */
10519 static void
10520f_has_key(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010521 typval_T *argvars;
10522 typval_T *rettv;
Bram Moolenaare9a41262005-01-15 22:18:47 +000010523{
10524 rettv->vval.v_number = 0;
10525 if (argvars[0].v_type != VAR_DICT)
10526 {
10527 EMSG(_(e_dictreq));
10528 return;
10529 }
10530 if (argvars[0].vval.v_dict == NULL)
10531 return;
10532
10533 rettv->vval.v_number = dict_find(argvars[0].vval.v_dict,
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000010534 get_tv_string(&argvars[1]), -1) != NULL;
Bram Moolenaare9a41262005-01-15 22:18:47 +000010535}
10536
10537/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000010538 * "hasmapto()" function
10539 */
10540 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010541f_hasmapto(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010542 typval_T *argvars;
10543 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010544{
10545 char_u *name;
10546 char_u *mode;
10547 char_u buf[NUMBUFLEN];
10548
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010549 name = get_tv_string(&argvars[0]);
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010550 if (argvars[1].v_type == VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +000010551 mode = (char_u *)"nvo";
10552 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010553 mode = get_tv_string_buf(&argvars[1], buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010554
10555 if (map_to_exists(name, mode))
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010556 rettv->vval.v_number = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010557 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010558 rettv->vval.v_number = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010559}
10560
10561/*
10562 * "histadd()" function
10563 */
10564/*ARGSUSED*/
10565 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010566f_histadd(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010567 typval_T *argvars;
10568 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010569{
10570#ifdef FEAT_CMDHIST
10571 int histype;
10572 char_u *str;
10573 char_u buf[NUMBUFLEN];
10574#endif
10575
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010576 rettv->vval.v_number = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010577 if (check_restricted() || check_secure())
10578 return;
10579#ifdef FEAT_CMDHIST
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010580 str = get_tv_string_chk(&argvars[0]); /* NULL on type error */
10581 histype = str != NULL ? get_histtype(str) : -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010582 if (histype >= 0)
10583 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010584 str = get_tv_string_buf(&argvars[1], buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010585 if (*str != NUL)
10586 {
10587 add_to_history(histype, str, FALSE, NUL);
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010588 rettv->vval.v_number = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010589 return;
10590 }
10591 }
10592#endif
10593}
10594
10595/*
10596 * "histdel()" function
10597 */
10598/*ARGSUSED*/
10599 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010600f_histdel(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010601 typval_T *argvars;
10602 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010603{
10604#ifdef FEAT_CMDHIST
10605 int n;
10606 char_u buf[NUMBUFLEN];
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010607 char_u *str;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010608
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010609 str = get_tv_string_chk(&argvars[0]); /* NULL on type error */
10610 if (str == NULL)
10611 n = 0;
10612 else if (argvars[1].v_type == VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +000010613 /* only one argument: clear entire history */
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010614 n = clr_history(get_histtype(str));
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010615 else if (argvars[1].v_type == VAR_NUMBER)
Bram Moolenaar071d4272004-06-13 20:20:40 +000010616 /* index given: remove that entry */
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010617 n = del_history_idx(get_histtype(str),
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010618 (int)get_tv_number(&argvars[1]));
Bram Moolenaar071d4272004-06-13 20:20:40 +000010619 else
10620 /* string given: remove all matching entries */
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010621 n = del_history_entry(get_histtype(str),
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010622 get_tv_string_buf(&argvars[1], buf));
10623 rettv->vval.v_number = n;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010624#else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010625 rettv->vval.v_number = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010626#endif
10627}
10628
10629/*
10630 * "histget()" function
10631 */
10632/*ARGSUSED*/
10633 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010634f_histget(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010635 typval_T *argvars;
10636 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010637{
10638#ifdef FEAT_CMDHIST
10639 int type;
10640 int idx;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010641 char_u *str;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010642
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010643 str = get_tv_string_chk(&argvars[0]); /* NULL on type error */
10644 if (str == NULL)
10645 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010646 else
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010647 {
10648 type = get_histtype(str);
10649 if (argvars[1].v_type == VAR_UNKNOWN)
10650 idx = get_history_idx(type);
10651 else
10652 idx = (int)get_tv_number_chk(&argvars[1], NULL);
10653 /* -1 on type error */
10654 rettv->vval.v_string = vim_strsave(get_history_entry(type, idx));
10655 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000010656#else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010657 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010658#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010659 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010660}
10661
10662/*
10663 * "histnr()" function
10664 */
10665/*ARGSUSED*/
10666 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010667f_histnr(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010668 typval_T *argvars;
10669 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010670{
10671 int i;
10672
10673#ifdef FEAT_CMDHIST
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010674 char_u *history = get_tv_string_chk(&argvars[0]);
10675
10676 i = history == NULL ? HIST_CMD - 1 : get_histtype(history);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010677 if (i >= HIST_CMD && i < HIST_COUNT)
10678 i = get_history_idx(i);
10679 else
10680#endif
10681 i = -1;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010682 rettv->vval.v_number = i;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010683}
10684
10685/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000010686 * "highlightID(name)" function
10687 */
10688 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010689f_hlID(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010690 typval_T *argvars;
10691 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010692{
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010693 rettv->vval.v_number = syn_name2id(get_tv_string(&argvars[0]));
Bram Moolenaar071d4272004-06-13 20:20:40 +000010694}
10695
10696/*
Bram Moolenaar0d660222005-01-07 21:51:51 +000010697 * "highlight_exists()" function
10698 */
10699 static void
10700f_hlexists(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010701 typval_T *argvars;
10702 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000010703{
10704 rettv->vval.v_number = highlight_exists(get_tv_string(&argvars[0]));
10705}
10706
10707/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000010708 * "hostname()" function
10709 */
10710/*ARGSUSED*/
10711 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010712f_hostname(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010713 typval_T *argvars;
10714 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010715{
10716 char_u hostname[256];
10717
10718 mch_get_host_name(hostname, 256);
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010719 rettv->v_type = VAR_STRING;
10720 rettv->vval.v_string = vim_strsave(hostname);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010721}
10722
10723/*
10724 * iconv() function
10725 */
10726/*ARGSUSED*/
10727 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010728f_iconv(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010729 typval_T *argvars;
10730 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010731{
10732#ifdef FEAT_MBYTE
10733 char_u buf1[NUMBUFLEN];
10734 char_u buf2[NUMBUFLEN];
10735 char_u *from, *to, *str;
10736 vimconv_T vimconv;
10737#endif
10738
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010739 rettv->v_type = VAR_STRING;
10740 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010741
10742#ifdef FEAT_MBYTE
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010743 str = get_tv_string(&argvars[0]);
10744 from = enc_canonize(enc_skip(get_tv_string_buf(&argvars[1], buf1)));
10745 to = enc_canonize(enc_skip(get_tv_string_buf(&argvars[2], buf2)));
Bram Moolenaar071d4272004-06-13 20:20:40 +000010746 vimconv.vc_type = CONV_NONE;
10747 convert_setup(&vimconv, from, to);
10748
10749 /* If the encodings are equal, no conversion needed. */
10750 if (vimconv.vc_type == CONV_NONE)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010751 rettv->vval.v_string = vim_strsave(str);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010752 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010753 rettv->vval.v_string = string_convert(&vimconv, str, NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010754
10755 convert_setup(&vimconv, NULL, NULL);
10756 vim_free(from);
10757 vim_free(to);
10758#endif
10759}
10760
10761/*
10762 * "indent()" function
10763 */
10764 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010765f_indent(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010766 typval_T *argvars;
10767 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010768{
10769 linenr_T lnum;
10770
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010771 lnum = get_tv_lnum(argvars);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010772 if (lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010773 rettv->vval.v_number = get_indent_lnum(lnum);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010774 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010775 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010776}
10777
Bram Moolenaar8a283e52005-01-06 23:28:25 +000010778/*
10779 * "index()" function
10780 */
10781 static void
10782f_index(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010783 typval_T *argvars;
10784 typval_T *rettv;
Bram Moolenaar8a283e52005-01-06 23:28:25 +000010785{
Bram Moolenaar33570922005-01-25 22:26:29 +000010786 list_T *l;
10787 listitem_T *item;
Bram Moolenaar8a283e52005-01-06 23:28:25 +000010788 long idx = 0;
10789 int ic = FALSE;
10790
10791 rettv->vval.v_number = -1;
10792 if (argvars[0].v_type != VAR_LIST)
10793 {
10794 EMSG(_(e_listreq));
10795 return;
10796 }
10797 l = argvars[0].vval.v_list;
10798 if (l != NULL)
10799 {
Bram Moolenaar758711c2005-02-02 23:11:38 +000010800 item = l->lv_first;
Bram Moolenaar8a283e52005-01-06 23:28:25 +000010801 if (argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000010802 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010803 int error = FALSE;
10804
Bram Moolenaar758711c2005-02-02 23:11:38 +000010805 /* Start at specified item. Use the cached index that list_find()
10806 * sets, so that a negative number also works. */
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010807 item = list_find(l, get_tv_number_chk(&argvars[2], &error));
Bram Moolenaar758711c2005-02-02 23:11:38 +000010808 idx = l->lv_idx;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000010809 if (argvars[3].v_type != VAR_UNKNOWN)
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010810 ic = get_tv_number_chk(&argvars[3], &error);
10811 if (error)
10812 item = NULL;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000010813 }
Bram Moolenaar8a283e52005-01-06 23:28:25 +000010814
Bram Moolenaar758711c2005-02-02 23:11:38 +000010815 for ( ; item != NULL; item = item->li_next, ++idx)
10816 if (tv_equal(&item->li_tv, &argvars[1], ic))
Bram Moolenaar8a283e52005-01-06 23:28:25 +000010817 {
10818 rettv->vval.v_number = idx;
10819 break;
10820 }
10821 }
10822}
10823
Bram Moolenaar071d4272004-06-13 20:20:40 +000010824static int inputsecret_flag = 0;
10825
10826/*
10827 * "input()" function
10828 * Also handles inputsecret() when inputsecret is set.
10829 */
10830 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010831f_input(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010832 typval_T *argvars;
10833 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010834{
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010835 char_u *prompt = get_tv_string_chk(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010836 char_u *p = NULL;
10837 int c;
10838 char_u buf[NUMBUFLEN];
10839 int cmd_silent_save = cmd_silent;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010840 char_u *defstr = (char_u *)"";
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +000010841 int xp_type = EXPAND_NOTHING;
10842 char_u *xp_arg = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010843
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010844 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010845
10846#ifdef NO_CONSOLE_INPUT
10847 /* While starting up, there is no place to enter text. */
10848 if (no_console_input())
10849 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010850 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010851 return;
10852 }
10853#endif
10854
10855 cmd_silent = FALSE; /* Want to see the prompt. */
10856 if (prompt != NULL)
10857 {
10858 /* Only the part of the message after the last NL is considered as
10859 * prompt for the command line */
10860 p = vim_strrchr(prompt, '\n');
10861 if (p == NULL)
10862 p = prompt;
10863 else
10864 {
10865 ++p;
10866 c = *p;
10867 *p = NUL;
10868 msg_start();
10869 msg_clr_eos();
10870 msg_puts_attr(prompt, echo_attr);
10871 msg_didout = FALSE;
10872 msg_starthere();
10873 *p = c;
10874 }
10875 cmdline_row = msg_row;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010876
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010877 if (argvars[1].v_type != VAR_UNKNOWN)
10878 {
10879 defstr = get_tv_string_buf_chk(&argvars[1], buf);
10880 if (defstr != NULL)
10881 stuffReadbuffSpec(defstr);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010882
Bram Moolenaar4463f292005-09-25 22:20:24 +000010883 if (argvars[2].v_type != VAR_UNKNOWN)
10884 {
10885 char_u *xp_name;
10886 int xp_namelen;
10887 long argt;
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +000010888
Bram Moolenaar4463f292005-09-25 22:20:24 +000010889 rettv->vval.v_string = NULL;
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +000010890
Bram Moolenaar4463f292005-09-25 22:20:24 +000010891 xp_name = get_tv_string_buf_chk(&argvars[2], buf);
10892 if (xp_name == NULL)
10893 return;
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +000010894
Bram Moolenaar4463f292005-09-25 22:20:24 +000010895 xp_namelen = STRLEN(xp_name);
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +000010896
Bram Moolenaar4463f292005-09-25 22:20:24 +000010897 if (parse_compl_arg(xp_name, xp_namelen, &xp_type, &argt,
10898 &xp_arg) == FAIL)
10899 return;
10900 }
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +000010901 }
10902
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010903 if (defstr != NULL)
10904 rettv->vval.v_string =
Bram Moolenaarbfd8fc02005-09-20 23:22:24 +000010905 getcmdline_prompt(inputsecret_flag ? NUL : '@', p, echo_attr,
10906 xp_type, xp_arg);
10907
10908 vim_free(xp_arg);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010909
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010910 /* since the user typed this, no need to wait for return */
10911 need_wait_return = FALSE;
10912 msg_didout = FALSE;
10913 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000010914 cmd_silent = cmd_silent_save;
10915}
10916
10917/*
10918 * "inputdialog()" function
10919 */
10920 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010921f_inputdialog(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010922 typval_T *argvars;
10923 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010924{
10925#if defined(FEAT_GUI_TEXTDIALOG)
10926 /* Use a GUI dialog if the GUI is running and 'c' is not in 'guioptions' */
10927 if (gui.in_use && vim_strchr(p_go, GO_CONDIALOG) == NULL)
10928 {
10929 char_u *message;
10930 char_u buf[NUMBUFLEN];
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010931 char_u *defstr = (char_u *)"";
Bram Moolenaar071d4272004-06-13 20:20:40 +000010932
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010933 message = get_tv_string_chk(&argvars[0]);
10934 if (argvars[1].v_type != VAR_UNKNOWN
10935 && (defstr = get_tv_string_buf_chk(&argvars[1], buf)) != NULL)
Bram Moolenaarce0842a2005-07-18 21:58:11 +000010936 vim_strncpy(IObuff, defstr, IOSIZE - 1);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010937 else
10938 IObuff[0] = NUL;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010939 if (message != NULL && defstr != NULL
10940 && do_dialog(VIM_QUESTION, NULL, message,
10941 (char_u *)_("&OK\n&Cancel"), 1, IObuff) == 1)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010942 rettv->vval.v_string = vim_strsave(IObuff);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010943 else
10944 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000010945 if (message != NULL && defstr != NULL
10946 && argvars[1].v_type != VAR_UNKNOWN
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010947 && argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010948 rettv->vval.v_string = vim_strsave(
10949 get_tv_string_buf(&argvars[2], buf));
Bram Moolenaar071d4272004-06-13 20:20:40 +000010950 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010951 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010952 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010953 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010954 }
10955 else
10956#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010957 f_input(argvars, rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010958}
10959
Bram Moolenaar6efa2b32005-09-10 19:26:26 +000010960/*
10961 * "inputlist()" function
10962 */
10963 static void
10964f_inputlist(argvars, rettv)
10965 typval_T *argvars;
10966 typval_T *rettv;
10967{
10968 listitem_T *li;
10969 int selected;
10970 int mouse_used;
10971
10972 rettv->vval.v_number = 0;
10973#ifdef NO_CONSOLE_INPUT
10974 /* While starting up, there is no place to enter text. */
10975 if (no_console_input())
10976 return;
10977#endif
10978 if (argvars[0].v_type != VAR_LIST || argvars[0].vval.v_list == NULL)
10979 {
10980 EMSG2(_(e_listarg), "inputlist()");
10981 return;
10982 }
10983
10984 msg_start();
10985 lines_left = Rows; /* avoid more prompt */
10986 msg_scroll = TRUE;
10987 msg_clr_eos();
10988
10989 for (li = argvars[0].vval.v_list->lv_first; li != NULL; li = li->li_next)
10990 {
10991 msg_puts(get_tv_string(&li->li_tv));
10992 msg_putchar('\n');
10993 }
10994
10995 /* Ask for choice. */
10996 selected = prompt_for_number(&mouse_used);
10997 if (mouse_used)
10998 selected -= lines_left;
10999
11000 rettv->vval.v_number = selected;
11001}
11002
11003
Bram Moolenaar071d4272004-06-13 20:20:40 +000011004static garray_T ga_userinput = {0, 0, sizeof(tasave_T), 4, NULL};
11005
11006/*
11007 * "inputrestore()" function
11008 */
11009/*ARGSUSED*/
11010 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011011f_inputrestore(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000011012 typval_T *argvars;
11013 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011014{
11015 if (ga_userinput.ga_len > 0)
11016 {
11017 --ga_userinput.ga_len;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011018 restore_typeahead((tasave_T *)(ga_userinput.ga_data)
11019 + ga_userinput.ga_len);
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011020 rettv->vval.v_number = 0; /* OK */
Bram Moolenaar071d4272004-06-13 20:20:40 +000011021 }
11022 else if (p_verbose > 1)
11023 {
Bram Moolenaar54ee7752005-05-31 22:22:17 +000011024 verb_msg((char_u *)_("called inputrestore() more often than inputsave()"));
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011025 rettv->vval.v_number = 1; /* Failed */
Bram Moolenaar071d4272004-06-13 20:20:40 +000011026 }
11027}
11028
11029/*
11030 * "inputsave()" function
11031 */
11032/*ARGSUSED*/
11033 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011034f_inputsave(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000011035 typval_T *argvars;
11036 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011037{
11038 /* Add an entry to the stack of typehead storage. */
11039 if (ga_grow(&ga_userinput, 1) == OK)
11040 {
11041 save_typeahead((tasave_T *)(ga_userinput.ga_data)
11042 + ga_userinput.ga_len);
11043 ++ga_userinput.ga_len;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011044 rettv->vval.v_number = 0; /* OK */
Bram Moolenaar071d4272004-06-13 20:20:40 +000011045 }
11046 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011047 rettv->vval.v_number = 1; /* Failed */
Bram Moolenaar071d4272004-06-13 20:20:40 +000011048}
11049
11050/*
11051 * "inputsecret()" function
11052 */
11053 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011054f_inputsecret(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000011055 typval_T *argvars;
11056 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011057{
11058 ++cmdline_star;
11059 ++inputsecret_flag;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011060 f_input(argvars, rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000011061 --cmdline_star;
11062 --inputsecret_flag;
11063}
11064
11065/*
Bram Moolenaar49cd9572005-01-03 21:06:01 +000011066 * "insert()" function
11067 */
11068 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011069f_insert(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000011070 typval_T *argvars;
11071 typval_T *rettv;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000011072{
11073 long before = 0;
Bram Moolenaar33570922005-01-25 22:26:29 +000011074 listitem_T *item;
11075 list_T *l;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000011076 int error = FALSE;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000011077
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000011078 rettv->vval.v_number = 0;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000011079 if (argvars[0].v_type != VAR_LIST)
Bram Moolenaar0d660222005-01-07 21:51:51 +000011080 EMSG2(_(e_listarg), "insert()");
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000011081 else if ((l = argvars[0].vval.v_list) != NULL
11082 && !tv_check_lock(l->lv_lock, (char_u *)"insert()"))
Bram Moolenaar49cd9572005-01-03 21:06:01 +000011083 {
11084 if (argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000011085 before = get_tv_number_chk(&argvars[2], &error);
11086 if (error)
11087 return; /* type error; errmsg already given */
Bram Moolenaar49cd9572005-01-03 21:06:01 +000011088
Bram Moolenaar758711c2005-02-02 23:11:38 +000011089 if (before == l->lv_len)
11090 item = NULL;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000011091 else
11092 {
Bram Moolenaar758711c2005-02-02 23:11:38 +000011093 item = list_find(l, before);
11094 if (item == NULL)
11095 {
11096 EMSGN(_(e_listidx), before);
11097 l = NULL;
11098 }
11099 }
11100 if (l != NULL)
11101 {
Bram Moolenaar8a283e52005-01-06 23:28:25 +000011102 list_insert_tv(l, &argvars[1], item);
Bram Moolenaar8a283e52005-01-06 23:28:25 +000011103 copy_tv(&argvars[0], rettv);
Bram Moolenaar49cd9572005-01-03 21:06:01 +000011104 }
11105 }
11106}
11107
11108/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000011109 * "isdirectory()" function
11110 */
11111 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011112f_isdirectory(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000011113 typval_T *argvars;
11114 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011115{
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011116 rettv->vval.v_number = mch_isdir(get_tv_string(&argvars[0]));
Bram Moolenaar071d4272004-06-13 20:20:40 +000011117}
11118
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000011119/*
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000011120 * "islocked()" function
11121 */
11122 static void
11123f_islocked(argvars, rettv)
11124 typval_T *argvars;
11125 typval_T *rettv;
11126{
11127 lval_T lv;
11128 char_u *end;
11129 dictitem_T *di;
11130
11131 rettv->vval.v_number = -1;
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +000011132 end = get_lval(get_tv_string(&argvars[0]), NULL, &lv, FALSE, FALSE, FALSE,
11133 FNE_CHECK_START);
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000011134 if (end != NULL && lv.ll_name != NULL)
11135 {
11136 if (*end != NUL)
11137 EMSG(_(e_trailing));
11138 else
11139 {
11140 if (lv.ll_tv == NULL)
11141 {
11142 if (check_changedtick(lv.ll_name))
11143 rettv->vval.v_number = 1; /* always locked */
11144 else
11145 {
11146 di = find_var(lv.ll_name, NULL);
11147 if (di != NULL)
11148 {
11149 /* Consider a variable locked when:
11150 * 1. the variable itself is locked
11151 * 2. the value of the variable is locked.
11152 * 3. the List or Dict value is locked.
11153 */
11154 rettv->vval.v_number = ((di->di_flags & DI_FLAGS_LOCK)
11155 || tv_islocked(&di->di_tv));
11156 }
11157 }
11158 }
11159 else if (lv.ll_range)
11160 EMSG(_("E745: Range not allowed"));
11161 else if (lv.ll_newkey != NULL)
11162 EMSG2(_(e_dictkey), lv.ll_newkey);
11163 else if (lv.ll_list != NULL)
11164 /* List item. */
11165 rettv->vval.v_number = tv_islocked(&lv.ll_li->li_tv);
11166 else
11167 /* Dictionary item. */
11168 rettv->vval.v_number = tv_islocked(&lv.ll_di->di_tv);
11169 }
11170 }
11171
11172 clear_lval(&lv);
11173}
11174
Bram Moolenaar33570922005-01-25 22:26:29 +000011175static void dict_list __ARGS((typval_T *argvars, typval_T *rettv, int what));
Bram Moolenaar8c711452005-01-14 21:53:12 +000011176
11177/*
11178 * Turn a dict into a list:
11179 * "what" == 0: list of keys
11180 * "what" == 1: list of values
11181 * "what" == 2: list of items
11182 */
11183 static void
11184dict_list(argvars, rettv, what)
Bram Moolenaar33570922005-01-25 22:26:29 +000011185 typval_T *argvars;
11186 typval_T *rettv;
Bram Moolenaar8c711452005-01-14 21:53:12 +000011187 int what;
11188{
Bram Moolenaar33570922005-01-25 22:26:29 +000011189 list_T *l;
11190 list_T *l2;
11191 dictitem_T *di;
11192 hashitem_T *hi;
11193 listitem_T *li;
11194 listitem_T *li2;
11195 dict_T *d;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000011196 int todo;
Bram Moolenaar8c711452005-01-14 21:53:12 +000011197
11198 rettv->vval.v_number = 0;
11199 if (argvars[0].v_type != VAR_DICT)
11200 {
11201 EMSG(_(e_dictreq));
11202 return;
11203 }
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000011204 if ((d = argvars[0].vval.v_dict) == NULL)
Bram Moolenaar8c711452005-01-14 21:53:12 +000011205 return;
11206
11207 l = list_alloc();
11208 if (l == NULL)
11209 return;
11210 rettv->v_type = VAR_LIST;
11211 rettv->vval.v_list = l;
11212 ++l->lv_refcount;
11213
Bram Moolenaar33570922005-01-25 22:26:29 +000011214 todo = d->dv_hashtab.ht_used;
11215 for (hi = d->dv_hashtab.ht_array; todo > 0; ++hi)
Bram Moolenaar8c711452005-01-14 21:53:12 +000011216 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000011217 if (!HASHITEM_EMPTY(hi))
Bram Moolenaar8c711452005-01-14 21:53:12 +000011218 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000011219 --todo;
11220 di = HI2DI(hi);
Bram Moolenaar8c711452005-01-14 21:53:12 +000011221
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000011222 li = listitem_alloc();
11223 if (li == NULL)
Bram Moolenaar8c711452005-01-14 21:53:12 +000011224 break;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000011225 list_append(l, li);
Bram Moolenaar8c711452005-01-14 21:53:12 +000011226
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000011227 if (what == 0)
11228 {
11229 /* keys() */
11230 li->li_tv.v_type = VAR_STRING;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000011231 li->li_tv.v_lock = 0;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000011232 li->li_tv.vval.v_string = vim_strsave(di->di_key);
11233 }
11234 else if (what == 1)
11235 {
11236 /* values() */
11237 copy_tv(&di->di_tv, &li->li_tv);
11238 }
11239 else
11240 {
11241 /* items() */
11242 l2 = list_alloc();
11243 li->li_tv.v_type = VAR_LIST;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000011244 li->li_tv.v_lock = 0;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000011245 li->li_tv.vval.v_list = l2;
11246 if (l2 == NULL)
11247 break;
11248 ++l2->lv_refcount;
11249
11250 li2 = listitem_alloc();
11251 if (li2 == NULL)
11252 break;
11253 list_append(l2, li2);
11254 li2->li_tv.v_type = VAR_STRING;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000011255 li2->li_tv.v_lock = 0;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000011256 li2->li_tv.vval.v_string = vim_strsave(di->di_key);
11257
11258 li2 = listitem_alloc();
11259 if (li2 == NULL)
11260 break;
11261 list_append(l2, li2);
11262 copy_tv(&di->di_tv, &li2->li_tv);
11263 }
Bram Moolenaar8c711452005-01-14 21:53:12 +000011264 }
11265 }
11266}
11267
11268/*
11269 * "items(dict)" function
11270 */
11271 static void
11272f_items(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000011273 typval_T *argvars;
11274 typval_T *rettv;
Bram Moolenaar8c711452005-01-14 21:53:12 +000011275{
11276 dict_list(argvars, rettv, 2);
11277}
11278
Bram Moolenaar071d4272004-06-13 20:20:40 +000011279/*
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000011280 * "join()" function
11281 */
11282 static void
11283f_join(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000011284 typval_T *argvars;
11285 typval_T *rettv;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000011286{
11287 garray_T ga;
11288 char_u *sep;
11289
11290 rettv->vval.v_number = 0;
11291 if (argvars[0].v_type != VAR_LIST)
11292 {
11293 EMSG(_(e_listreq));
11294 return;
11295 }
11296 if (argvars[0].vval.v_list == NULL)
11297 return;
11298 if (argvars[1].v_type == VAR_UNKNOWN)
11299 sep = (char_u *)" ";
11300 else
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000011301 sep = get_tv_string_chk(&argvars[1]);
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000011302
11303 rettv->v_type = VAR_STRING;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000011304
11305 if (sep != NULL)
11306 {
11307 ga_init2(&ga, (int)sizeof(char), 80);
11308 list_join(&ga, argvars[0].vval.v_list, sep, TRUE);
11309 ga_append(&ga, NUL);
11310 rettv->vval.v_string = (char_u *)ga.ga_data;
11311 }
11312 else
11313 rettv->vval.v_string = NULL;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000011314}
11315
11316/*
Bram Moolenaar8c711452005-01-14 21:53:12 +000011317 * "keys()" function
11318 */
11319 static void
11320f_keys(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000011321 typval_T *argvars;
11322 typval_T *rettv;
Bram Moolenaar8c711452005-01-14 21:53:12 +000011323{
11324 dict_list(argvars, rettv, 0);
11325}
11326
11327/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000011328 * "last_buffer_nr()" function.
11329 */
11330/*ARGSUSED*/
11331 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011332f_last_buffer_nr(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000011333 typval_T *argvars;
11334 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011335{
11336 int n = 0;
11337 buf_T *buf;
11338
11339 for (buf = firstbuf; buf != NULL; buf = buf->b_next)
11340 if (n < buf->b_fnum)
11341 n = buf->b_fnum;
11342
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011343 rettv->vval.v_number = n;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000011344}
11345
11346/*
11347 * "len()" function
11348 */
11349 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011350f_len(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000011351 typval_T *argvars;
11352 typval_T *rettv;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000011353{
11354 switch (argvars[0].v_type)
11355 {
11356 case VAR_STRING:
11357 case VAR_NUMBER:
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011358 rettv->vval.v_number = (varnumber_T)STRLEN(
11359 get_tv_string(&argvars[0]));
Bram Moolenaar49cd9572005-01-03 21:06:01 +000011360 break;
11361 case VAR_LIST:
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011362 rettv->vval.v_number = list_len(argvars[0].vval.v_list);
Bram Moolenaar49cd9572005-01-03 21:06:01 +000011363 break;
Bram Moolenaare9a41262005-01-15 22:18:47 +000011364 case VAR_DICT:
11365 rettv->vval.v_number = dict_len(argvars[0].vval.v_dict);
11366 break;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000011367 default:
Bram Moolenaare49b69a2005-01-08 16:11:57 +000011368 EMSG(_("E701: Invalid type for len()"));
Bram Moolenaar49cd9572005-01-03 21:06:01 +000011369 break;
11370 }
11371}
11372
Bram Moolenaar33570922005-01-25 22:26:29 +000011373static void libcall_common __ARGS((typval_T *argvars, typval_T *rettv, int type));
Bram Moolenaar49cd9572005-01-03 21:06:01 +000011374
11375 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011376libcall_common(argvars, rettv, type)
Bram Moolenaar33570922005-01-25 22:26:29 +000011377 typval_T *argvars;
11378 typval_T *rettv;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000011379 int type;
11380{
11381#ifdef FEAT_LIBCALL
11382 char_u *string_in;
11383 char_u **string_result;
11384 int nr_result;
11385#endif
11386
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011387 rettv->v_type = type;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000011388 if (type == VAR_NUMBER)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011389 rettv->vval.v_number = 0;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000011390 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011391 rettv->vval.v_string = NULL;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000011392
11393 if (check_restricted() || check_secure())
11394 return;
11395
11396#ifdef FEAT_LIBCALL
11397 /* The first two args must be strings, otherwise its meaningless */
11398 if (argvars[0].v_type == VAR_STRING && argvars[1].v_type == VAR_STRING)
11399 {
Bram Moolenaar758711c2005-02-02 23:11:38 +000011400 string_in = NULL;
11401 if (argvars[2].v_type == VAR_STRING)
Bram Moolenaar49cd9572005-01-03 21:06:01 +000011402 string_in = argvars[2].vval.v_string;
11403 if (type == VAR_NUMBER)
11404 string_result = NULL;
11405 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011406 string_result = &rettv->vval.v_string;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000011407 if (mch_libcall(argvars[0].vval.v_string,
11408 argvars[1].vval.v_string,
11409 string_in,
11410 argvars[2].vval.v_number,
11411 string_result,
11412 &nr_result) == OK
11413 && type == VAR_NUMBER)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011414 rettv->vval.v_number = nr_result;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000011415 }
11416#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000011417}
11418
11419/*
Bram Moolenaar0d660222005-01-07 21:51:51 +000011420 * "libcall()" function
11421 */
11422 static void
11423f_libcall(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000011424 typval_T *argvars;
11425 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000011426{
11427 libcall_common(argvars, rettv, VAR_STRING);
11428}
11429
11430/*
11431 * "libcallnr()" function
11432 */
11433 static void
11434f_libcallnr(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000011435 typval_T *argvars;
11436 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000011437{
11438 libcall_common(argvars, rettv, VAR_NUMBER);
11439}
11440
11441/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000011442 * "line(string)" function
11443 */
11444 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011445f_line(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000011446 typval_T *argvars;
11447 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011448{
11449 linenr_T lnum = 0;
11450 pos_T *fp;
11451
11452 fp = var2fpos(&argvars[0], TRUE);
11453 if (fp != NULL)
11454 lnum = fp->lnum;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011455 rettv->vval.v_number = lnum;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011456}
11457
11458/*
11459 * "line2byte(lnum)" function
11460 */
11461/*ARGSUSED*/
11462 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011463f_line2byte(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000011464 typval_T *argvars;
11465 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011466{
11467#ifndef FEAT_BYTEOFF
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011468 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011469#else
11470 linenr_T lnum;
11471
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011472 lnum = get_tv_lnum(argvars);
Bram Moolenaar071d4272004-06-13 20:20:40 +000011473 if (lnum < 1 || lnum > curbuf->b_ml.ml_line_count + 1)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011474 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011475 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011476 rettv->vval.v_number = ml_find_line_or_offset(curbuf, lnum, NULL);
11477 if (rettv->vval.v_number >= 0)
11478 ++rettv->vval.v_number;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011479#endif
11480}
11481
11482/*
11483 * "lispindent(lnum)" function
11484 */
11485 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011486f_lispindent(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000011487 typval_T *argvars;
11488 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011489{
11490#ifdef FEAT_LISP
11491 pos_T pos;
11492 linenr_T lnum;
11493
11494 pos = curwin->w_cursor;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011495 lnum = get_tv_lnum(argvars);
Bram Moolenaar071d4272004-06-13 20:20:40 +000011496 if (lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count)
11497 {
11498 curwin->w_cursor.lnum = lnum;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011499 rettv->vval.v_number = get_lisp_indent();
Bram Moolenaar071d4272004-06-13 20:20:40 +000011500 curwin->w_cursor = pos;
11501 }
11502 else
11503#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011504 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011505}
11506
11507/*
11508 * "localtime()" function
11509 */
11510/*ARGSUSED*/
11511 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011512f_localtime(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000011513 typval_T *argvars;
11514 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011515{
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011516 rettv->vval.v_number = (varnumber_T)time(NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +000011517}
11518
Bram Moolenaar33570922005-01-25 22:26:29 +000011519static void get_maparg __ARGS((typval_T *argvars, typval_T *rettv, int exact));
Bram Moolenaar071d4272004-06-13 20:20:40 +000011520
11521 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011522get_maparg(argvars, rettv, exact)
Bram Moolenaar33570922005-01-25 22:26:29 +000011523 typval_T *argvars;
11524 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011525 int exact;
11526{
11527 char_u *keys;
11528 char_u *which;
11529 char_u buf[NUMBUFLEN];
11530 char_u *keys_buf = NULL;
11531 char_u *rhs;
11532 int mode;
11533 garray_T ga;
11534
11535 /* return empty string for failure */
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011536 rettv->v_type = VAR_STRING;
11537 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011538
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011539 keys = get_tv_string(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +000011540 if (*keys == NUL)
11541 return;
11542
Bram Moolenaar49cd9572005-01-03 21:06:01 +000011543 if (argvars[1].v_type != VAR_UNKNOWN)
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000011544 which = get_tv_string_buf_chk(&argvars[1], buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +000011545 else
11546 which = (char_u *)"";
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000011547 if (which == NULL)
11548 return;
11549
Bram Moolenaar071d4272004-06-13 20:20:40 +000011550 mode = get_map_mode(&which, 0);
11551
11552 keys = replace_termcodes(keys, &keys_buf, TRUE, TRUE);
Bram Moolenaarf4630b62005-05-20 21:31:17 +000011553 rhs = check_map(keys, mode, exact, FALSE);
Bram Moolenaar071d4272004-06-13 20:20:40 +000011554 vim_free(keys_buf);
11555 if (rhs != NULL)
11556 {
11557 ga_init(&ga);
11558 ga.ga_itemsize = 1;
11559 ga.ga_growsize = 40;
11560
11561 while (*rhs != NUL)
11562 ga_concat(&ga, str2special(&rhs, FALSE));
11563
11564 ga_append(&ga, NUL);
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011565 rettv->vval.v_string = (char_u *)ga.ga_data;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011566 }
11567}
11568
11569/*
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000011570 * "map()" function
11571 */
11572 static void
11573f_map(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000011574 typval_T *argvars;
11575 typval_T *rettv;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000011576{
11577 filter_map(argvars, rettv, TRUE);
11578}
11579
11580/*
Bram Moolenaar0d660222005-01-07 21:51:51 +000011581 * "maparg()" function
Bram Moolenaar071d4272004-06-13 20:20:40 +000011582 */
11583 static void
Bram Moolenaar0d660222005-01-07 21:51:51 +000011584f_maparg(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000011585 typval_T *argvars;
11586 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011587{
Bram Moolenaar0d660222005-01-07 21:51:51 +000011588 get_maparg(argvars, rettv, TRUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +000011589}
11590
11591/*
Bram Moolenaar0d660222005-01-07 21:51:51 +000011592 * "mapcheck()" function
Bram Moolenaar071d4272004-06-13 20:20:40 +000011593 */
11594 static void
Bram Moolenaar0d660222005-01-07 21:51:51 +000011595f_mapcheck(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000011596 typval_T *argvars;
11597 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011598{
Bram Moolenaar0d660222005-01-07 21:51:51 +000011599 get_maparg(argvars, rettv, FALSE);
Bram Moolenaar071d4272004-06-13 20:20:40 +000011600}
11601
Bram Moolenaar33570922005-01-25 22:26:29 +000011602static void find_some_match __ARGS((typval_T *argvars, typval_T *rettv, int start));
Bram Moolenaar071d4272004-06-13 20:20:40 +000011603
11604 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011605find_some_match(argvars, rettv, type)
Bram Moolenaar33570922005-01-25 22:26:29 +000011606 typval_T *argvars;
11607 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011608 int type;
11609{
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000011610 char_u *str = NULL;
11611 char_u *expr = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011612 char_u *pat;
11613 regmatch_T regmatch;
11614 char_u patbuf[NUMBUFLEN];
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000011615 char_u strbuf[NUMBUFLEN];
Bram Moolenaar071d4272004-06-13 20:20:40 +000011616 char_u *save_cpo;
11617 long start = 0;
Bram Moolenaar89cb5e02004-07-19 20:55:54 +000011618 long nth = 1;
Bram Moolenaar81bf7082005-02-12 14:31:42 +000011619 int match = 0;
Bram Moolenaar33570922005-01-25 22:26:29 +000011620 list_T *l = NULL;
11621 listitem_T *li = NULL;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000011622 long idx = 0;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000011623 char_u *tofree = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011624
11625 /* Make 'cpoptions' empty, the 'l' flag should not be used here. */
11626 save_cpo = p_cpo;
11627 p_cpo = (char_u *)"";
11628
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000011629 rettv->vval.v_number = -1;
11630 if (type == 3)
11631 {
11632 /* return empty list when there are no matches */
11633 if ((rettv->vval.v_list = list_alloc()) == NULL)
11634 goto theend;
11635 rettv->v_type = VAR_LIST;
11636 ++rettv->vval.v_list->lv_refcount;
11637 }
11638 else if (type == 2)
Bram Moolenaar071d4272004-06-13 20:20:40 +000011639 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011640 rettv->v_type = VAR_STRING;
11641 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011642 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000011643
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000011644 if (argvars[0].v_type == VAR_LIST)
11645 {
11646 if ((l = argvars[0].vval.v_list) == NULL)
11647 goto theend;
11648 li = l->lv_first;
11649 }
11650 else
11651 expr = str = get_tv_string(&argvars[0]);
11652
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000011653 pat = get_tv_string_buf_chk(&argvars[1], patbuf);
11654 if (pat == NULL)
11655 goto theend;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000011656
Bram Moolenaar49cd9572005-01-03 21:06:01 +000011657 if (argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +000011658 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000011659 int error = FALSE;
11660
11661 start = get_tv_number_chk(&argvars[2], &error);
11662 if (error)
11663 goto theend;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000011664 if (l != NULL)
11665 {
11666 li = list_find(l, start);
11667 if (li == NULL)
11668 goto theend;
Bram Moolenaar758711c2005-02-02 23:11:38 +000011669 idx = l->lv_idx; /* use the cached index */
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000011670 }
11671 else
11672 {
11673 if (start < 0)
11674 start = 0;
11675 if (start > (long)STRLEN(str))
11676 goto theend;
11677 str += start;
11678 }
Bram Moolenaar89cb5e02004-07-19 20:55:54 +000011679
Bram Moolenaar49cd9572005-01-03 21:06:01 +000011680 if (argvars[3].v_type != VAR_UNKNOWN)
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000011681 nth = get_tv_number_chk(&argvars[3], &error);
11682 if (error)
11683 goto theend;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011684 }
11685
11686 regmatch.regprog = vim_regcomp(pat, RE_MAGIC + RE_STRING);
11687 if (regmatch.regprog != NULL)
11688 {
11689 regmatch.rm_ic = p_ic;
Bram Moolenaar89cb5e02004-07-19 20:55:54 +000011690
Bram Moolenaard8e9bb22005-07-09 21:14:46 +000011691 for (;;)
Bram Moolenaar89cb5e02004-07-19 20:55:54 +000011692 {
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000011693 if (l != NULL)
11694 {
11695 if (li == NULL)
11696 {
11697 match = FALSE;
11698 break;
11699 }
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000011700 vim_free(tofree);
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000011701 str = echo_string(&li->li_tv, &tofree, strbuf);
Bram Moolenaar81bf7082005-02-12 14:31:42 +000011702 if (str == NULL)
11703 break;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000011704 }
11705
Bram Moolenaar89cb5e02004-07-19 20:55:54 +000011706 match = vim_regexec_nl(&regmatch, str, (colnr_T)0);
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000011707
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000011708 if (match && --nth <= 0)
Bram Moolenaar89cb5e02004-07-19 20:55:54 +000011709 break;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000011710 if (l == NULL && !match)
11711 break;
11712
Bram Moolenaar89cb5e02004-07-19 20:55:54 +000011713 /* Advance to just after the match. */
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000011714 if (l != NULL)
11715 {
11716 li = li->li_next;
11717 ++idx;
11718 }
11719 else
11720 {
Bram Moolenaar89cb5e02004-07-19 20:55:54 +000011721#ifdef FEAT_MBYTE
Bram Moolenaar0fa313a2005-08-10 21:07:57 +000011722 str = regmatch.startp[0] + (*mb_ptr2len)(regmatch.startp[0]);
Bram Moolenaar89cb5e02004-07-19 20:55:54 +000011723#else
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000011724 str = regmatch.startp[0] + 1;
Bram Moolenaar89cb5e02004-07-19 20:55:54 +000011725#endif
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000011726 }
Bram Moolenaar89cb5e02004-07-19 20:55:54 +000011727 }
11728
11729 if (match)
Bram Moolenaar071d4272004-06-13 20:20:40 +000011730 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000011731 if (type == 3)
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000011732 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000011733 int i;
11734
11735 /* return list with matched string and submatches */
11736 for (i = 0; i < NSUBEXP; ++i)
11737 {
11738 if (regmatch.endp[i] == NULL)
11739 break;
Bram Moolenaar4463f292005-09-25 22:20:24 +000011740 if (list_append_string(rettv->vval.v_list,
11741 regmatch.startp[i],
11742 (int)(regmatch.endp[i] - regmatch.startp[i]))
11743 == FAIL)
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000011744 break;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000011745 }
11746 }
11747 else if (type == 2)
11748 {
11749 /* return matched string */
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000011750 if (l != NULL)
11751 copy_tv(&li->li_tv, rettv);
11752 else
11753 rettv->vval.v_string = vim_strnsave(regmatch.startp[0],
Bram Moolenaar071d4272004-06-13 20:20:40 +000011754 (int)(regmatch.endp[0] - regmatch.startp[0]));
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000011755 }
11756 else if (l != NULL)
11757 rettv->vval.v_number = idx;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011758 else
11759 {
11760 if (type != 0)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011761 rettv->vval.v_number =
Bram Moolenaar071d4272004-06-13 20:20:40 +000011762 (varnumber_T)(regmatch.startp[0] - str);
11763 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011764 rettv->vval.v_number =
Bram Moolenaar071d4272004-06-13 20:20:40 +000011765 (varnumber_T)(regmatch.endp[0] - str);
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011766 rettv->vval.v_number += str - expr;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011767 }
11768 }
11769 vim_free(regmatch.regprog);
11770 }
11771
11772theend:
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000011773 vim_free(tofree);
Bram Moolenaar071d4272004-06-13 20:20:40 +000011774 p_cpo = save_cpo;
11775}
11776
11777/*
Bram Moolenaar0d660222005-01-07 21:51:51 +000011778 * "match()" function
11779 */
11780 static void
11781f_match(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000011782 typval_T *argvars;
11783 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000011784{
11785 find_some_match(argvars, rettv, 1);
11786}
11787
11788/*
11789 * "matchend()" function
11790 */
11791 static void
11792f_matchend(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000011793 typval_T *argvars;
11794 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000011795{
11796 find_some_match(argvars, rettv, 0);
11797}
11798
11799/*
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000011800 * "matchlist()" function
11801 */
11802 static void
11803f_matchlist(argvars, rettv)
11804 typval_T *argvars;
11805 typval_T *rettv;
11806{
11807 find_some_match(argvars, rettv, 3);
11808}
11809
11810/*
Bram Moolenaar0d660222005-01-07 21:51:51 +000011811 * "matchstr()" function
11812 */
11813 static void
11814f_matchstr(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000011815 typval_T *argvars;
11816 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000011817{
11818 find_some_match(argvars, rettv, 2);
11819}
11820
Bram Moolenaar33570922005-01-25 22:26:29 +000011821static void max_min __ARGS((typval_T *argvars, typval_T *rettv, int domax));
Bram Moolenaar6cc16192005-01-08 21:49:45 +000011822
11823 static void
11824max_min(argvars, rettv, domax)
Bram Moolenaar33570922005-01-25 22:26:29 +000011825 typval_T *argvars;
11826 typval_T *rettv;
Bram Moolenaar6cc16192005-01-08 21:49:45 +000011827 int domax;
11828{
Bram Moolenaar6cc16192005-01-08 21:49:45 +000011829 long n = 0;
11830 long i;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000011831 int error = FALSE;
Bram Moolenaar6cc16192005-01-08 21:49:45 +000011832
11833 if (argvars[0].v_type == VAR_LIST)
11834 {
Bram Moolenaar33570922005-01-25 22:26:29 +000011835 list_T *l;
11836 listitem_T *li;
Bram Moolenaare9a41262005-01-15 22:18:47 +000011837
Bram Moolenaar6cc16192005-01-08 21:49:45 +000011838 l = argvars[0].vval.v_list;
11839 if (l != NULL)
11840 {
11841 li = l->lv_first;
11842 if (li != NULL)
11843 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000011844 n = get_tv_number_chk(&li->li_tv, &error);
Bram Moolenaard8e9bb22005-07-09 21:14:46 +000011845 for (;;)
Bram Moolenaar6cc16192005-01-08 21:49:45 +000011846 {
11847 li = li->li_next;
11848 if (li == NULL)
11849 break;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000011850 i = get_tv_number_chk(&li->li_tv, &error);
Bram Moolenaar6cc16192005-01-08 21:49:45 +000011851 if (domax ? i > n : i < n)
11852 n = i;
11853 }
11854 }
11855 }
11856 }
Bram Moolenaare9a41262005-01-15 22:18:47 +000011857 else if (argvars[0].v_type == VAR_DICT)
11858 {
Bram Moolenaar33570922005-01-25 22:26:29 +000011859 dict_T *d;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000011860 int first = TRUE;
Bram Moolenaar33570922005-01-25 22:26:29 +000011861 hashitem_T *hi;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000011862 int todo;
Bram Moolenaare9a41262005-01-15 22:18:47 +000011863
11864 d = argvars[0].vval.v_dict;
11865 if (d != NULL)
11866 {
Bram Moolenaar33570922005-01-25 22:26:29 +000011867 todo = d->dv_hashtab.ht_used;
11868 for (hi = d->dv_hashtab.ht_array; todo > 0; ++hi)
Bram Moolenaare9a41262005-01-15 22:18:47 +000011869 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000011870 if (!HASHITEM_EMPTY(hi))
Bram Moolenaare9a41262005-01-15 22:18:47 +000011871 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000011872 --todo;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000011873 i = get_tv_number_chk(&HI2DI(hi)->di_tv, &error);
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000011874 if (first)
11875 {
11876 n = i;
11877 first = FALSE;
11878 }
11879 else if (domax ? i > n : i < n)
Bram Moolenaare9a41262005-01-15 22:18:47 +000011880 n = i;
11881 }
11882 }
11883 }
11884 }
Bram Moolenaar6cc16192005-01-08 21:49:45 +000011885 else
Bram Moolenaar758711c2005-02-02 23:11:38 +000011886 EMSG(_(e_listdictarg));
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000011887 rettv->vval.v_number = error ? 0 : n;
Bram Moolenaar6cc16192005-01-08 21:49:45 +000011888}
11889
11890/*
11891 * "max()" function
11892 */
11893 static void
11894f_max(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000011895 typval_T *argvars;
11896 typval_T *rettv;
Bram Moolenaar6cc16192005-01-08 21:49:45 +000011897{
11898 max_min(argvars, rettv, TRUE);
11899}
11900
11901/*
11902 * "min()" function
11903 */
11904 static void
11905f_min(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000011906 typval_T *argvars;
11907 typval_T *rettv;
Bram Moolenaar6cc16192005-01-08 21:49:45 +000011908{
11909 max_min(argvars, rettv, FALSE);
11910}
11911
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000011912static int mkdir_recurse __ARGS((char_u *dir, int prot));
11913
11914/*
11915 * Create the directory in which "dir" is located, and higher levels when
11916 * needed.
11917 */
11918 static int
11919mkdir_recurse(dir, prot)
11920 char_u *dir;
11921 int prot;
11922{
11923 char_u *p;
11924 char_u *updir;
11925 int r = FAIL;
11926
11927 /* Get end of directory name in "dir".
11928 * We're done when it's "/" or "c:/". */
11929 p = gettail_sep(dir);
11930 if (p <= get_past_head(dir))
11931 return OK;
11932
11933 /* If the directory exists we're done. Otherwise: create it.*/
11934 updir = vim_strnsave(dir, (int)(p - dir));
11935 if (updir == NULL)
11936 return FAIL;
11937 if (mch_isdir(updir))
11938 r = OK;
11939 else if (mkdir_recurse(updir, prot) == OK)
11940 r = vim_mkdir_emsg(updir, prot);
11941 vim_free(updir);
11942 return r;
11943}
11944
11945#ifdef vim_mkdir
11946/*
11947 * "mkdir()" function
11948 */
11949 static void
11950f_mkdir(argvars, rettv)
11951 typval_T *argvars;
11952 typval_T *rettv;
11953{
11954 char_u *dir;
11955 char_u buf[NUMBUFLEN];
11956 int prot = 0755;
11957
11958 rettv->vval.v_number = FAIL;
11959 if (check_restricted() || check_secure())
11960 return;
11961
11962 dir = get_tv_string_buf(&argvars[0], buf);
11963 if (argvars[1].v_type != VAR_UNKNOWN)
11964 {
11965 if (argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000011966 prot = get_tv_number_chk(&argvars[2], NULL);
11967 if (prot != -1 && STRCMP(get_tv_string(&argvars[1]), "p") == 0)
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000011968 mkdir_recurse(dir, prot);
11969 }
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000011970 rettv->vval.v_number = prot != -1 ? vim_mkdir_emsg(dir, prot) : 0;
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000011971}
11972#endif
11973
Bram Moolenaar0d660222005-01-07 21:51:51 +000011974/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000011975 * "mode()" function
11976 */
11977/*ARGSUSED*/
11978 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011979f_mode(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000011980 typval_T *argvars;
11981 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011982{
11983 char_u buf[2];
11984
11985#ifdef FEAT_VISUAL
11986 if (VIsual_active)
11987 {
11988 if (VIsual_select)
11989 buf[0] = VIsual_mode + 's' - 'v';
11990 else
11991 buf[0] = VIsual_mode;
11992 }
11993 else
11994#endif
11995 if (State == HITRETURN || State == ASKMORE || State == SETWSIZE)
11996 buf[0] = 'r';
11997 else if (State & INSERT)
11998 {
11999 if (State & REPLACE_FLAG)
12000 buf[0] = 'R';
12001 else
12002 buf[0] = 'i';
12003 }
12004 else if (State & CMDLINE)
12005 buf[0] = 'c';
12006 else
12007 buf[0] = 'n';
12008
12009 buf[1] = NUL;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012010 rettv->vval.v_string = vim_strsave(buf);
12011 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012012}
12013
12014/*
Bram Moolenaar0d660222005-01-07 21:51:51 +000012015 * "nextnonblank()" function
12016 */
12017 static void
12018f_nextnonblank(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000012019 typval_T *argvars;
12020 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000012021{
12022 linenr_T lnum;
12023
12024 for (lnum = get_tv_lnum(argvars); ; ++lnum)
12025 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000012026 if (lnum < 0 || lnum > curbuf->b_ml.ml_line_count)
Bram Moolenaar0d660222005-01-07 21:51:51 +000012027 {
12028 lnum = 0;
12029 break;
12030 }
12031 if (*skipwhite(ml_get(lnum)) != NUL)
12032 break;
12033 }
12034 rettv->vval.v_number = lnum;
12035}
12036
12037/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000012038 * "nr2char()" function
12039 */
12040 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012041f_nr2char(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000012042 typval_T *argvars;
12043 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012044{
12045 char_u buf[NUMBUFLEN];
12046
12047#ifdef FEAT_MBYTE
12048 if (has_mbyte)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012049 buf[(*mb_char2bytes)((int)get_tv_number(&argvars[0]), buf)] = NUL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012050 else
12051#endif
12052 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012053 buf[0] = (char_u)get_tv_number(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +000012054 buf[1] = NUL;
12055 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012056 rettv->v_type = VAR_STRING;
12057 rettv->vval.v_string = vim_strsave(buf);
Bram Moolenaar49cd9572005-01-03 21:06:01 +000012058}
12059
12060/*
Bram Moolenaar0d660222005-01-07 21:51:51 +000012061 * "prevnonblank()" function
12062 */
12063 static void
12064f_prevnonblank(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000012065 typval_T *argvars;
12066 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000012067{
12068 linenr_T lnum;
12069
12070 lnum = get_tv_lnum(argvars);
12071 if (lnum < 1 || lnum > curbuf->b_ml.ml_line_count)
12072 lnum = 0;
12073 else
12074 while (lnum >= 1 && *skipwhite(ml_get(lnum)) == NUL)
12075 --lnum;
12076 rettv->vval.v_number = lnum;
12077}
12078
Bram Moolenaara6c840d2005-08-22 22:59:46 +000012079#ifdef HAVE_STDARG_H
12080/* This dummy va_list is here because:
12081 * - passing a NULL pointer doesn't work when va_list isn't a pointer
12082 * - locally in the function results in a "used before set" warning
12083 * - using va_start() to initialize it gives "function with fixed args" error */
12084static va_list ap;
12085#endif
12086
Bram Moolenaar8c711452005-01-14 21:53:12 +000012087/*
Bram Moolenaar4be06f92005-07-29 22:36:03 +000012088 * "printf()" function
12089 */
12090 static void
12091f_printf(argvars, rettv)
12092 typval_T *argvars;
12093 typval_T *rettv;
12094{
12095 rettv->v_type = VAR_STRING;
12096 rettv->vval.v_string = NULL;
Bram Moolenaard52d9742005-08-21 22:20:28 +000012097#ifdef HAVE_STDARG_H /* only very old compilers can't do this */
Bram Moolenaar4be06f92005-07-29 22:36:03 +000012098 {
12099 char_u buf[NUMBUFLEN];
12100 int len;
12101 char_u *s;
12102 int saved_did_emsg = did_emsg;
12103 char *fmt;
12104
12105 /* Get the required length, allocate the buffer and do it for real. */
12106 did_emsg = FALSE;
12107 fmt = (char *)get_tv_string_buf(&argvars[0], buf);
Bram Moolenaar5b8d8fd2005-08-16 23:01:50 +000012108 len = vim_vsnprintf(NULL, 0, fmt, ap, argvars + 1);
Bram Moolenaar4be06f92005-07-29 22:36:03 +000012109 if (!did_emsg)
12110 {
12111 s = alloc(len + 1);
12112 if (s != NULL)
12113 {
12114 rettv->vval.v_string = s;
Bram Moolenaar5b8d8fd2005-08-16 23:01:50 +000012115 (void)vim_vsnprintf((char *)s, len + 1, fmt, ap, argvars + 1);
Bram Moolenaar4be06f92005-07-29 22:36:03 +000012116 }
12117 }
12118 did_emsg |= saved_did_emsg;
12119 }
12120#endif
12121}
12122
12123/*
Bram Moolenaar8c711452005-01-14 21:53:12 +000012124 * "range()" function
12125 */
12126 static void
12127f_range(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000012128 typval_T *argvars;
12129 typval_T *rettv;
Bram Moolenaar8c711452005-01-14 21:53:12 +000012130{
12131 long start;
12132 long end;
12133 long stride = 1;
12134 long i;
Bram Moolenaar33570922005-01-25 22:26:29 +000012135 list_T *l;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000012136 int error = FALSE;
Bram Moolenaar8c711452005-01-14 21:53:12 +000012137
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000012138 start = get_tv_number_chk(&argvars[0], &error);
Bram Moolenaar8c711452005-01-14 21:53:12 +000012139 if (argvars[1].v_type == VAR_UNKNOWN)
12140 {
12141 end = start - 1;
12142 start = 0;
12143 }
12144 else
12145 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000012146 end = get_tv_number_chk(&argvars[1], &error);
Bram Moolenaar8c711452005-01-14 21:53:12 +000012147 if (argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000012148 stride = get_tv_number_chk(&argvars[2], &error);
Bram Moolenaar8c711452005-01-14 21:53:12 +000012149 }
12150
12151 rettv->vval.v_number = 0;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000012152 if (error)
12153 return; /* type error; errmsg already given */
Bram Moolenaar8c711452005-01-14 21:53:12 +000012154 if (stride == 0)
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000012155 EMSG(_("E726: Stride is zero"));
Bram Moolenaar92124a32005-06-17 22:03:40 +000012156 else if (stride > 0 ? end + 1 < start : end - 1 > start)
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000012157 EMSG(_("E727: Start past end"));
Bram Moolenaar8c711452005-01-14 21:53:12 +000012158 else
12159 {
12160 l = list_alloc();
12161 if (l != NULL)
12162 {
12163 rettv->v_type = VAR_LIST;
12164 rettv->vval.v_list = l;
12165 ++l->lv_refcount;
12166
12167 for (i = start; stride > 0 ? i <= end : i >= end; i += stride)
Bram Moolenaar4463f292005-09-25 22:20:24 +000012168 if (list_append_number(l, (varnumber_T)i) == FAIL)
Bram Moolenaar8c711452005-01-14 21:53:12 +000012169 break;
Bram Moolenaar8c711452005-01-14 21:53:12 +000012170 }
12171 }
12172}
12173
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000012174/*
12175 * "readfile()" function
12176 */
12177 static void
12178f_readfile(argvars, rettv)
12179 typval_T *argvars;
12180 typval_T *rettv;
12181{
12182 int binary = FALSE;
12183 char_u *fname;
12184 FILE *fd;
12185 list_T *l;
12186 listitem_T *li;
12187#define FREAD_SIZE 200 /* optimized for text lines */
12188 char_u buf[FREAD_SIZE];
12189 int readlen; /* size of last fread() */
12190 int buflen; /* nr of valid chars in buf[] */
12191 int filtd; /* how much in buf[] was NUL -> '\n' filtered */
12192 int tolist; /* first byte in buf[] still to be put in list */
12193 int chop; /* how many CR to chop off */
12194 char_u *prev = NULL; /* previously read bytes, if any */
12195 int prevlen = 0; /* length of "prev" if not NULL */
12196 char_u *s;
12197 int len;
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000012198 long maxline = MAXLNUM;
12199 long cnt = 0;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000012200
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000012201 if (argvars[1].v_type != VAR_UNKNOWN)
12202 {
12203 if (STRCMP(get_tv_string(&argvars[1]), "b") == 0)
12204 binary = TRUE;
12205 if (argvars[2].v_type != VAR_UNKNOWN)
12206 maxline = get_tv_number(&argvars[2]);
12207 }
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000012208
12209 l = list_alloc();
12210 if (l == NULL)
12211 return;
12212 rettv->v_type = VAR_LIST;
12213 rettv->vval.v_list = l;
12214 l->lv_refcount = 1;
12215
12216 /* Always open the file in binary mode, library functions have a mind of
12217 * their own about CR-LF conversion. */
12218 fname = get_tv_string(&argvars[0]);
12219 if (*fname == NUL || (fd = mch_fopen((char *)fname, READBIN)) == NULL)
12220 {
12221 EMSG2(_(e_notopen), *fname == NUL ? (char_u *)_("<empty>") : fname);
12222 return;
12223 }
12224
12225 filtd = 0;
Bram Moolenaarb982ca52005-03-28 21:02:15 +000012226 while (cnt < maxline || maxline < 0)
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000012227 {
12228 readlen = fread(buf + filtd, 1, FREAD_SIZE - filtd, fd);
12229 buflen = filtd + readlen;
12230 tolist = 0;
12231 for ( ; filtd < buflen || readlen <= 0; ++filtd)
12232 {
12233 if (buf[filtd] == '\n' || readlen <= 0)
12234 {
12235 /* Only when in binary mode add an empty list item when the
12236 * last line ends in a '\n'. */
12237 if (!binary && readlen == 0 && filtd == 0)
12238 break;
12239
12240 /* Found end-of-line or end-of-file: add a text line to the
12241 * list. */
12242 chop = 0;
12243 if (!binary)
12244 while (filtd - chop - 1 >= tolist
12245 && buf[filtd - chop - 1] == '\r')
12246 ++chop;
12247 len = filtd - tolist - chop;
12248 if (prev == NULL)
12249 s = vim_strnsave(buf + tolist, len);
12250 else
12251 {
12252 s = alloc((unsigned)(prevlen + len + 1));
12253 if (s != NULL)
12254 {
12255 mch_memmove(s, prev, prevlen);
12256 vim_free(prev);
12257 prev = NULL;
12258 mch_memmove(s + prevlen, buf + tolist, len);
12259 s[prevlen + len] = NUL;
12260 }
12261 }
12262 tolist = filtd + 1;
12263
12264 li = listitem_alloc();
12265 if (li == NULL)
12266 {
12267 vim_free(s);
12268 break;
12269 }
12270 li->li_tv.v_type = VAR_STRING;
12271 li->li_tv.v_lock = 0;
12272 li->li_tv.vval.v_string = s;
12273 list_append(l, li);
12274
Bram Moolenaarb982ca52005-03-28 21:02:15 +000012275 if (++cnt >= maxline && maxline >= 0)
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000012276 break;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000012277 if (readlen <= 0)
12278 break;
12279 }
12280 else if (buf[filtd] == NUL)
12281 buf[filtd] = '\n';
12282 }
12283 if (readlen <= 0)
12284 break;
12285
12286 if (tolist == 0)
12287 {
12288 /* "buf" is full, need to move text to an allocated buffer */
12289 if (prev == NULL)
12290 {
12291 prev = vim_strnsave(buf, buflen);
12292 prevlen = buflen;
12293 }
12294 else
12295 {
12296 s = alloc((unsigned)(prevlen + buflen));
12297 if (s != NULL)
12298 {
12299 mch_memmove(s, prev, prevlen);
12300 mch_memmove(s + prevlen, buf, buflen);
12301 vim_free(prev);
12302 prev = s;
12303 prevlen += buflen;
12304 }
12305 }
12306 filtd = 0;
12307 }
12308 else
12309 {
12310 mch_memmove(buf, buf + tolist, buflen - tolist);
12311 filtd -= tolist;
12312 }
12313 }
12314
Bram Moolenaarb982ca52005-03-28 21:02:15 +000012315 /*
12316 * For a negative line count use only the lines at the end of the file,
12317 * free the rest.
12318 */
12319 if (maxline < 0)
12320 while (cnt > -maxline)
12321 {
12322 listitem_remove(l, l->lv_first);
12323 --cnt;
12324 }
12325
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000012326 vim_free(prev);
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000012327 fclose(fd);
12328}
12329
12330
Bram Moolenaar0d660222005-01-07 21:51:51 +000012331#if defined(FEAT_CLIENTSERVER) && defined(FEAT_X11)
12332static void make_connection __ARGS((void));
12333static int check_connection __ARGS((void));
12334
12335 static void
12336make_connection()
12337{
12338 if (X_DISPLAY == NULL
12339# ifdef FEAT_GUI
12340 && !gui.in_use
12341# endif
12342 )
12343 {
12344 x_force_connect = TRUE;
12345 setup_term_clip();
12346 x_force_connect = FALSE;
12347 }
12348}
12349
12350 static int
12351check_connection()
12352{
12353 make_connection();
12354 if (X_DISPLAY == NULL)
12355 {
12356 EMSG(_("E240: No connection to Vim server"));
12357 return FAIL;
12358 }
12359 return OK;
12360}
12361#endif
12362
12363#ifdef FEAT_CLIENTSERVER
Bram Moolenaar33570922005-01-25 22:26:29 +000012364static void remote_common __ARGS((typval_T *argvars, typval_T *rettv, int expr));
Bram Moolenaar0d660222005-01-07 21:51:51 +000012365
12366 static void
12367remote_common(argvars, rettv, expr)
Bram Moolenaar33570922005-01-25 22:26:29 +000012368 typval_T *argvars;
12369 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000012370 int expr;
12371{
12372 char_u *server_name;
12373 char_u *keys;
12374 char_u *r = NULL;
12375 char_u buf[NUMBUFLEN];
12376# ifdef WIN32
12377 HWND w;
12378# else
12379 Window w;
12380# endif
12381
12382 if (check_restricted() || check_secure())
12383 return;
12384
12385# ifdef FEAT_X11
12386 if (check_connection() == FAIL)
12387 return;
12388# endif
12389
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000012390 server_name = get_tv_string_chk(&argvars[0]);
12391 if (server_name == NULL)
12392 return; /* type error; errmsg already given */
Bram Moolenaar0d660222005-01-07 21:51:51 +000012393 keys = get_tv_string_buf(&argvars[1], buf);
12394# ifdef WIN32
12395 if (serverSendToVim(server_name, keys, &r, &w, expr, TRUE) < 0)
12396# else
12397 if (serverSendToVim(X_DISPLAY, server_name, keys, &r, &w, expr, 0, TRUE)
12398 < 0)
12399# endif
12400 {
12401 if (r != NULL)
12402 EMSG(r); /* sending worked but evaluation failed */
12403 else
12404 EMSG2(_("E241: Unable to send to %s"), server_name);
12405 return;
12406 }
12407
12408 rettv->vval.v_string = r;
12409
12410 if (argvars[2].v_type != VAR_UNKNOWN)
12411 {
Bram Moolenaar33570922005-01-25 22:26:29 +000012412 dictitem_T v;
Bram Moolenaar555b2802005-05-19 21:08:39 +000012413 char_u str[30];
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000012414 char_u *idvar;
Bram Moolenaar0d660222005-01-07 21:51:51 +000012415
12416 sprintf((char *)str, "0x%x", (unsigned int)w);
Bram Moolenaar33570922005-01-25 22:26:29 +000012417 v.di_tv.v_type = VAR_STRING;
12418 v.di_tv.vval.v_string = vim_strsave(str);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000012419 idvar = get_tv_string_chk(&argvars[2]);
12420 if (idvar != NULL)
12421 set_var(idvar, &v.di_tv, FALSE);
Bram Moolenaar33570922005-01-25 22:26:29 +000012422 vim_free(v.di_tv.vval.v_string);
Bram Moolenaar0d660222005-01-07 21:51:51 +000012423 }
12424}
12425#endif
12426
12427/*
12428 * "remote_expr()" function
12429 */
12430/*ARGSUSED*/
12431 static void
12432f_remote_expr(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000012433 typval_T *argvars;
12434 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000012435{
12436 rettv->v_type = VAR_STRING;
12437 rettv->vval.v_string = NULL;
12438#ifdef FEAT_CLIENTSERVER
12439 remote_common(argvars, rettv, TRUE);
12440#endif
12441}
12442
12443/*
12444 * "remote_foreground()" function
12445 */
12446/*ARGSUSED*/
12447 static void
12448f_remote_foreground(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000012449 typval_T *argvars;
12450 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000012451{
12452 rettv->vval.v_number = 0;
12453#ifdef FEAT_CLIENTSERVER
12454# ifdef WIN32
12455 /* On Win32 it's done in this application. */
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000012456 {
12457 char_u *server_name = get_tv_string_chk(&argvars[0]);
12458
12459 if (server_name != NULL)
12460 serverForeground(server_name);
12461 }
Bram Moolenaar0d660222005-01-07 21:51:51 +000012462# else
12463 /* Send a foreground() expression to the server. */
12464 argvars[1].v_type = VAR_STRING;
12465 argvars[1].vval.v_string = vim_strsave((char_u *)"foreground()");
12466 argvars[2].v_type = VAR_UNKNOWN;
12467 remote_common(argvars, rettv, TRUE);
12468 vim_free(argvars[1].vval.v_string);
12469# endif
12470#endif
12471}
12472
12473/*ARGSUSED*/
12474 static void
12475f_remote_peek(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000012476 typval_T *argvars;
12477 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000012478{
12479#ifdef FEAT_CLIENTSERVER
Bram Moolenaar33570922005-01-25 22:26:29 +000012480 dictitem_T v;
Bram Moolenaar0d660222005-01-07 21:51:51 +000012481 char_u *s = NULL;
12482# ifdef WIN32
12483 int n = 0;
12484# endif
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000012485 char_u *serverid;
Bram Moolenaar0d660222005-01-07 21:51:51 +000012486
12487 if (check_restricted() || check_secure())
12488 {
12489 rettv->vval.v_number = -1;
12490 return;
12491 }
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000012492 serverid = get_tv_string_chk(&argvars[0]);
12493 if (serverid == NULL)
12494 {
12495 rettv->vval.v_number = -1;
12496 return; /* type error; errmsg already given */
12497 }
Bram Moolenaar0d660222005-01-07 21:51:51 +000012498# ifdef WIN32
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000012499 sscanf(serverid, "%x", &n);
Bram Moolenaar0d660222005-01-07 21:51:51 +000012500 if (n == 0)
12501 rettv->vval.v_number = -1;
12502 else
12503 {
12504 s = serverGetReply((HWND)n, FALSE, FALSE, FALSE);
12505 rettv->vval.v_number = (s != NULL);
12506 }
12507# else
12508 rettv->vval.v_number = 0;
12509 if (check_connection() == FAIL)
12510 return;
12511
12512 rettv->vval.v_number = serverPeekReply(X_DISPLAY,
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000012513 serverStrToWin(serverid), &s);
Bram Moolenaar0d660222005-01-07 21:51:51 +000012514# endif
12515
12516 if (argvars[1].v_type != VAR_UNKNOWN && rettv->vval.v_number > 0)
12517 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000012518 char_u *retvar;
12519
Bram Moolenaar33570922005-01-25 22:26:29 +000012520 v.di_tv.v_type = VAR_STRING;
12521 v.di_tv.vval.v_string = vim_strsave(s);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000012522 retvar = get_tv_string_chk(&argvars[1]);
12523 if (retvar != NULL)
12524 set_var(retvar, &v.di_tv, FALSE);
Bram Moolenaar33570922005-01-25 22:26:29 +000012525 vim_free(v.di_tv.vval.v_string);
Bram Moolenaar0d660222005-01-07 21:51:51 +000012526 }
12527#else
12528 rettv->vval.v_number = -1;
12529#endif
12530}
12531
12532/*ARGSUSED*/
12533 static void
12534f_remote_read(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000012535 typval_T *argvars;
12536 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000012537{
12538 char_u *r = NULL;
12539
12540#ifdef FEAT_CLIENTSERVER
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000012541 char_u *serverid = get_tv_string_chk(&argvars[0]);
12542
12543 if (serverid != NULL && !check_restricted() && !check_secure())
Bram Moolenaar0d660222005-01-07 21:51:51 +000012544 {
12545# ifdef WIN32
12546 /* The server's HWND is encoded in the 'id' parameter */
12547 int n = 0;
12548
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000012549 sscanf(serverid, "%x", &n);
Bram Moolenaar0d660222005-01-07 21:51:51 +000012550 if (n != 0)
12551 r = serverGetReply((HWND)n, FALSE, TRUE, TRUE);
12552 if (r == NULL)
12553# else
12554 if (check_connection() == FAIL || serverReadReply(X_DISPLAY,
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000012555 serverStrToWin(serverid), &r, FALSE) < 0)
Bram Moolenaar0d660222005-01-07 21:51:51 +000012556# endif
12557 EMSG(_("E277: Unable to read a server reply"));
12558 }
12559#endif
12560 rettv->v_type = VAR_STRING;
12561 rettv->vval.v_string = r;
12562}
12563
12564/*
12565 * "remote_send()" function
12566 */
12567/*ARGSUSED*/
12568 static void
12569f_remote_send(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000012570 typval_T *argvars;
12571 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000012572{
12573 rettv->v_type = VAR_STRING;
12574 rettv->vval.v_string = NULL;
12575#ifdef FEAT_CLIENTSERVER
12576 remote_common(argvars, rettv, FALSE);
12577#endif
12578}
12579
12580/*
Bram Moolenaar8c711452005-01-14 21:53:12 +000012581 * "remove()" function
Bram Moolenaar49cd9572005-01-03 21:06:01 +000012582 */
12583 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012584f_remove(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000012585 typval_T *argvars;
12586 typval_T *rettv;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000012587{
Bram Moolenaar33570922005-01-25 22:26:29 +000012588 list_T *l;
12589 listitem_T *item, *item2;
12590 listitem_T *li;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000012591 long idx;
Bram Moolenaar8a283e52005-01-06 23:28:25 +000012592 long end;
Bram Moolenaar8c711452005-01-14 21:53:12 +000012593 char_u *key;
Bram Moolenaar33570922005-01-25 22:26:29 +000012594 dict_T *d;
12595 dictitem_T *di;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000012596
Bram Moolenaar8a283e52005-01-06 23:28:25 +000012597 rettv->vval.v_number = 0;
Bram Moolenaar8c711452005-01-14 21:53:12 +000012598 if (argvars[0].v_type == VAR_DICT)
12599 {
12600 if (argvars[2].v_type != VAR_UNKNOWN)
12601 EMSG2(_(e_toomanyarg), "remove()");
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000012602 else if ((d = argvars[0].vval.v_dict) != NULL
Bram Moolenaar758711c2005-02-02 23:11:38 +000012603 && !tv_check_lock(d->dv_lock, (char_u *)"remove()"))
Bram Moolenaar8c711452005-01-14 21:53:12 +000012604 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000012605 key = get_tv_string_chk(&argvars[1]);
12606 if (key != NULL)
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000012607 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000012608 di = dict_find(d, key, -1);
12609 if (di == NULL)
12610 EMSG2(_(e_dictkey), key);
12611 else
12612 {
12613 *rettv = di->di_tv;
12614 init_tv(&di->di_tv);
12615 dictitem_remove(d, di);
12616 }
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000012617 }
Bram Moolenaar8c711452005-01-14 21:53:12 +000012618 }
12619 }
12620 else if (argvars[0].v_type != VAR_LIST)
12621 EMSG2(_(e_listdictarg), "remove()");
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000012622 else if ((l = argvars[0].vval.v_list) != NULL
12623 && !tv_check_lock(l->lv_lock, (char_u *)"remove()"))
Bram Moolenaar49cd9572005-01-03 21:06:01 +000012624 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000012625 int error = FALSE;
12626
12627 idx = get_tv_number_chk(&argvars[1], &error);
12628 if (error)
12629 ; /* type error: do nothing, errmsg already given */
12630 else if ((item = list_find(l, idx)) == NULL)
Bram Moolenaar49cd9572005-01-03 21:06:01 +000012631 EMSGN(_(e_listidx), idx);
12632 else
12633 {
Bram Moolenaar8a283e52005-01-06 23:28:25 +000012634 if (argvars[2].v_type == VAR_UNKNOWN)
12635 {
12636 /* Remove one item, return its value. */
Bram Moolenaar7480b5c2005-01-16 22:07:38 +000012637 list_remove(l, item, item);
Bram Moolenaar8a283e52005-01-06 23:28:25 +000012638 *rettv = item->li_tv;
12639 vim_free(item);
12640 }
12641 else
12642 {
12643 /* Remove range of items, return list with values. */
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000012644 end = get_tv_number_chk(&argvars[2], &error);
12645 if (error)
12646 ; /* type error: do nothing */
12647 else if ((item2 = list_find(l, end)) == NULL)
Bram Moolenaar8a283e52005-01-06 23:28:25 +000012648 EMSGN(_(e_listidx), end);
12649 else
12650 {
Bram Moolenaar758711c2005-02-02 23:11:38 +000012651 int cnt = 0;
12652
12653 for (li = item; li != NULL; li = li->li_next)
12654 {
12655 ++cnt;
12656 if (li == item2)
12657 break;
12658 }
Bram Moolenaar8a283e52005-01-06 23:28:25 +000012659 if (li == NULL) /* didn't find "item2" after "item" */
12660 EMSG(_(e_invrange));
12661 else
12662 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +000012663 list_remove(l, item, item2);
Bram Moolenaar8a283e52005-01-06 23:28:25 +000012664 l = list_alloc();
12665 if (l != NULL)
12666 {
12667 rettv->v_type = VAR_LIST;
12668 rettv->vval.v_list = l;
12669 l->lv_first = item;
12670 l->lv_last = item2;
12671 l->lv_refcount = 1;
12672 item->li_prev = NULL;
12673 item2->li_next = NULL;
Bram Moolenaar758711c2005-02-02 23:11:38 +000012674 l->lv_len = cnt;
Bram Moolenaar8a283e52005-01-06 23:28:25 +000012675 }
12676 }
12677 }
12678 }
Bram Moolenaar49cd9572005-01-03 21:06:01 +000012679 }
12680 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000012681}
12682
12683/*
12684 * "rename({from}, {to})" function
12685 */
12686 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012687f_rename(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000012688 typval_T *argvars;
12689 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012690{
12691 char_u buf[NUMBUFLEN];
12692
12693 if (check_restricted() || check_secure())
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012694 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012695 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012696 rettv->vval.v_number = vim_rename(get_tv_string(&argvars[0]),
12697 get_tv_string_buf(&argvars[1], buf));
Bram Moolenaar071d4272004-06-13 20:20:40 +000012698}
12699
12700/*
Bram Moolenaar8a283e52005-01-06 23:28:25 +000012701 * "repeat()" function
12702 */
12703/*ARGSUSED*/
12704 static void
12705f_repeat(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000012706 typval_T *argvars;
12707 typval_T *rettv;
Bram Moolenaar8a283e52005-01-06 23:28:25 +000012708{
12709 char_u *p;
12710 int n;
12711 int slen;
12712 int len;
12713 char_u *r;
12714 int i;
Bram Moolenaar33570922005-01-25 22:26:29 +000012715 list_T *l;
Bram Moolenaar8a283e52005-01-06 23:28:25 +000012716
12717 n = get_tv_number(&argvars[1]);
12718 if (argvars[0].v_type == VAR_LIST)
12719 {
12720 l = list_alloc();
12721 if (l != NULL && argvars[0].vval.v_list != NULL)
12722 {
12723 l->lv_refcount = 1;
12724 while (n-- > 0)
12725 if (list_extend(l, argvars[0].vval.v_list, NULL) == FAIL)
12726 break;
12727 }
12728 rettv->v_type = VAR_LIST;
12729 rettv->vval.v_list = l;
12730 }
12731 else
12732 {
12733 p = get_tv_string(&argvars[0]);
12734 rettv->v_type = VAR_STRING;
12735 rettv->vval.v_string = NULL;
12736
12737 slen = (int)STRLEN(p);
12738 len = slen * n;
12739 if (len <= 0)
12740 return;
12741
12742 r = alloc(len + 1);
12743 if (r != NULL)
12744 {
12745 for (i = 0; i < n; i++)
12746 mch_memmove(r + i * slen, p, (size_t)slen);
12747 r[len] = NUL;
12748 }
12749
12750 rettv->vval.v_string = r;
12751 }
12752}
12753
12754/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000012755 * "resolve()" function
12756 */
12757 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012758f_resolve(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000012759 typval_T *argvars;
12760 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012761{
12762 char_u *p;
12763
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012764 p = get_tv_string(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +000012765#ifdef FEAT_SHORTCUT
12766 {
12767 char_u *v = NULL;
12768
12769 v = mch_resolve_shortcut(p);
12770 if (v != NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012771 rettv->vval.v_string = v;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012772 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012773 rettv->vval.v_string = vim_strsave(p);
Bram Moolenaar071d4272004-06-13 20:20:40 +000012774 }
12775#else
12776# ifdef HAVE_READLINK
12777 {
12778 char_u buf[MAXPATHL + 1];
12779 char_u *cpy;
12780 int len;
12781 char_u *remain = NULL;
12782 char_u *q;
12783 int is_relative_to_current = FALSE;
12784 int has_trailing_pathsep = FALSE;
12785 int limit = 100;
12786
12787 p = vim_strsave(p);
12788
12789 if (p[0] == '.' && (vim_ispathsep(p[1])
12790 || (p[1] == '.' && (vim_ispathsep(p[2])))))
12791 is_relative_to_current = TRUE;
12792
12793 len = STRLEN(p);
Bram Moolenaar1cd871b2004-12-19 22:46:22 +000012794 if (len > 0 && after_pathsep(p, p + len))
Bram Moolenaar071d4272004-06-13 20:20:40 +000012795 has_trailing_pathsep = TRUE;
12796
12797 q = getnextcomp(p);
12798 if (*q != NUL)
12799 {
12800 /* Separate the first path component in "p", and keep the
12801 * remainder (beginning with the path separator). */
12802 remain = vim_strsave(q - 1);
12803 q[-1] = NUL;
12804 }
12805
12806 for (;;)
12807 {
12808 for (;;)
12809 {
12810 len = readlink((char *)p, (char *)buf, MAXPATHL);
12811 if (len <= 0)
12812 break;
12813 buf[len] = NUL;
12814
12815 if (limit-- == 0)
12816 {
12817 vim_free(p);
12818 vim_free(remain);
12819 EMSG(_("E655: Too many symbolic links (cycle?)"));
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012820 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012821 goto fail;
12822 }
12823
12824 /* Ensure that the result will have a trailing path separator
12825 * if the argument has one. */
12826 if (remain == NULL && has_trailing_pathsep)
12827 add_pathsep(buf);
12828
12829 /* Separate the first path component in the link value and
12830 * concatenate the remainders. */
12831 q = getnextcomp(vim_ispathsep(*buf) ? buf + 1 : buf);
12832 if (*q != NUL)
12833 {
12834 if (remain == NULL)
12835 remain = vim_strsave(q - 1);
12836 else
12837 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000012838 cpy = vim_strnsave(q-1, STRLEN(q-1) + STRLEN(remain));
Bram Moolenaar071d4272004-06-13 20:20:40 +000012839 if (cpy != NULL)
12840 {
12841 STRCAT(cpy, remain);
12842 vim_free(remain);
12843 remain = cpy;
12844 }
12845 }
12846 q[-1] = NUL;
12847 }
12848
12849 q = gettail(p);
12850 if (q > p && *q == NUL)
12851 {
12852 /* Ignore trailing path separator. */
12853 q[-1] = NUL;
12854 q = gettail(p);
12855 }
12856 if (q > p && !mch_isFullName(buf))
12857 {
12858 /* symlink is relative to directory of argument */
12859 cpy = alloc((unsigned)(STRLEN(p) + STRLEN(buf) + 1));
12860 if (cpy != NULL)
12861 {
12862 STRCPY(cpy, p);
12863 STRCPY(gettail(cpy), buf);
12864 vim_free(p);
12865 p = cpy;
12866 }
12867 }
12868 else
12869 {
12870 vim_free(p);
12871 p = vim_strsave(buf);
12872 }
12873 }
12874
12875 if (remain == NULL)
12876 break;
12877
12878 /* Append the first path component of "remain" to "p". */
12879 q = getnextcomp(remain + 1);
12880 len = q - remain - (*q != NUL);
12881 cpy = vim_strnsave(p, STRLEN(p) + len);
12882 if (cpy != NULL)
12883 {
12884 STRNCAT(cpy, remain, len);
12885 vim_free(p);
12886 p = cpy;
12887 }
12888 /* Shorten "remain". */
12889 if (*q != NUL)
12890 STRCPY(remain, q - 1);
12891 else
12892 {
12893 vim_free(remain);
12894 remain = NULL;
12895 }
12896 }
12897
12898 /* If the result is a relative path name, make it explicitly relative to
12899 * the current directory if and only if the argument had this form. */
12900 if (!vim_ispathsep(*p))
12901 {
12902 if (is_relative_to_current
12903 && *p != NUL
12904 && !(p[0] == '.'
12905 && (p[1] == NUL
12906 || vim_ispathsep(p[1])
12907 || (p[1] == '.'
12908 && (p[2] == NUL
12909 || vim_ispathsep(p[2]))))))
12910 {
12911 /* Prepend "./". */
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000012912 cpy = concat_str((char_u *)"./", p);
Bram Moolenaar071d4272004-06-13 20:20:40 +000012913 if (cpy != NULL)
12914 {
Bram Moolenaar071d4272004-06-13 20:20:40 +000012915 vim_free(p);
12916 p = cpy;
12917 }
12918 }
12919 else if (!is_relative_to_current)
12920 {
12921 /* Strip leading "./". */
12922 q = p;
12923 while (q[0] == '.' && vim_ispathsep(q[1]))
12924 q += 2;
12925 if (q > p)
12926 mch_memmove(p, p + 2, STRLEN(p + 2) + (size_t)1);
12927 }
12928 }
12929
12930 /* Ensure that the result will have no trailing path separator
12931 * if the argument had none. But keep "/" or "//". */
12932 if (!has_trailing_pathsep)
12933 {
12934 q = p + STRLEN(p);
Bram Moolenaar1cd871b2004-12-19 22:46:22 +000012935 if (after_pathsep(p, q))
12936 *gettail_sep(p) = NUL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012937 }
12938
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012939 rettv->vval.v_string = p;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012940 }
12941# else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012942 rettv->vval.v_string = vim_strsave(p);
Bram Moolenaar071d4272004-06-13 20:20:40 +000012943# endif
12944#endif
12945
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012946 simplify_filename(rettv->vval.v_string);
Bram Moolenaar071d4272004-06-13 20:20:40 +000012947
12948#ifdef HAVE_READLINK
12949fail:
12950#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012951 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012952}
12953
12954/*
Bram Moolenaar0d660222005-01-07 21:51:51 +000012955 * "reverse({list})" function
Bram Moolenaar071d4272004-06-13 20:20:40 +000012956 */
12957 static void
Bram Moolenaar0d660222005-01-07 21:51:51 +000012958f_reverse(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000012959 typval_T *argvars;
12960 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012961{
Bram Moolenaar33570922005-01-25 22:26:29 +000012962 list_T *l;
12963 listitem_T *li, *ni;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012964
Bram Moolenaar0d660222005-01-07 21:51:51 +000012965 rettv->vval.v_number = 0;
12966 if (argvars[0].v_type != VAR_LIST)
12967 EMSG2(_(e_listarg), "reverse()");
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000012968 else if ((l = argvars[0].vval.v_list) != NULL
12969 && !tv_check_lock(l->lv_lock, (char_u *)"reverse()"))
Bram Moolenaar0d660222005-01-07 21:51:51 +000012970 {
12971 li = l->lv_last;
Bram Moolenaar81bf7082005-02-12 14:31:42 +000012972 l->lv_first = l->lv_last = NULL;
Bram Moolenaar758711c2005-02-02 23:11:38 +000012973 l->lv_len = 0;
Bram Moolenaar0d660222005-01-07 21:51:51 +000012974 while (li != NULL)
12975 {
12976 ni = li->li_prev;
12977 list_append(l, li);
12978 li = ni;
12979 }
12980 rettv->vval.v_list = l;
12981 rettv->v_type = VAR_LIST;
12982 ++l->lv_refcount;
12983 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000012984}
12985
Bram Moolenaar5eb86f92004-07-26 12:53:41 +000012986#define SP_NOMOVE 1 /* don't move cursor */
12987#define SP_REPEAT 2 /* repeat to find outer pair */
12988#define SP_RETCOUNT 4 /* return matchcount */
Bram Moolenaar231334e2005-07-25 20:46:57 +000012989#define SP_SETPCMARK 8 /* set previous context mark */
Bram Moolenaar5eb86f92004-07-26 12:53:41 +000012990
Bram Moolenaar33570922005-01-25 22:26:29 +000012991static int get_search_arg __ARGS((typval_T *varp, int *flagsp));
Bram Moolenaar0d660222005-01-07 21:51:51 +000012992
12993/*
12994 * Get flags for a search function.
12995 * Possibly sets "p_ws".
12996 * Returns BACKWARD, FORWARD or zero (for an error).
12997 */
12998 static int
12999get_search_arg(varp, flagsp)
Bram Moolenaar33570922005-01-25 22:26:29 +000013000 typval_T *varp;
Bram Moolenaar0d660222005-01-07 21:51:51 +000013001 int *flagsp;
13002{
13003 int dir = FORWARD;
13004 char_u *flags;
13005 char_u nbuf[NUMBUFLEN];
13006 int mask;
13007
13008 if (varp->v_type != VAR_UNKNOWN)
13009 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013010 flags = get_tv_string_buf_chk(varp, nbuf);
13011 if (flags == NULL)
13012 return 0; /* type error; errmsg already given */
Bram Moolenaar0d660222005-01-07 21:51:51 +000013013 while (*flags != NUL)
13014 {
13015 switch (*flags)
13016 {
13017 case 'b': dir = BACKWARD; break;
13018 case 'w': p_ws = TRUE; break;
13019 case 'W': p_ws = FALSE; break;
13020 default: mask = 0;
13021 if (flagsp != NULL)
13022 switch (*flags)
13023 {
13024 case 'n': mask = SP_NOMOVE; break;
13025 case 'r': mask = SP_REPEAT; break;
13026 case 'm': mask = SP_RETCOUNT; break;
Bram Moolenaar231334e2005-07-25 20:46:57 +000013027 case 's': mask = SP_SETPCMARK; break;
Bram Moolenaar0d660222005-01-07 21:51:51 +000013028 }
13029 if (mask == 0)
13030 {
13031 EMSG2(_(e_invarg2), flags);
13032 dir = 0;
13033 }
13034 else
13035 *flagsp |= mask;
13036 }
13037 if (dir == 0)
13038 break;
13039 ++flags;
13040 }
13041 }
13042 return dir;
13043}
13044
Bram Moolenaar071d4272004-06-13 20:20:40 +000013045/*
13046 * "search()" function
13047 */
13048 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013049f_search(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000013050 typval_T *argvars;
13051 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013052{
13053 char_u *pat;
13054 pos_T pos;
Bram Moolenaar5eb86f92004-07-26 12:53:41 +000013055 pos_T save_cursor;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013056 int save_p_ws = p_ws;
13057 int dir;
Bram Moolenaar5eb86f92004-07-26 12:53:41 +000013058 int flags = 0;
13059
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013060 rettv->vval.v_number = 0; /* default: FAIL */
Bram Moolenaar071d4272004-06-13 20:20:40 +000013061
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013062 pat = get_tv_string(&argvars[0]);
Bram Moolenaar5eb86f92004-07-26 12:53:41 +000013063 dir = get_search_arg(&argvars[1], &flags); /* may set p_ws */
13064 if (dir == 0)
13065 goto theend;
Bram Moolenaar231334e2005-07-25 20:46:57 +000013066 /*
13067 * This function accepts only SP_NOMOVE and SP_SETPCMARK flags.
13068 * Check to make sure only those flags are set.
13069 * Also, Only the SP_NOMOVE or the SP_SETPCMARK flag can be set. Both
13070 * flags cannot be set. Check for that condition also.
13071 */
13072 if (((flags & ~(SP_NOMOVE | SP_SETPCMARK)) != 0) ||
13073 ((flags & SP_NOMOVE) && (flags & SP_SETPCMARK)))
Bram Moolenaar5eb86f92004-07-26 12:53:41 +000013074 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013075 EMSG2(_(e_invarg2), get_tv_string(&argvars[1]));
Bram Moolenaar5eb86f92004-07-26 12:53:41 +000013076 goto theend;
13077 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000013078
Bram Moolenaar5eb86f92004-07-26 12:53:41 +000013079 pos = save_cursor = curwin->w_cursor;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013080 if (searchit(curwin, curbuf, &pos, dir, pat, 1L,
13081 SEARCH_KEEP, RE_SEARCH) != FAIL)
13082 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013083 rettv->vval.v_number = pos.lnum;
Bram Moolenaar231334e2005-07-25 20:46:57 +000013084 if (flags & SP_SETPCMARK)
13085 setpcmark();
Bram Moolenaar071d4272004-06-13 20:20:40 +000013086 curwin->w_cursor = pos;
13087 /* "/$" will put the cursor after the end of the line, may need to
13088 * correct that here */
13089 check_cursor();
13090 }
Bram Moolenaar5eb86f92004-07-26 12:53:41 +000013091
13092 /* If 'n' flag is used: restore cursor position. */
13093 if (flags & SP_NOMOVE)
13094 curwin->w_cursor = save_cursor;
13095theend:
Bram Moolenaar071d4272004-06-13 20:20:40 +000013096 p_ws = save_p_ws;
13097}
13098
Bram Moolenaar071d4272004-06-13 20:20:40 +000013099/*
Bram Moolenaardd2436f2005-09-05 22:14:46 +000013100 * "searchdecl()" function
13101 */
13102 static void
13103f_searchdecl(argvars, rettv)
13104 typval_T *argvars;
13105 typval_T *rettv;
13106{
13107 int locally = 1;
Bram Moolenaare6facf92005-09-13 21:22:27 +000013108 int thisblock = 0;
Bram Moolenaardd2436f2005-09-05 22:14:46 +000013109 int error = FALSE;
13110 char_u *name;
13111
13112 rettv->vval.v_number = 1; /* default: FAIL */
13113
13114 name = get_tv_string_chk(&argvars[0]);
13115 if (argvars[1].v_type != VAR_UNKNOWN)
Bram Moolenaare6facf92005-09-13 21:22:27 +000013116 {
Bram Moolenaardd2436f2005-09-05 22:14:46 +000013117 locally = get_tv_number_chk(&argvars[1], &error) == 0;
Bram Moolenaare6facf92005-09-13 21:22:27 +000013118 if (!error && argvars[2].v_type != VAR_UNKNOWN)
13119 thisblock = get_tv_number_chk(&argvars[2], &error) != 0;
13120 }
Bram Moolenaardd2436f2005-09-05 22:14:46 +000013121 if (!error && name != NULL)
13122 rettv->vval.v_number = find_decl(name, (int)STRLEN(name),
Bram Moolenaare6facf92005-09-13 21:22:27 +000013123 locally, thisblock, SEARCH_KEEP) == FAIL;
Bram Moolenaardd2436f2005-09-05 22:14:46 +000013124}
13125
13126/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000013127 * "searchpair()" function
13128 */
13129 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013130f_searchpair(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000013131 typval_T *argvars;
13132 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013133{
13134 char_u *spat, *mpat, *epat;
13135 char_u *skip;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013136 int save_p_ws = p_ws;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013137 int dir;
13138 int flags = 0;
13139 char_u nbuf1[NUMBUFLEN];
13140 char_u nbuf2[NUMBUFLEN];
13141 char_u nbuf3[NUMBUFLEN];
Bram Moolenaar071d4272004-06-13 20:20:40 +000013142
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013143 rettv->vval.v_number = 0; /* default: FAIL */
Bram Moolenaar071d4272004-06-13 20:20:40 +000013144
Bram Moolenaar071d4272004-06-13 20:20:40 +000013145 /* Get the three pattern arguments: start, middle, end. */
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013146 spat = get_tv_string_chk(&argvars[0]);
13147 mpat = get_tv_string_buf_chk(&argvars[1], nbuf1);
13148 epat = get_tv_string_buf_chk(&argvars[2], nbuf2);
13149 if (spat == NULL || mpat == NULL || epat == NULL)
13150 goto theend; /* type error */
Bram Moolenaar071d4272004-06-13 20:20:40 +000013151
Bram Moolenaar071d4272004-06-13 20:20:40 +000013152 /* Handle the optional fourth argument: flags */
13153 dir = get_search_arg(&argvars[3], &flags); /* may set p_ws */
Bram Moolenaar5eb86f92004-07-26 12:53:41 +000013154 if (dir == 0)
13155 goto theend;
Bram Moolenaar231334e2005-07-25 20:46:57 +000013156 /*
13157 * Only one of the SP_NOMOVE or SP_SETPCMARK flags can be set.
13158 */
13159 if ((flags & SP_NOMOVE) && (flags & SP_SETPCMARK))
13160 {
13161 EMSG2(_(e_invarg2), get_tv_string(&argvars[1]));
13162 goto theend;
13163 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000013164
13165 /* Optional fifth argument: skip expresion */
Bram Moolenaar49cd9572005-01-03 21:06:01 +000013166 if (argvars[3].v_type == VAR_UNKNOWN
13167 || argvars[4].v_type == VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +000013168 skip = (char_u *)"";
13169 else
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013170 skip = get_tv_string_buf_chk(&argvars[4], nbuf3);
13171 if (skip == NULL)
13172 goto theend; /* type error */
Bram Moolenaar071d4272004-06-13 20:20:40 +000013173
Bram Moolenaar9fad3082005-07-19 22:22:13 +000013174 rettv->vval.v_number = do_searchpair(spat, mpat, epat, dir, skip, flags);
13175
13176theend:
13177 p_ws = save_p_ws;
13178}
13179
13180/*
13181 * Search for a start/middle/end thing.
13182 * Used by searchpair(), see its documentation for the details.
13183 * Returns 0 or -1 for no match,
13184 */
13185 long
13186do_searchpair(spat, mpat, epat, dir, skip, flags)
13187 char_u *spat; /* start pattern */
13188 char_u *mpat; /* middle pattern */
13189 char_u *epat; /* end pattern */
13190 int dir; /* BACKWARD or FORWARD */
13191 char_u *skip; /* skip expression */
13192 int flags; /* SP_RETCOUNT, SP_REPEAT, SP_NOMOVE */
13193{
13194 char_u *save_cpo;
13195 char_u *pat, *pat2 = NULL, *pat3 = NULL;
13196 long retval = 0;
13197 pos_T pos;
13198 pos_T firstpos;
13199 pos_T foundpos;
13200 pos_T save_cursor;
13201 pos_T save_pos;
13202 int n;
13203 int r;
13204 int nest = 1;
13205 int err;
13206
13207 /* Make 'cpoptions' empty, the 'l' flag should not be used here. */
13208 save_cpo = p_cpo;
13209 p_cpo = (char_u *)"";
13210
13211 /* Make two search patterns: start/end (pat2, for in nested pairs) and
13212 * start/middle/end (pat3, for the top pair). */
13213 pat2 = alloc((unsigned)(STRLEN(spat) + STRLEN(epat) + 15));
13214 pat3 = alloc((unsigned)(STRLEN(spat) + STRLEN(mpat) + STRLEN(epat) + 23));
13215 if (pat2 == NULL || pat3 == NULL)
13216 goto theend;
13217 sprintf((char *)pat2, "\\(%s\\m\\)\\|\\(%s\\m\\)", spat, epat);
13218 if (*mpat == NUL)
13219 STRCPY(pat3, pat2);
13220 else
13221 sprintf((char *)pat3, "\\(%s\\m\\)\\|\\(%s\\m\\)\\|\\(%s\\m\\)",
13222 spat, epat, mpat);
13223
Bram Moolenaar071d4272004-06-13 20:20:40 +000013224 save_cursor = curwin->w_cursor;
13225 pos = curwin->w_cursor;
13226 firstpos.lnum = 0;
Bram Moolenaarc9a2d2e2005-04-24 22:09:56 +000013227 foundpos.lnum = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013228 pat = pat3;
13229 for (;;)
13230 {
13231 n = searchit(curwin, curbuf, &pos, dir, pat, 1L,
13232 SEARCH_KEEP, RE_SEARCH);
13233 if (n == FAIL || (firstpos.lnum != 0 && equalpos(pos, firstpos)))
13234 /* didn't find it or found the first match again: FAIL */
13235 break;
13236
13237 if (firstpos.lnum == 0)
13238 firstpos = pos;
Bram Moolenaarc9a2d2e2005-04-24 22:09:56 +000013239 if (equalpos(pos, foundpos))
13240 {
13241 /* Found the same position again. Can happen with a pattern that
13242 * has "\zs" at the end and searching backwards. Advance one
13243 * character and try again. */
13244 if (dir == BACKWARD)
13245 decl(&pos);
13246 else
13247 incl(&pos);
13248 }
13249 foundpos = pos;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013250
13251 /* If the skip pattern matches, ignore this match. */
13252 if (*skip != NUL)
13253 {
13254 save_pos = curwin->w_cursor;
13255 curwin->w_cursor = pos;
13256 r = eval_to_bool(skip, &err, NULL, FALSE);
13257 curwin->w_cursor = save_pos;
13258 if (err)
13259 {
13260 /* Evaluating {skip} caused an error, break here. */
13261 curwin->w_cursor = save_cursor;
Bram Moolenaar9fad3082005-07-19 22:22:13 +000013262 retval = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013263 break;
13264 }
13265 if (r)
13266 continue;
13267 }
13268
13269 if ((dir == BACKWARD && n == 3) || (dir == FORWARD && n == 2))
13270 {
13271 /* Found end when searching backwards or start when searching
13272 * forward: nested pair. */
13273 ++nest;
13274 pat = pat2; /* nested, don't search for middle */
13275 }
13276 else
13277 {
13278 /* Found end when searching forward or start when searching
13279 * backward: end of (nested) pair; or found middle in outer pair. */
13280 if (--nest == 1)
13281 pat = pat3; /* outer level, search for middle */
13282 }
13283
13284 if (nest == 0)
13285 {
13286 /* Found the match: return matchcount or line number. */
13287 if (flags & SP_RETCOUNT)
Bram Moolenaar9fad3082005-07-19 22:22:13 +000013288 ++retval;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013289 else
Bram Moolenaar9fad3082005-07-19 22:22:13 +000013290 retval = pos.lnum;
Bram Moolenaar231334e2005-07-25 20:46:57 +000013291 if (flags & SP_SETPCMARK)
13292 setpcmark();
Bram Moolenaar071d4272004-06-13 20:20:40 +000013293 curwin->w_cursor = pos;
13294 if (!(flags & SP_REPEAT))
13295 break;
13296 nest = 1; /* search for next unmatched */
13297 }
13298 }
13299
13300 /* If 'n' flag is used or search failed: restore cursor position. */
Bram Moolenaar9fad3082005-07-19 22:22:13 +000013301 if ((flags & SP_NOMOVE) || retval == 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +000013302 curwin->w_cursor = save_cursor;
13303
13304theend:
13305 vim_free(pat2);
13306 vim_free(pat3);
Bram Moolenaar071d4272004-06-13 20:20:40 +000013307 p_cpo = save_cpo;
Bram Moolenaar9fad3082005-07-19 22:22:13 +000013308
13309 return retval;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013310}
13311
Bram Moolenaar0d660222005-01-07 21:51:51 +000013312/*ARGSUSED*/
13313 static void
13314f_server2client(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000013315 typval_T *argvars;
13316 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013317{
Bram Moolenaar0d660222005-01-07 21:51:51 +000013318#ifdef FEAT_CLIENTSERVER
13319 char_u buf[NUMBUFLEN];
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013320 char_u *server = get_tv_string_chk(&argvars[0]);
13321 char_u *reply = get_tv_string_buf_chk(&argvars[1], buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +000013322
Bram Moolenaar0d660222005-01-07 21:51:51 +000013323 rettv->vval.v_number = -1;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013324 if (server == NULL || reply == NULL)
13325 return;
Bram Moolenaar0d660222005-01-07 21:51:51 +000013326 if (check_restricted() || check_secure())
13327 return;
13328# ifdef FEAT_X11
13329 if (check_connection() == FAIL)
13330 return;
13331# endif
13332
13333 if (serverSendReply(server, reply) < 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +000013334 {
Bram Moolenaar0d660222005-01-07 21:51:51 +000013335 EMSG(_("E258: Unable to send to client"));
13336 return;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013337 }
Bram Moolenaar0d660222005-01-07 21:51:51 +000013338 rettv->vval.v_number = 0;
13339#else
13340 rettv->vval.v_number = -1;
13341#endif
13342}
13343
13344/*ARGSUSED*/
13345 static void
13346f_serverlist(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000013347 typval_T *argvars;
13348 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000013349{
13350 char_u *r = NULL;
13351
13352#ifdef FEAT_CLIENTSERVER
13353# ifdef WIN32
13354 r = serverGetVimNames();
13355# else
13356 make_connection();
13357 if (X_DISPLAY != NULL)
13358 r = serverGetVimNames(X_DISPLAY);
13359# endif
13360#endif
13361 rettv->v_type = VAR_STRING;
13362 rettv->vval.v_string = r;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013363}
13364
13365/*
13366 * "setbufvar()" function
13367 */
13368/*ARGSUSED*/
13369 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013370f_setbufvar(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000013371 typval_T *argvars;
13372 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013373{
13374 buf_T *buf;
13375#ifdef FEAT_AUTOCMD
13376 aco_save_T aco;
13377#else
13378 buf_T *save_curbuf;
13379#endif
13380 char_u *varname, *bufvarname;
Bram Moolenaar33570922005-01-25 22:26:29 +000013381 typval_T *varp;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013382 char_u nbuf[NUMBUFLEN];
13383
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013384 rettv->vval.v_number = 0;
13385
Bram Moolenaar071d4272004-06-13 20:20:40 +000013386 if (check_restricted() || check_secure())
13387 return;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013388 (void)get_tv_number(&argvars[0]); /* issue errmsg if type error */
13389 varname = get_tv_string_chk(&argvars[1]);
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013390 buf = get_buf_tv(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +000013391 varp = &argvars[2];
13392
13393 if (buf != NULL && varname != NULL && varp != NULL)
13394 {
13395 /* set curbuf to be our buf, temporarily */
13396#ifdef FEAT_AUTOCMD
13397 aucmd_prepbuf(&aco, buf);
13398#else
13399 save_curbuf = curbuf;
13400 curbuf = buf;
13401#endif
13402
13403 if (*varname == '&')
13404 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013405 long numval;
13406 char_u *strval;
13407 int error = FALSE;
13408
Bram Moolenaar071d4272004-06-13 20:20:40 +000013409 ++varname;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013410 numval = get_tv_number_chk(varp, &error);
13411 strval = get_tv_string_buf_chk(varp, nbuf);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013412 if (!error && strval != NULL)
13413 set_option_value(varname, numval, strval, OPT_LOCAL);
Bram Moolenaar071d4272004-06-13 20:20:40 +000013414 }
13415 else
13416 {
13417 bufvarname = alloc((unsigned)STRLEN(varname) + 3);
13418 if (bufvarname != NULL)
13419 {
13420 STRCPY(bufvarname, "b:");
13421 STRCPY(bufvarname + 2, varname);
Bram Moolenaar1c2fda22005-01-02 11:43:19 +000013422 set_var(bufvarname, varp, TRUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +000013423 vim_free(bufvarname);
13424 }
13425 }
13426
13427 /* reset notion of buffer */
13428#ifdef FEAT_AUTOCMD
13429 aucmd_restbuf(&aco);
13430#else
13431 curbuf = save_curbuf;
13432#endif
13433 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000013434}
13435
13436/*
13437 * "setcmdpos()" function
13438 */
13439 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013440f_setcmdpos(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000013441 typval_T *argvars;
13442 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013443{
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013444 int pos = (int)get_tv_number(&argvars[0]) - 1;
13445
13446 if (pos >= 0)
13447 rettv->vval.v_number = set_cmdline_pos(pos);
Bram Moolenaar071d4272004-06-13 20:20:40 +000013448}
13449
13450/*
13451 * "setline()" function
13452 */
13453 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013454f_setline(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000013455 typval_T *argvars;
13456 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013457{
13458 linenr_T lnum;
Bram Moolenaar0e6830e2005-05-27 20:23:44 +000013459 char_u *line = NULL;
Bram Moolenaar67fe1a12005-05-22 22:12:58 +000013460 list_T *l = NULL;
13461 listitem_T *li = NULL;
13462 long added = 0;
13463 linenr_T lcount = curbuf->b_ml.ml_line_count;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013464
Bram Moolenaar67fe1a12005-05-22 22:12:58 +000013465 lnum = get_tv_lnum(&argvars[0]);
13466 if (argvars[1].v_type == VAR_LIST)
Bram Moolenaar071d4272004-06-13 20:20:40 +000013467 {
Bram Moolenaar67fe1a12005-05-22 22:12:58 +000013468 l = argvars[1].vval.v_list;
13469 li = l->lv_first;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013470 }
Bram Moolenaar67fe1a12005-05-22 22:12:58 +000013471 else
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013472 line = get_tv_string_chk(&argvars[1]);
Bram Moolenaar67fe1a12005-05-22 22:12:58 +000013473
13474 rettv->vval.v_number = 0; /* OK */
13475 for (;;)
13476 {
13477 if (l != NULL)
13478 {
13479 /* list argument, get next string */
13480 if (li == NULL)
13481 break;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013482 line = get_tv_string_chk(&li->li_tv);
Bram Moolenaar67fe1a12005-05-22 22:12:58 +000013483 li = li->li_next;
13484 }
13485
13486 rettv->vval.v_number = 1; /* FAIL */
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013487 if (line == NULL || lnum < 1 || lnum > curbuf->b_ml.ml_line_count + 1)
Bram Moolenaar67fe1a12005-05-22 22:12:58 +000013488 break;
13489 if (lnum <= curbuf->b_ml.ml_line_count)
13490 {
13491 /* existing line, replace it */
13492 if (u_savesub(lnum) == OK && ml_replace(lnum, line, TRUE) == OK)
13493 {
13494 changed_bytes(lnum, 0);
13495 check_cursor_col();
13496 rettv->vval.v_number = 0; /* OK */
13497 }
13498 }
13499 else if (added > 0 || u_save(lnum - 1, lnum) == OK)
13500 {
13501 /* lnum is one past the last line, append the line */
13502 ++added;
13503 if (ml_append(lnum - 1, line, (colnr_T)0, FALSE) == OK)
13504 rettv->vval.v_number = 0; /* OK */
13505 }
13506
13507 if (l == NULL) /* only one string argument */
13508 break;
13509 ++lnum;
13510 }
13511
13512 if (added > 0)
13513 appended_lines_mark(lcount, added);
Bram Moolenaar071d4272004-06-13 20:20:40 +000013514}
13515
13516/*
Bram Moolenaar2641f772005-03-25 21:58:17 +000013517 * "setqflist()" function
13518 */
13519/*ARGSUSED*/
13520 static void
13521f_setqflist(argvars, rettv)
13522 typval_T *argvars;
13523 typval_T *rettv;
13524{
Bram Moolenaarf4630b62005-05-20 21:31:17 +000013525 char_u *act;
13526 int action = ' ';
13527
Bram Moolenaar2641f772005-03-25 21:58:17 +000013528 rettv->vval.v_number = -1;
13529
13530#ifdef FEAT_QUICKFIX
13531 if (argvars[0].v_type != VAR_LIST)
13532 EMSG(_(e_listreq));
13533 else
13534 {
13535 list_T *l = argvars[0].vval.v_list;
13536
Bram Moolenaarf4630b62005-05-20 21:31:17 +000013537 if (argvars[1].v_type == VAR_STRING)
13538 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013539 act = get_tv_string_chk(&argvars[1]);
13540 if (act == NULL)
13541 return; /* type error; errmsg already given */
Bram Moolenaarf4630b62005-05-20 21:31:17 +000013542 if (*act == 'a' || *act == 'r')
13543 action = *act;
13544 }
13545
13546 if (l != NULL && set_errorlist(l, action) == OK)
Bram Moolenaar2641f772005-03-25 21:58:17 +000013547 rettv->vval.v_number = 0;
13548 }
13549#endif
13550}
13551
13552/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000013553 * "setreg()" function
13554 */
13555 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013556f_setreg(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000013557 typval_T *argvars;
13558 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013559{
13560 int regname;
13561 char_u *strregname;
13562 char_u *stropt;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013563 char_u *strval;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013564 int append;
13565 char_u yank_type;
13566 long block_len;
13567
13568 block_len = -1;
13569 yank_type = MAUTO;
13570 append = FALSE;
13571
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013572 strregname = get_tv_string_chk(argvars);
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013573 rettv->vval.v_number = 1; /* FAIL is default */
Bram Moolenaar071d4272004-06-13 20:20:40 +000013574
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013575 if (strregname == NULL)
13576 return; /* type error; errmsg already given */
13577 regname = *strregname;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013578 if (regname == 0 || regname == '@')
13579 regname = '"';
13580 else if (regname == '=')
13581 return;
13582
Bram Moolenaar49cd9572005-01-03 21:06:01 +000013583 if (argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +000013584 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013585 stropt = get_tv_string_chk(&argvars[2]);
13586 if (stropt == NULL)
13587 return; /* type error */
13588 for (; *stropt != NUL; ++stropt)
Bram Moolenaar071d4272004-06-13 20:20:40 +000013589 switch (*stropt)
13590 {
13591 case 'a': case 'A': /* append */
13592 append = TRUE;
13593 break;
13594 case 'v': case 'c': /* character-wise selection */
13595 yank_type = MCHAR;
13596 break;
13597 case 'V': case 'l': /* line-wise selection */
13598 yank_type = MLINE;
13599 break;
13600#ifdef FEAT_VISUAL
13601 case 'b': case Ctrl_V: /* block-wise selection */
13602 yank_type = MBLOCK;
13603 if (VIM_ISDIGIT(stropt[1]))
13604 {
13605 ++stropt;
13606 block_len = getdigits(&stropt) - 1;
13607 --stropt;
13608 }
13609 break;
13610#endif
13611 }
13612 }
13613
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013614 strval = get_tv_string_chk(&argvars[1]);
13615 if (strval != NULL)
13616 write_reg_contents_ex(regname, strval, -1,
Bram Moolenaar071d4272004-06-13 20:20:40 +000013617 append, yank_type, block_len);
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013618 rettv->vval.v_number = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013619}
13620
13621
13622/*
13623 * "setwinvar(expr)" function
13624 */
13625/*ARGSUSED*/
13626 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013627f_setwinvar(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000013628 typval_T *argvars;
13629 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013630{
13631 win_T *win;
13632#ifdef FEAT_WINDOWS
13633 win_T *save_curwin;
13634#endif
13635 char_u *varname, *winvarname;
Bram Moolenaar33570922005-01-25 22:26:29 +000013636 typval_T *varp;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013637 char_u nbuf[NUMBUFLEN];
13638
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013639 rettv->vval.v_number = 0;
13640
Bram Moolenaar071d4272004-06-13 20:20:40 +000013641 if (check_restricted() || check_secure())
13642 return;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013643 win = find_win_by_nr(&argvars[0]);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013644 varname = get_tv_string_chk(&argvars[1]);
Bram Moolenaar071d4272004-06-13 20:20:40 +000013645 varp = &argvars[2];
13646
13647 if (win != NULL && varname != NULL && varp != NULL)
13648 {
13649#ifdef FEAT_WINDOWS
13650 /* set curwin to be our win, temporarily */
13651 save_curwin = curwin;
13652 curwin = win;
13653 curbuf = curwin->w_buffer;
13654#endif
13655
13656 if (*varname == '&')
13657 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013658 long numval;
13659 char_u *strval;
13660 int error = FALSE;
13661
Bram Moolenaar071d4272004-06-13 20:20:40 +000013662 ++varname;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013663 numval = get_tv_number_chk(varp, &error);
13664 strval = get_tv_string_buf_chk(varp, nbuf);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013665 if (!error && strval != NULL)
13666 set_option_value(varname, numval, strval, OPT_LOCAL);
Bram Moolenaar071d4272004-06-13 20:20:40 +000013667 }
13668 else
13669 {
13670 winvarname = alloc((unsigned)STRLEN(varname) + 3);
13671 if (winvarname != NULL)
13672 {
13673 STRCPY(winvarname, "w:");
13674 STRCPY(winvarname + 2, varname);
Bram Moolenaar1c2fda22005-01-02 11:43:19 +000013675 set_var(winvarname, varp, TRUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +000013676 vim_free(winvarname);
13677 }
13678 }
13679
13680#ifdef FEAT_WINDOWS
13681 /* Restore current window, if it's still valid (autocomands can make
13682 * it invalid). */
13683 if (win_valid(save_curwin))
13684 {
13685 curwin = save_curwin;
13686 curbuf = curwin->w_buffer;
13687 }
13688#endif
13689 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000013690}
13691
13692/*
Bram Moolenaar0d660222005-01-07 21:51:51 +000013693 * "simplify()" function
Bram Moolenaar071d4272004-06-13 20:20:40 +000013694 */
13695 static void
Bram Moolenaar0d660222005-01-07 21:51:51 +000013696f_simplify(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000013697 typval_T *argvars;
13698 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013699{
Bram Moolenaar0d660222005-01-07 21:51:51 +000013700 char_u *p;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013701
Bram Moolenaar0d660222005-01-07 21:51:51 +000013702 p = get_tv_string(&argvars[0]);
13703 rettv->vval.v_string = vim_strsave(p);
13704 simplify_filename(rettv->vval.v_string); /* simplify in place */
13705 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013706}
13707
Bram Moolenaar0d660222005-01-07 21:51:51 +000013708static int
13709#ifdef __BORLANDC__
13710 _RTLENTRYF
13711#endif
13712 item_compare __ARGS((const void *s1, const void *s2));
13713static int
13714#ifdef __BORLANDC__
13715 _RTLENTRYF
13716#endif
13717 item_compare2 __ARGS((const void *s1, const void *s2));
13718
13719static int item_compare_ic;
13720static char_u *item_compare_func;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013721static int item_compare_func_err;
Bram Moolenaar0d660222005-01-07 21:51:51 +000013722#define ITEM_COMPARE_FAIL 999
13723
Bram Moolenaar071d4272004-06-13 20:20:40 +000013724/*
Bram Moolenaar0d660222005-01-07 21:51:51 +000013725 * Compare functions for f_sort() below.
Bram Moolenaar071d4272004-06-13 20:20:40 +000013726 */
Bram Moolenaar0d660222005-01-07 21:51:51 +000013727 static int
13728#ifdef __BORLANDC__
13729_RTLENTRYF
13730#endif
13731item_compare(s1, s2)
13732 const void *s1;
13733 const void *s2;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013734{
Bram Moolenaar0d660222005-01-07 21:51:51 +000013735 char_u *p1, *p2;
13736 char_u *tofree1, *tofree2;
13737 int res;
13738 char_u numbuf1[NUMBUFLEN];
13739 char_u numbuf2[NUMBUFLEN];
Bram Moolenaar071d4272004-06-13 20:20:40 +000013740
Bram Moolenaar33570922005-01-25 22:26:29 +000013741 p1 = tv2string(&(*(listitem_T **)s1)->li_tv, &tofree1, numbuf1);
13742 p2 = tv2string(&(*(listitem_T **)s2)->li_tv, &tofree2, numbuf2);
Bram Moolenaar0d660222005-01-07 21:51:51 +000013743 if (item_compare_ic)
13744 res = STRICMP(p1, p2);
Bram Moolenaar071d4272004-06-13 20:20:40 +000013745 else
Bram Moolenaar0d660222005-01-07 21:51:51 +000013746 res = STRCMP(p1, p2);
13747 vim_free(tofree1);
13748 vim_free(tofree2);
13749 return res;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013750}
13751
13752 static int
Bram Moolenaar0d660222005-01-07 21:51:51 +000013753#ifdef __BORLANDC__
13754_RTLENTRYF
Bram Moolenaar071d4272004-06-13 20:20:40 +000013755#endif
Bram Moolenaar0d660222005-01-07 21:51:51 +000013756item_compare2(s1, s2)
13757 const void *s1;
13758 const void *s2;
13759{
13760 int res;
Bram Moolenaar33570922005-01-25 22:26:29 +000013761 typval_T rettv;
13762 typval_T argv[2];
Bram Moolenaar0d660222005-01-07 21:51:51 +000013763 int dummy;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013764
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013765 /* shortcut after failure in previous call; compare all items equal */
13766 if (item_compare_func_err)
13767 return 0;
13768
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000013769 /* copy the values. This is needed to be able to set v_lock to VAR_FIXED
13770 * in the copy without changing the original list items. */
Bram Moolenaar33570922005-01-25 22:26:29 +000013771 copy_tv(&(*(listitem_T **)s1)->li_tv, &argv[0]);
13772 copy_tv(&(*(listitem_T **)s2)->li_tv, &argv[1]);
Bram Moolenaar0d660222005-01-07 21:51:51 +000013773
13774 rettv.v_type = VAR_UNKNOWN; /* clear_tv() uses this */
13775 res = call_func(item_compare_func, STRLEN(item_compare_func),
Bram Moolenaare9a41262005-01-15 22:18:47 +000013776 &rettv, 2, argv, 0L, 0L, &dummy, TRUE, NULL);
Bram Moolenaar0d660222005-01-07 21:51:51 +000013777 clear_tv(&argv[0]);
13778 clear_tv(&argv[1]);
13779
13780 if (res == FAIL)
13781 res = ITEM_COMPARE_FAIL;
13782 else
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013783 /* return value has wrong type */
13784 res = get_tv_number_chk(&rettv, &item_compare_func_err);
13785 if (item_compare_func_err)
13786 res = ITEM_COMPARE_FAIL;
Bram Moolenaar0d660222005-01-07 21:51:51 +000013787 clear_tv(&rettv);
13788 return res;
13789}
13790
13791/*
13792 * "sort({list})" function
13793 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000013794 static void
Bram Moolenaar0d660222005-01-07 21:51:51 +000013795f_sort(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000013796 typval_T *argvars;
13797 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013798{
Bram Moolenaar33570922005-01-25 22:26:29 +000013799 list_T *l;
13800 listitem_T *li;
13801 listitem_T **ptrs;
Bram Moolenaar0d660222005-01-07 21:51:51 +000013802 long len;
13803 long i;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013804
Bram Moolenaar0d660222005-01-07 21:51:51 +000013805 rettv->vval.v_number = 0;
13806 if (argvars[0].v_type != VAR_LIST)
13807 EMSG2(_(e_listarg), "sort()");
Bram Moolenaar071d4272004-06-13 20:20:40 +000013808 else
13809 {
Bram Moolenaar0d660222005-01-07 21:51:51 +000013810 l = argvars[0].vval.v_list;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000013811 if (l == NULL || tv_check_lock(l->lv_lock, (char_u *)"sort()"))
Bram Moolenaar0d660222005-01-07 21:51:51 +000013812 return;
13813 rettv->vval.v_list = l;
13814 rettv->v_type = VAR_LIST;
13815 ++l->lv_refcount;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013816
Bram Moolenaar0d660222005-01-07 21:51:51 +000013817 len = list_len(l);
13818 if (len <= 1)
13819 return; /* short list sorts pretty quickly */
Bram Moolenaar071d4272004-06-13 20:20:40 +000013820
Bram Moolenaar0d660222005-01-07 21:51:51 +000013821 item_compare_ic = FALSE;
13822 item_compare_func = NULL;
13823 if (argvars[1].v_type != VAR_UNKNOWN)
13824 {
13825 if (argvars[1].v_type == VAR_FUNC)
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013826 item_compare_func = argvars[1].vval.v_string;
Bram Moolenaar0d660222005-01-07 21:51:51 +000013827 else
13828 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013829 int error = FALSE;
13830
13831 i = get_tv_number_chk(&argvars[1], &error);
13832 if (error)
13833 return; /* type error; errmsg already given */
Bram Moolenaar0d660222005-01-07 21:51:51 +000013834 if (i == 1)
13835 item_compare_ic = TRUE;
13836 else
13837 item_compare_func = get_tv_string(&argvars[1]);
13838 }
13839 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000013840
Bram Moolenaar0d660222005-01-07 21:51:51 +000013841 /* Make an array with each entry pointing to an item in the List. */
Bram Moolenaar33570922005-01-25 22:26:29 +000013842 ptrs = (listitem_T **)alloc((int)(len * sizeof(listitem_T *)));
Bram Moolenaar0d660222005-01-07 21:51:51 +000013843 if (ptrs == NULL)
13844 return;
13845 i = 0;
13846 for (li = l->lv_first; li != NULL; li = li->li_next)
13847 ptrs[i++] = li;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013848
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013849 item_compare_func_err = FALSE;
Bram Moolenaar0d660222005-01-07 21:51:51 +000013850 /* test the compare function */
13851 if (item_compare_func != NULL
13852 && item_compare2((void *)&ptrs[0], (void *)&ptrs[1])
13853 == ITEM_COMPARE_FAIL)
Bram Moolenaare49b69a2005-01-08 16:11:57 +000013854 EMSG(_("E702: Sort compare function failed"));
Bram Moolenaar071d4272004-06-13 20:20:40 +000013855 else
Bram Moolenaar0d660222005-01-07 21:51:51 +000013856 {
13857 /* Sort the array with item pointers. */
Bram Moolenaar33570922005-01-25 22:26:29 +000013858 qsort((void *)ptrs, (size_t)len, sizeof(listitem_T *),
Bram Moolenaar0d660222005-01-07 21:51:51 +000013859 item_compare_func == NULL ? item_compare : item_compare2);
13860
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000013861 if (!item_compare_func_err)
13862 {
13863 /* Clear the List and append the items in the sorted order. */
13864 l->lv_first = l->lv_last = NULL;
13865 l->lv_len = 0;
13866 for (i = 0; i < len; ++i)
13867 list_append(l, ptrs[i]);
13868 }
Bram Moolenaar0d660222005-01-07 21:51:51 +000013869 }
13870
13871 vim_free(ptrs);
13872 }
13873}
13874
Bram Moolenaard857f0e2005-06-21 22:37:39 +000013875/*
Bram Moolenaar24bbcfe2005-06-28 23:32:02 +000013876 * "soundfold({word})" function
13877 */
13878 static void
13879f_soundfold(argvars, rettv)
13880 typval_T *argvars;
13881 typval_T *rettv;
13882{
13883 char_u *s;
13884
13885 rettv->v_type = VAR_STRING;
13886 s = get_tv_string(&argvars[0]);
13887#ifdef FEAT_SYN_HL
13888 rettv->vval.v_string = eval_soundfold(s);
13889#else
13890 rettv->vval.v_string = vim_strsave(s);
13891#endif
13892}
13893
13894/*
Bram Moolenaard857f0e2005-06-21 22:37:39 +000013895 * "spellbadword()" function
13896 */
13897/* ARGSUSED */
13898 static void
13899f_spellbadword(argvars, rettv)
13900 typval_T *argvars;
13901 typval_T *rettv;
13902{
Bram Moolenaar4463f292005-09-25 22:20:24 +000013903 char_u *word = (char_u *)"";
13904#ifdef FEAT_SYN_HL
Bram Moolenaar482aaeb2005-09-29 18:26:07 +000013905 int len = 0;
13906 hlf_T attr = HLF_COUNT;
Bram Moolenaar4463f292005-09-25 22:20:24 +000013907 list_T *l;
13908#endif
Bram Moolenaard857f0e2005-06-21 22:37:39 +000013909
Bram Moolenaar4463f292005-09-25 22:20:24 +000013910 l = list_alloc();
13911 if (l == NULL)
13912 return;
13913 rettv->v_type = VAR_LIST;
13914 rettv->vval.v_list = l;
13915 ++l->lv_refcount;
Bram Moolenaard857f0e2005-06-21 22:37:39 +000013916
13917#ifdef FEAT_SYN_HL
Bram Moolenaar4463f292005-09-25 22:20:24 +000013918 if (argvars[0].v_type == VAR_UNKNOWN)
13919 {
13920 /* Find the start and length of the badly spelled word. */
13921 len = spell_move_to(curwin, FORWARD, TRUE, TRUE, &attr);
13922 if (len != 0)
13923 word = ml_get_cursor();
13924 }
13925 else if (curwin->w_p_spell && *curbuf->b_p_spl != NUL)
13926 {
13927 char_u *str = get_tv_string_chk(&argvars[0]);
13928 int capcol = -1;
13929
13930 if (str != NULL)
13931 {
13932 /* Check the argument for spelling. */
13933 while (*str != NUL)
13934 {
13935 len = spell_check(curwin, str, &attr, &capcol);
Bram Moolenaar482aaeb2005-09-29 18:26:07 +000013936 if (attr != HLF_COUNT)
Bram Moolenaar4463f292005-09-25 22:20:24 +000013937 {
13938 word = str;
13939 break;
13940 }
13941 str += len;
13942 }
13943 }
13944 }
Bram Moolenaard857f0e2005-06-21 22:37:39 +000013945#endif
Bram Moolenaar4463f292005-09-25 22:20:24 +000013946
13947 list_append_string(l, word, len);
13948 list_append_string(l, (char_u *)(
Bram Moolenaar482aaeb2005-09-29 18:26:07 +000013949 attr == HLF_SPB ? "bad" :
13950 attr == HLF_SPR ? "rare" :
13951 attr == HLF_SPL ? "local" :
13952 attr == HLF_SPC ? "caps" :
13953 ""), -1);
Bram Moolenaard857f0e2005-06-21 22:37:39 +000013954}
13955
13956/*
13957 * "spellsuggest()" function
13958 */
13959 static void
13960f_spellsuggest(argvars, rettv)
13961 typval_T *argvars;
13962 typval_T *rettv;
13963{
Bram Moolenaar69e0ff92005-09-30 21:23:56 +000013964 list_T *l;
13965#ifdef FEAT_SYN_HL
Bram Moolenaard857f0e2005-06-21 22:37:39 +000013966 char_u *str;
Bram Moolenaar69e0ff92005-09-30 21:23:56 +000013967 int typeerr = FALSE;
Bram Moolenaard857f0e2005-06-21 22:37:39 +000013968 int maxcount;
13969 garray_T ga;
Bram Moolenaard857f0e2005-06-21 22:37:39 +000013970 int i;
Bram Moolenaar69e0ff92005-09-30 21:23:56 +000013971 listitem_T *li;
13972 int need_capital = FALSE;
13973#endif
Bram Moolenaard857f0e2005-06-21 22:37:39 +000013974
13975 l = list_alloc();
13976 if (l == NULL)
13977 return;
13978 rettv->v_type = VAR_LIST;
13979 rettv->vval.v_list = l;
13980 ++l->lv_refcount;
13981
13982#ifdef FEAT_SYN_HL
13983 if (curwin->w_p_spell && *curbuf->b_p_spl != NUL)
13984 {
13985 str = get_tv_string(&argvars[0]);
13986 if (argvars[1].v_type != VAR_UNKNOWN)
13987 {
Bram Moolenaar69e0ff92005-09-30 21:23:56 +000013988 maxcount = get_tv_number_chk(&argvars[1], &typeerr);
Bram Moolenaard857f0e2005-06-21 22:37:39 +000013989 if (maxcount <= 0)
13990 return;
Bram Moolenaar69e0ff92005-09-30 21:23:56 +000013991 if (argvars[2].v_type != VAR_UNKNOWN)
13992 {
13993 need_capital = get_tv_number_chk(&argvars[2], &typeerr);
13994 if (typeerr)
13995 return;
13996 }
Bram Moolenaard857f0e2005-06-21 22:37:39 +000013997 }
13998 else
13999 maxcount = 25;
14000
Bram Moolenaar69e0ff92005-09-30 21:23:56 +000014001 spell_suggest_list(&ga, str, maxcount, need_capital);
Bram Moolenaard857f0e2005-06-21 22:37:39 +000014002
14003 for (i = 0; i < ga.ga_len; ++i)
14004 {
14005 str = ((char_u **)ga.ga_data)[i];
14006
14007 li = listitem_alloc();
14008 if (li == NULL)
14009 vim_free(str);
14010 else
14011 {
14012 li->li_tv.v_type = VAR_STRING;
14013 li->li_tv.v_lock = 0;
14014 li->li_tv.vval.v_string = str;
14015 list_append(l, li);
14016 }
14017 }
14018 ga_clear(&ga);
14019 }
14020#endif
14021}
14022
Bram Moolenaar0d660222005-01-07 21:51:51 +000014023 static void
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000014024f_split(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000014025 typval_T *argvars;
14026 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000014027{
14028 char_u *str;
14029 char_u *end;
Bram Moolenaar67fe1a12005-05-22 22:12:58 +000014030 char_u *pat = NULL;
Bram Moolenaar0d660222005-01-07 21:51:51 +000014031 regmatch_T regmatch;
14032 char_u patbuf[NUMBUFLEN];
14033 char_u *save_cpo;
14034 int match;
Bram Moolenaar33570922005-01-25 22:26:29 +000014035 list_T *l;
Bram Moolenaar0d660222005-01-07 21:51:51 +000014036 colnr_T col = 0;
Bram Moolenaar67fe1a12005-05-22 22:12:58 +000014037 int keepempty = FALSE;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000014038 int typeerr = FALSE;
Bram Moolenaar0d660222005-01-07 21:51:51 +000014039
14040 /* Make 'cpoptions' empty, the 'l' flag should not be used here. */
14041 save_cpo = p_cpo;
14042 p_cpo = (char_u *)"";
14043
14044 str = get_tv_string(&argvars[0]);
Bram Moolenaar67fe1a12005-05-22 22:12:58 +000014045 if (argvars[1].v_type != VAR_UNKNOWN)
14046 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000014047 pat = get_tv_string_buf_chk(&argvars[1], patbuf);
14048 if (pat == NULL)
14049 typeerr = TRUE;
Bram Moolenaar67fe1a12005-05-22 22:12:58 +000014050 if (argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000014051 keepempty = get_tv_number_chk(&argvars[2], &typeerr);
Bram Moolenaar67fe1a12005-05-22 22:12:58 +000014052 }
14053 if (pat == NULL || *pat == NUL)
14054 pat = (char_u *)"[\\x01- ]\\+";
Bram Moolenaar0d660222005-01-07 21:51:51 +000014055
14056 l = list_alloc();
14057 if (l == NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000014058 return;
Bram Moolenaar0d660222005-01-07 21:51:51 +000014059 rettv->v_type = VAR_LIST;
14060 rettv->vval.v_list = l;
14061 ++l->lv_refcount;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000014062 if (typeerr)
14063 return;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014064
Bram Moolenaar0d660222005-01-07 21:51:51 +000014065 regmatch.regprog = vim_regcomp(pat, RE_MAGIC + RE_STRING);
14066 if (regmatch.regprog != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000014067 {
Bram Moolenaar0d660222005-01-07 21:51:51 +000014068 regmatch.rm_ic = FALSE;
Bram Moolenaar67fe1a12005-05-22 22:12:58 +000014069 while (*str != NUL || keepempty)
Bram Moolenaar0d660222005-01-07 21:51:51 +000014070 {
Bram Moolenaar67fe1a12005-05-22 22:12:58 +000014071 if (*str == NUL)
14072 match = FALSE; /* empty item at the end */
14073 else
14074 match = vim_regexec_nl(&regmatch, str, col);
Bram Moolenaar0d660222005-01-07 21:51:51 +000014075 if (match)
14076 end = regmatch.startp[0];
14077 else
14078 end = str + STRLEN(str);
Bram Moolenaar54ee7752005-05-31 22:22:17 +000014079 if (keepempty || end > str || (l->lv_len > 0 && *str != NUL
14080 && match && end < regmatch.endp[0]))
Bram Moolenaar0d660222005-01-07 21:51:51 +000014081 {
Bram Moolenaar4463f292005-09-25 22:20:24 +000014082 if (list_append_string(l, str, (int)(end - str)) == FAIL)
Bram Moolenaar0d660222005-01-07 21:51:51 +000014083 break;
Bram Moolenaar0d660222005-01-07 21:51:51 +000014084 }
14085 if (!match)
14086 break;
14087 /* Advance to just after the match. */
14088 if (regmatch.endp[0] > str)
14089 col = 0;
14090 else
14091 {
14092 /* Don't get stuck at the same match. */
14093#ifdef FEAT_MBYTE
Bram Moolenaar0fa313a2005-08-10 21:07:57 +000014094 col = (*mb_ptr2len)(regmatch.endp[0]);
Bram Moolenaar0d660222005-01-07 21:51:51 +000014095#else
14096 col = 1;
14097#endif
14098 }
14099 str = regmatch.endp[0];
14100 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000014101
Bram Moolenaar0d660222005-01-07 21:51:51 +000014102 vim_free(regmatch.regprog);
Bram Moolenaar071d4272004-06-13 20:20:40 +000014103 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000014104
Bram Moolenaar0d660222005-01-07 21:51:51 +000014105 p_cpo = save_cpo;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014106}
14107
14108#ifdef HAVE_STRFTIME
14109/*
14110 * "strftime({format}[, {time}])" function
14111 */
14112 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014113f_strftime(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000014114 typval_T *argvars;
14115 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014116{
14117 char_u result_buf[256];
14118 struct tm *curtime;
14119 time_t seconds;
14120 char_u *p;
14121
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014122 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014123
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014124 p = get_tv_string(&argvars[0]);
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014125 if (argvars[1].v_type == VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +000014126 seconds = time(NULL);
14127 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014128 seconds = (time_t)get_tv_number(&argvars[1]);
Bram Moolenaar071d4272004-06-13 20:20:40 +000014129 curtime = localtime(&seconds);
14130 /* MSVC returns NULL for an invalid value of seconds. */
14131 if (curtime == NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014132 rettv->vval.v_string = vim_strsave((char_u *)_("(Invalid)"));
Bram Moolenaar071d4272004-06-13 20:20:40 +000014133 else
14134 {
14135# ifdef FEAT_MBYTE
14136 vimconv_T conv;
14137 char_u *enc;
14138
14139 conv.vc_type = CONV_NONE;
14140 enc = enc_locale();
14141 convert_setup(&conv, p_enc, enc);
14142 if (conv.vc_type != CONV_NONE)
14143 p = string_convert(&conv, p, NULL);
14144# endif
14145 if (p != NULL)
14146 (void)strftime((char *)result_buf, sizeof(result_buf),
14147 (char *)p, curtime);
14148 else
14149 result_buf[0] = NUL;
14150
14151# ifdef FEAT_MBYTE
14152 if (conv.vc_type != CONV_NONE)
14153 vim_free(p);
14154 convert_setup(&conv, enc, p_enc);
14155 if (conv.vc_type != CONV_NONE)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014156 rettv->vval.v_string = string_convert(&conv, result_buf, NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +000014157 else
14158# endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014159 rettv->vval.v_string = vim_strsave(result_buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +000014160
14161# ifdef FEAT_MBYTE
14162 /* Release conversion descriptors */
14163 convert_setup(&conv, NULL, NULL);
14164 vim_free(enc);
14165# endif
14166 }
14167}
14168#endif
14169
14170/*
14171 * "stridx()" function
14172 */
14173 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014174f_stridx(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000014175 typval_T *argvars;
14176 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014177{
14178 char_u buf[NUMBUFLEN];
14179 char_u *needle;
14180 char_u *haystack;
Bram Moolenaar33570922005-01-25 22:26:29 +000014181 char_u *save_haystack;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014182 char_u *pos;
Bram Moolenaar33570922005-01-25 22:26:29 +000014183 int start_idx;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014184
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000014185 needle = get_tv_string_chk(&argvars[1]);
14186 save_haystack = haystack = get_tv_string_buf_chk(&argvars[0], buf);
Bram Moolenaar33570922005-01-25 22:26:29 +000014187 rettv->vval.v_number = -1;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000014188 if (needle == NULL || haystack == NULL)
14189 return; /* type error; errmsg already given */
Bram Moolenaar071d4272004-06-13 20:20:40 +000014190
Bram Moolenaar33570922005-01-25 22:26:29 +000014191 if (argvars[2].v_type != VAR_UNKNOWN)
14192 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000014193 int error = FALSE;
14194
14195 start_idx = get_tv_number_chk(&argvars[2], &error);
14196 if (error || start_idx >= (int)STRLEN(haystack))
Bram Moolenaar33570922005-01-25 22:26:29 +000014197 return;
Bram Moolenaar532c7802005-01-27 14:44:31 +000014198 if (start_idx >= 0)
14199 haystack += start_idx;
Bram Moolenaar33570922005-01-25 22:26:29 +000014200 }
14201
14202 pos = (char_u *)strstr((char *)haystack, (char *)needle);
14203 if (pos != NULL)
14204 rettv->vval.v_number = (varnumber_T)(pos - save_haystack);
Bram Moolenaar071d4272004-06-13 20:20:40 +000014205}
14206
14207/*
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014208 * "string()" function
14209 */
14210 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014211f_string(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000014212 typval_T *argvars;
14213 typval_T *rettv;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014214{
14215 char_u *tofree;
Bram Moolenaar8a283e52005-01-06 23:28:25 +000014216 char_u numbuf[NUMBUFLEN];
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014217
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014218 rettv->v_type = VAR_STRING;
Bram Moolenaar8a283e52005-01-06 23:28:25 +000014219 rettv->vval.v_string = tv2string(&argvars[0], &tofree, numbuf);
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014220 if (tofree == NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014221 rettv->vval.v_string = vim_strsave(rettv->vval.v_string);
Bram Moolenaar071d4272004-06-13 20:20:40 +000014222}
14223
14224/*
14225 * "strlen()" function
14226 */
14227 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014228f_strlen(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000014229 typval_T *argvars;
14230 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014231{
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014232 rettv->vval.v_number = (varnumber_T)(STRLEN(
14233 get_tv_string(&argvars[0])));
Bram Moolenaar071d4272004-06-13 20:20:40 +000014234}
14235
14236/*
14237 * "strpart()" function
14238 */
14239 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014240f_strpart(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000014241 typval_T *argvars;
14242 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014243{
14244 char_u *p;
14245 int n;
14246 int len;
14247 int slen;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000014248 int error = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014249
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014250 p = get_tv_string(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +000014251 slen = (int)STRLEN(p);
14252
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000014253 n = get_tv_number_chk(&argvars[1], &error);
14254 if (error)
14255 len = 0;
14256 else if (argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014257 len = get_tv_number(&argvars[2]);
Bram Moolenaar071d4272004-06-13 20:20:40 +000014258 else
14259 len = slen - n; /* default len: all bytes that are available. */
14260
14261 /*
14262 * Only return the overlap between the specified part and the actual
14263 * string.
14264 */
14265 if (n < 0)
14266 {
14267 len += n;
14268 n = 0;
14269 }
14270 else if (n > slen)
14271 n = slen;
14272 if (len < 0)
14273 len = 0;
14274 else if (n + len > slen)
14275 len = slen - n;
14276
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014277 rettv->v_type = VAR_STRING;
14278 rettv->vval.v_string = vim_strnsave(p + n, len);
Bram Moolenaar071d4272004-06-13 20:20:40 +000014279}
14280
14281/*
Bram Moolenaar0d660222005-01-07 21:51:51 +000014282 * "strridx()" function
14283 */
14284 static void
14285f_strridx(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000014286 typval_T *argvars;
14287 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000014288{
14289 char_u buf[NUMBUFLEN];
14290 char_u *needle;
14291 char_u *haystack;
14292 char_u *rest;
14293 char_u *lastmatch = NULL;
Bram Moolenaar532c7802005-01-27 14:44:31 +000014294 int haystack_len, end_idx;
Bram Moolenaar0d660222005-01-07 21:51:51 +000014295
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000014296 needle = get_tv_string_chk(&argvars[1]);
14297 haystack = get_tv_string_buf_chk(&argvars[0], buf);
Bram Moolenaar532c7802005-01-27 14:44:31 +000014298 haystack_len = STRLEN(haystack);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000014299
14300 rettv->vval.v_number = -1;
14301 if (needle == NULL || haystack == NULL)
14302 return; /* type error; errmsg already given */
Bram Moolenaar05159a02005-02-26 23:04:13 +000014303 if (argvars[2].v_type != VAR_UNKNOWN)
14304 {
14305 /* Third argument: upper limit for index */
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000014306 end_idx = get_tv_number_chk(&argvars[2], NULL);
Bram Moolenaar05159a02005-02-26 23:04:13 +000014307 if (end_idx < 0)
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000014308 return; /* can never find a match */
Bram Moolenaar05159a02005-02-26 23:04:13 +000014309 }
14310 else
14311 end_idx = haystack_len;
14312
Bram Moolenaar0d660222005-01-07 21:51:51 +000014313 if (*needle == NUL)
Bram Moolenaar05159a02005-02-26 23:04:13 +000014314 {
Bram Moolenaar0d660222005-01-07 21:51:51 +000014315 /* Empty string matches past the end. */
Bram Moolenaar05159a02005-02-26 23:04:13 +000014316 lastmatch = haystack + end_idx;
14317 }
Bram Moolenaar0d660222005-01-07 21:51:51 +000014318 else
Bram Moolenaar532c7802005-01-27 14:44:31 +000014319 {
Bram Moolenaar0d660222005-01-07 21:51:51 +000014320 for (rest = haystack; *rest != '\0'; ++rest)
14321 {
14322 rest = (char_u *)strstr((char *)rest, (char *)needle);
Bram Moolenaar532c7802005-01-27 14:44:31 +000014323 if (rest == NULL || rest > haystack + end_idx)
Bram Moolenaar0d660222005-01-07 21:51:51 +000014324 break;
14325 lastmatch = rest;
14326 }
Bram Moolenaar532c7802005-01-27 14:44:31 +000014327 }
Bram Moolenaar0d660222005-01-07 21:51:51 +000014328
14329 if (lastmatch == NULL)
14330 rettv->vval.v_number = -1;
14331 else
14332 rettv->vval.v_number = (varnumber_T)(lastmatch - haystack);
14333}
14334
14335/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000014336 * "strtrans()" function
14337 */
14338 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014339f_strtrans(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000014340 typval_T *argvars;
14341 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014342{
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014343 rettv->v_type = VAR_STRING;
14344 rettv->vval.v_string = transstr(get_tv_string(&argvars[0]));
Bram Moolenaar071d4272004-06-13 20:20:40 +000014345}
14346
14347/*
Bram Moolenaar0d660222005-01-07 21:51:51 +000014348 * "submatch()" function
14349 */
14350 static void
14351f_submatch(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000014352 typval_T *argvars;
14353 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000014354{
14355 rettv->v_type = VAR_STRING;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000014356 rettv->vval.v_string =
14357 reg_submatch((int)get_tv_number_chk(&argvars[0], NULL));
Bram Moolenaar0d660222005-01-07 21:51:51 +000014358}
14359
14360/*
14361 * "substitute()" function
14362 */
14363 static void
14364f_substitute(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000014365 typval_T *argvars;
14366 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000014367{
14368 char_u patbuf[NUMBUFLEN];
14369 char_u subbuf[NUMBUFLEN];
14370 char_u flagsbuf[NUMBUFLEN];
14371
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000014372 char_u *str = get_tv_string_chk(&argvars[0]);
14373 char_u *pat = get_tv_string_buf_chk(&argvars[1], patbuf);
14374 char_u *sub = get_tv_string_buf_chk(&argvars[2], subbuf);
14375 char_u *flg = get_tv_string_buf_chk(&argvars[3], flagsbuf);
14376
Bram Moolenaar0d660222005-01-07 21:51:51 +000014377 rettv->v_type = VAR_STRING;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000014378 if (str == NULL || pat == NULL || sub == NULL || flg == NULL)
14379 rettv->vval.v_string = NULL;
14380 else
14381 rettv->vval.v_string = do_string_sub(str, pat, sub, flg);
Bram Moolenaar0d660222005-01-07 21:51:51 +000014382}
14383
14384/*
Bram Moolenaar54ff3412005-04-20 19:48:33 +000014385 * "synID(lnum, col, trans)" function
Bram Moolenaar071d4272004-06-13 20:20:40 +000014386 */
14387/*ARGSUSED*/
14388 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014389f_synID(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000014390 typval_T *argvars;
14391 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014392{
14393 int id = 0;
14394#ifdef FEAT_SYN_HL
Bram Moolenaar54ff3412005-04-20 19:48:33 +000014395 long lnum;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014396 long col;
14397 int trans;
Bram Moolenaar92124a32005-06-17 22:03:40 +000014398 int transerr = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014399
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000014400 lnum = get_tv_lnum(argvars); /* -1 on type error */
14401 col = get_tv_number(&argvars[1]) - 1; /* -1 on type error */
14402 trans = get_tv_number_chk(&argvars[2], &transerr);
Bram Moolenaar071d4272004-06-13 20:20:40 +000014403
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000014404 if (!transerr && lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count
Bram Moolenaar54ff3412005-04-20 19:48:33 +000014405 && col >= 0 && col < (long)STRLEN(ml_get(lnum)))
Bram Moolenaar81f1ecb2005-08-25 21:27:31 +000014406 id = syn_get_id(curwin, lnum, (colnr_T)col, trans, NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +000014407#endif
14408
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014409 rettv->vval.v_number = id;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014410}
14411
14412/*
14413 * "synIDattr(id, what [, mode])" function
14414 */
14415/*ARGSUSED*/
14416 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014417f_synIDattr(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000014418 typval_T *argvars;
14419 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014420{
14421 char_u *p = NULL;
14422#ifdef FEAT_SYN_HL
14423 int id;
14424 char_u *what;
14425 char_u *mode;
14426 char_u modebuf[NUMBUFLEN];
14427 int modec;
14428
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014429 id = get_tv_number(&argvars[0]);
14430 what = get_tv_string(&argvars[1]);
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014431 if (argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +000014432 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014433 mode = get_tv_string_buf(&argvars[2], modebuf);
Bram Moolenaar071d4272004-06-13 20:20:40 +000014434 modec = TOLOWER_ASC(mode[0]);
14435 if (modec != 't' && modec != 'c'
14436#ifdef FEAT_GUI
14437 && modec != 'g'
14438#endif
14439 )
14440 modec = 0; /* replace invalid with current */
14441 }
14442 else
14443 {
14444#ifdef FEAT_GUI
14445 if (gui.in_use)
14446 modec = 'g';
14447 else
14448#endif
14449 if (t_colors > 1)
14450 modec = 'c';
14451 else
14452 modec = 't';
14453 }
14454
14455
14456 switch (TOLOWER_ASC(what[0]))
14457 {
14458 case 'b':
14459 if (TOLOWER_ASC(what[1]) == 'g') /* bg[#] */
14460 p = highlight_color(id, what, modec);
14461 else /* bold */
14462 p = highlight_has_attr(id, HL_BOLD, modec);
14463 break;
14464
14465 case 'f': /* fg[#] */
14466 p = highlight_color(id, what, modec);
14467 break;
14468
14469 case 'i':
14470 if (TOLOWER_ASC(what[1]) == 'n') /* inverse */
14471 p = highlight_has_attr(id, HL_INVERSE, modec);
14472 else /* italic */
14473 p = highlight_has_attr(id, HL_ITALIC, modec);
14474 break;
14475
14476 case 'n': /* name */
14477 p = get_highlight_name(NULL, id - 1);
14478 break;
14479
14480 case 'r': /* reverse */
14481 p = highlight_has_attr(id, HL_INVERSE, modec);
14482 break;
14483
14484 case 's': /* standout */
14485 p = highlight_has_attr(id, HL_STANDOUT, modec);
14486 break;
14487
Bram Moolenaar5b743bf2005-03-15 22:50:43 +000014488 case 'u':
14489 if (STRLEN(what) <= 5 || TOLOWER_ASC(what[5]) != 'c')
14490 /* underline */
14491 p = highlight_has_attr(id, HL_UNDERLINE, modec);
14492 else
14493 /* undercurl */
14494 p = highlight_has_attr(id, HL_UNDERCURL, modec);
Bram Moolenaar071d4272004-06-13 20:20:40 +000014495 break;
14496 }
14497
14498 if (p != NULL)
14499 p = vim_strsave(p);
14500#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014501 rettv->v_type = VAR_STRING;
14502 rettv->vval.v_string = p;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014503}
14504
14505/*
14506 * "synIDtrans(id)" function
14507 */
14508/*ARGSUSED*/
14509 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014510f_synIDtrans(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000014511 typval_T *argvars;
14512 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014513{
14514 int id;
14515
14516#ifdef FEAT_SYN_HL
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014517 id = get_tv_number(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +000014518
14519 if (id > 0)
14520 id = syn_get_final_id(id);
14521 else
14522#endif
14523 id = 0;
14524
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014525 rettv->vval.v_number = id;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014526}
14527
14528/*
14529 * "system()" function
14530 */
14531 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014532f_system(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000014533 typval_T *argvars;
14534 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014535{
Bram Moolenaarc0197e22004-09-13 20:26:32 +000014536 char_u *res = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014537 char_u *p;
Bram Moolenaarc0197e22004-09-13 20:26:32 +000014538 char_u *infile = NULL;
14539 char_u buf[NUMBUFLEN];
14540 int err = FALSE;
14541 FILE *fd;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014542
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014543 if (argvars[1].v_type != VAR_UNKNOWN)
Bram Moolenaarc0197e22004-09-13 20:26:32 +000014544 {
14545 /*
14546 * Write the string to a temp file, to be used for input of the shell
14547 * command.
14548 */
14549 if ((infile = vim_tempname('i')) == NULL)
14550 {
14551 EMSG(_(e_notmp));
14552 return;
14553 }
14554
14555 fd = mch_fopen((char *)infile, WRITEBIN);
14556 if (fd == NULL)
14557 {
14558 EMSG2(_(e_notopen), infile);
14559 goto done;
14560 }
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000014561 p = get_tv_string_buf_chk(&argvars[1], buf);
14562 if (p == NULL)
14563 goto done; /* type error; errmsg already given */
Bram Moolenaarc0197e22004-09-13 20:26:32 +000014564 if (fwrite(p, STRLEN(p), 1, fd) != 1)
14565 err = TRUE;
14566 if (fclose(fd) != 0)
14567 err = TRUE;
14568 if (err)
14569 {
14570 EMSG(_("E677: Error writing temp file"));
14571 goto done;
14572 }
14573 }
14574
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014575 res = get_cmd_output(get_tv_string(&argvars[0]), infile, SHELL_SILENT);
Bram Moolenaarc0197e22004-09-13 20:26:32 +000014576
Bram Moolenaar071d4272004-06-13 20:20:40 +000014577#ifdef USE_CR
14578 /* translate <CR> into <NL> */
Bram Moolenaarc0197e22004-09-13 20:26:32 +000014579 if (res != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000014580 {
14581 char_u *s;
14582
Bram Moolenaarc0197e22004-09-13 20:26:32 +000014583 for (s = res; *s; ++s)
Bram Moolenaar071d4272004-06-13 20:20:40 +000014584 {
14585 if (*s == CAR)
14586 *s = NL;
14587 }
14588 }
14589#else
14590# ifdef USE_CRNL
14591 /* translate <CR><NL> into <NL> */
Bram Moolenaarc0197e22004-09-13 20:26:32 +000014592 if (res != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000014593 {
14594 char_u *s, *d;
14595
Bram Moolenaarc0197e22004-09-13 20:26:32 +000014596 d = res;
14597 for (s = res; *s; ++s)
Bram Moolenaar071d4272004-06-13 20:20:40 +000014598 {
14599 if (s[0] == CAR && s[1] == NL)
14600 ++s;
14601 *d++ = *s;
14602 }
14603 *d = NUL;
14604 }
14605# endif
14606#endif
Bram Moolenaarc0197e22004-09-13 20:26:32 +000014607
14608done:
14609 if (infile != NULL)
14610 {
14611 mch_remove(infile);
14612 vim_free(infile);
14613 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014614 rettv->v_type = VAR_STRING;
14615 rettv->vval.v_string = res;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014616}
14617
14618/*
Bram Moolenaard43b6cf2005-09-09 19:53:42 +000014619 * "tagfiles()" function
14620 */
14621/*ARGSUSED*/
14622 static void
14623f_tagfiles(argvars, rettv)
14624 typval_T *argvars;
14625 typval_T *rettv;
14626{
14627 char_u fname[MAXPATHL + 1];
14628 list_T *l;
14629
14630 l = list_alloc();
14631 if (l == NULL)
14632 {
14633 rettv->vval.v_number = 0;
14634 return;
14635 }
14636 rettv->vval.v_list = l;
14637 rettv->v_type = VAR_LIST;
14638 ++l->lv_refcount;
14639
14640 get_tagfname(TRUE, NULL);
14641 for (;;)
14642 if (get_tagfname(FALSE, fname) == FAIL
Bram Moolenaar4463f292005-09-25 22:20:24 +000014643 || list_append_string(l, fname, -1) == FAIL)
Bram Moolenaard43b6cf2005-09-09 19:53:42 +000014644 break;
14645}
14646
14647/*
Bram Moolenaare2ac10d2005-03-07 23:26:06 +000014648 * "taglist()" function
Bram Moolenaar19a09a12005-03-04 23:39:37 +000014649 */
14650 static void
14651f_taglist(argvars, rettv)
14652 typval_T *argvars;
14653 typval_T *rettv;
14654{
14655 char_u *tag_pattern;
14656 list_T *l;
14657
14658 tag_pattern = get_tv_string(&argvars[0]);
14659
14660 rettv->vval.v_number = FALSE;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000014661 if (*tag_pattern == NUL)
14662 return;
Bram Moolenaar19a09a12005-03-04 23:39:37 +000014663
14664 l = list_alloc();
14665 if (l != NULL)
14666 {
14667 if (get_tags(l, tag_pattern) != FAIL)
14668 {
14669 rettv->vval.v_list = l;
14670 rettv->v_type = VAR_LIST;
14671 ++l->lv_refcount;
14672 }
14673 else
14674 list_free(l);
14675 }
14676}
14677
14678/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000014679 * "tempname()" function
14680 */
14681/*ARGSUSED*/
14682 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014683f_tempname(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000014684 typval_T *argvars;
14685 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014686{
14687 static int x = 'A';
14688
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014689 rettv->v_type = VAR_STRING;
14690 rettv->vval.v_string = vim_tempname(x);
Bram Moolenaar071d4272004-06-13 20:20:40 +000014691
14692 /* Advance 'x' to use A-Z and 0-9, so that there are at least 34 different
14693 * names. Skip 'I' and 'O', they are used for shell redirection. */
14694 do
14695 {
14696 if (x == 'Z')
14697 x = '0';
14698 else if (x == '9')
14699 x = 'A';
14700 else
14701 {
14702#ifdef EBCDIC
14703 if (x == 'I')
14704 x = 'J';
14705 else if (x == 'R')
14706 x = 'S';
14707 else
14708#endif
14709 ++x;
14710 }
14711 } while (x == 'I' || x == 'O');
14712}
14713
14714/*
Bram Moolenaard52d9742005-08-21 22:20:28 +000014715 * "test(list)" function: Just checking the walls...
14716 */
14717/*ARGSUSED*/
14718 static void
14719f_test(argvars, rettv)
14720 typval_T *argvars;
14721 typval_T *rettv;
14722{
14723 /* Used for unit testing. Change the code below to your liking. */
14724#if 0
14725 listitem_T *li;
14726 list_T *l;
14727 char_u *bad, *good;
14728
14729 if (argvars[0].v_type != VAR_LIST)
14730 return;
14731 l = argvars[0].vval.v_list;
14732 if (l == NULL)
14733 return;
14734 li = l->lv_first;
14735 if (li == NULL)
14736 return;
14737 bad = get_tv_string(&li->li_tv);
14738 li = li->li_next;
14739 if (li == NULL)
14740 return;
14741 good = get_tv_string(&li->li_tv);
14742 rettv->vval.v_number = test_edit_score(bad, good);
14743#endif
14744}
14745
14746/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000014747 * "tolower(string)" function
14748 */
14749 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014750f_tolower(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000014751 typval_T *argvars;
14752 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014753{
14754 char_u *p;
14755
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014756 p = vim_strsave(get_tv_string(&argvars[0]));
14757 rettv->v_type = VAR_STRING;
14758 rettv->vval.v_string = p;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014759
14760 if (p != NULL)
14761 while (*p != NUL)
14762 {
14763#ifdef FEAT_MBYTE
14764 int l;
14765
14766 if (enc_utf8)
14767 {
14768 int c, lc;
14769
14770 c = utf_ptr2char(p);
14771 lc = utf_tolower(c);
Bram Moolenaar0fa313a2005-08-10 21:07:57 +000014772 l = utf_ptr2len(p);
Bram Moolenaar071d4272004-06-13 20:20:40 +000014773 /* TODO: reallocate string when byte count changes. */
14774 if (utf_char2len(lc) == l)
14775 utf_char2bytes(lc, p);
14776 p += l;
14777 }
Bram Moolenaar0fa313a2005-08-10 21:07:57 +000014778 else if (has_mbyte && (l = (*mb_ptr2len)(p)) > 1)
Bram Moolenaar071d4272004-06-13 20:20:40 +000014779 p += l; /* skip multi-byte character */
14780 else
14781#endif
14782 {
14783 *p = TOLOWER_LOC(*p); /* note that tolower() can be a macro */
14784 ++p;
14785 }
14786 }
14787}
14788
14789/*
14790 * "toupper(string)" function
14791 */
14792 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014793f_toupper(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000014794 typval_T *argvars;
14795 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014796{
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014797 rettv->v_type = VAR_STRING;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000014798 rettv->vval.v_string = strup_save(get_tv_string(&argvars[0]));
Bram Moolenaar071d4272004-06-13 20:20:40 +000014799}
14800
14801/*
Bram Moolenaar8299df92004-07-10 09:47:34 +000014802 * "tr(string, fromstr, tostr)" function
14803 */
14804 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014805f_tr(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000014806 typval_T *argvars;
14807 typval_T *rettv;
Bram Moolenaar8299df92004-07-10 09:47:34 +000014808{
14809 char_u *instr;
14810 char_u *fromstr;
14811 char_u *tostr;
14812 char_u *p;
14813#ifdef FEAT_MBYTE
Bram Moolenaar342337a2005-07-21 21:11:17 +000014814 int inlen;
14815 int fromlen;
14816 int tolen;
Bram Moolenaar8299df92004-07-10 09:47:34 +000014817 int idx;
14818 char_u *cpstr;
14819 int cplen;
14820 int first = TRUE;
14821#endif
14822 char_u buf[NUMBUFLEN];
14823 char_u buf2[NUMBUFLEN];
14824 garray_T ga;
14825
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014826 instr = get_tv_string(&argvars[0]);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000014827 fromstr = get_tv_string_buf_chk(&argvars[1], buf);
14828 tostr = get_tv_string_buf_chk(&argvars[2], buf2);
Bram Moolenaar8299df92004-07-10 09:47:34 +000014829
14830 /* Default return value: empty string. */
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014831 rettv->v_type = VAR_STRING;
14832 rettv->vval.v_string = NULL;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000014833 if (fromstr == NULL || tostr == NULL)
14834 return; /* type error; errmsg already given */
Bram Moolenaar8299df92004-07-10 09:47:34 +000014835 ga_init2(&ga, (int)sizeof(char), 80);
14836
14837#ifdef FEAT_MBYTE
14838 if (!has_mbyte)
14839#endif
14840 /* not multi-byte: fromstr and tostr must be the same length */
14841 if (STRLEN(fromstr) != STRLEN(tostr))
14842 {
Bram Moolenaar5eb86f92004-07-26 12:53:41 +000014843#ifdef FEAT_MBYTE
Bram Moolenaar8299df92004-07-10 09:47:34 +000014844error:
Bram Moolenaar5eb86f92004-07-26 12:53:41 +000014845#endif
Bram Moolenaar8299df92004-07-10 09:47:34 +000014846 EMSG2(_(e_invarg2), fromstr);
14847 ga_clear(&ga);
14848 return;
14849 }
14850
14851 /* fromstr and tostr have to contain the same number of chars */
14852 while (*instr != NUL)
14853 {
14854#ifdef FEAT_MBYTE
14855 if (has_mbyte)
14856 {
Bram Moolenaar0fa313a2005-08-10 21:07:57 +000014857 inlen = (*mb_ptr2len)(instr);
Bram Moolenaar8299df92004-07-10 09:47:34 +000014858 cpstr = instr;
14859 cplen = inlen;
14860 idx = 0;
14861 for (p = fromstr; *p != NUL; p += fromlen)
14862 {
Bram Moolenaar0fa313a2005-08-10 21:07:57 +000014863 fromlen = (*mb_ptr2len)(p);
Bram Moolenaar8299df92004-07-10 09:47:34 +000014864 if (fromlen == inlen && STRNCMP(instr, p, inlen) == 0)
14865 {
14866 for (p = tostr; *p != NUL; p += tolen)
14867 {
Bram Moolenaar0fa313a2005-08-10 21:07:57 +000014868 tolen = (*mb_ptr2len)(p);
Bram Moolenaar8299df92004-07-10 09:47:34 +000014869 if (idx-- == 0)
14870 {
14871 cplen = tolen;
14872 cpstr = p;
14873 break;
14874 }
14875 }
14876 if (*p == NUL) /* tostr is shorter than fromstr */
14877 goto error;
14878 break;
14879 }
14880 ++idx;
14881 }
14882
14883 if (first && cpstr == instr)
14884 {
14885 /* Check that fromstr and tostr have the same number of
14886 * (multi-byte) characters. Done only once when a character
14887 * of instr doesn't appear in fromstr. */
14888 first = FALSE;
14889 for (p = tostr; *p != NUL; p += tolen)
14890 {
Bram Moolenaar0fa313a2005-08-10 21:07:57 +000014891 tolen = (*mb_ptr2len)(p);
Bram Moolenaar8299df92004-07-10 09:47:34 +000014892 --idx;
14893 }
14894 if (idx != 0)
14895 goto error;
14896 }
14897
14898 ga_grow(&ga, cplen);
Bram Moolenaar2df6dcc2004-07-12 15:53:54 +000014899 mch_memmove((char *)ga.ga_data + ga.ga_len, cpstr, (size_t)cplen);
Bram Moolenaar8299df92004-07-10 09:47:34 +000014900 ga.ga_len += cplen;
Bram Moolenaar8299df92004-07-10 09:47:34 +000014901
14902 instr += inlen;
14903 }
14904 else
14905#endif
14906 {
14907 /* When not using multi-byte chars we can do it faster. */
14908 p = vim_strchr(fromstr, *instr);
14909 if (p != NULL)
14910 ga_append(&ga, tostr[p - fromstr]);
14911 else
14912 ga_append(&ga, *instr);
14913 ++instr;
14914 }
14915 }
14916
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014917 rettv->vval.v_string = ga.ga_data;
Bram Moolenaar8299df92004-07-10 09:47:34 +000014918}
14919
14920/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000014921 * "type(expr)" function
14922 */
14923 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014924f_type(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000014925 typval_T *argvars;
14926 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014927{
Bram Moolenaar6cc16192005-01-08 21:49:45 +000014928 int n;
14929
14930 switch (argvars[0].v_type)
14931 {
14932 case VAR_NUMBER: n = 0; break;
14933 case VAR_STRING: n = 1; break;
14934 case VAR_FUNC: n = 2; break;
14935 case VAR_LIST: n = 3; break;
Bram Moolenaar758711c2005-02-02 23:11:38 +000014936 case VAR_DICT: n = 4; break;
Bram Moolenaar6cc16192005-01-08 21:49:45 +000014937 default: EMSG2(_(e_intern2), "f_type()"); n = 0; break;
14938 }
14939 rettv->vval.v_number = n;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014940}
14941
14942/*
Bram Moolenaar8c711452005-01-14 21:53:12 +000014943 * "values(dict)" function
14944 */
14945 static void
14946f_values(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000014947 typval_T *argvars;
14948 typval_T *rettv;
Bram Moolenaar8c711452005-01-14 21:53:12 +000014949{
14950 dict_list(argvars, rettv, 1);
14951}
14952
14953/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000014954 * "virtcol(string)" function
14955 */
14956 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014957f_virtcol(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000014958 typval_T *argvars;
14959 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014960{
14961 colnr_T vcol = 0;
14962 pos_T *fp;
14963
14964 fp = var2fpos(&argvars[0], FALSE);
14965 if (fp != NULL && fp->lnum <= curbuf->b_ml.ml_line_count)
14966 {
14967 getvvcol(curwin, fp, NULL, NULL, &vcol);
14968 ++vcol;
14969 }
14970
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014971 rettv->vval.v_number = vcol;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014972}
14973
14974/*
14975 * "visualmode()" function
14976 */
14977/*ARGSUSED*/
14978 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014979f_visualmode(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000014980 typval_T *argvars;
14981 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014982{
14983#ifdef FEAT_VISUAL
14984 char_u str[2];
14985
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014986 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014987 str[0] = curbuf->b_visual_mode_eval;
14988 str[1] = NUL;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014989 rettv->vval.v_string = vim_strsave(str);
Bram Moolenaar071d4272004-06-13 20:20:40 +000014990
14991 /* A non-zero number or non-empty string argument: reset mode. */
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014992 if ((argvars[0].v_type == VAR_NUMBER
14993 && argvars[0].vval.v_number != 0)
14994 || (argvars[0].v_type == VAR_STRING
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014995 && *get_tv_string(&argvars[0]) != NUL))
Bram Moolenaar071d4272004-06-13 20:20:40 +000014996 curbuf->b_visual_mode_eval = NUL;
14997#else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014998 rettv->vval.v_number = 0; /* return anything, it won't work anyway */
Bram Moolenaar071d4272004-06-13 20:20:40 +000014999#endif
15000}
15001
15002/*
15003 * "winbufnr(nr)" function
15004 */
15005 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015006f_winbufnr(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000015007 typval_T *argvars;
15008 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015009{
15010 win_T *wp;
15011
15012 wp = find_win_by_nr(&argvars[0]);
15013 if (wp == NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015014 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015015 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015016 rettv->vval.v_number = wp->w_buffer->b_fnum;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015017}
15018
15019/*
15020 * "wincol()" function
15021 */
15022/*ARGSUSED*/
15023 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015024f_wincol(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000015025 typval_T *argvars;
15026 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015027{
15028 validate_cursor();
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015029 rettv->vval.v_number = curwin->w_wcol + 1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015030}
15031
15032/*
15033 * "winheight(nr)" function
15034 */
15035 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015036f_winheight(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000015037 typval_T *argvars;
15038 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015039{
15040 win_T *wp;
15041
15042 wp = find_win_by_nr(&argvars[0]);
15043 if (wp == NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015044 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015045 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015046 rettv->vval.v_number = wp->w_height;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015047}
15048
15049/*
15050 * "winline()" function
15051 */
15052/*ARGSUSED*/
15053 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015054f_winline(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000015055 typval_T *argvars;
15056 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015057{
15058 validate_cursor();
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015059 rettv->vval.v_number = curwin->w_wrow + 1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015060}
15061
15062/*
15063 * "winnr()" function
15064 */
15065/* ARGSUSED */
15066 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015067f_winnr(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000015068 typval_T *argvars;
15069 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015070{
15071 int nr = 1;
15072#ifdef FEAT_WINDOWS
15073 win_T *wp;
Bram Moolenaar5eb86f92004-07-26 12:53:41 +000015074 win_T *twin = curwin;
15075 char_u *arg;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015076
Bram Moolenaar49cd9572005-01-03 21:06:01 +000015077 if (argvars[0].v_type != VAR_UNKNOWN)
Bram Moolenaar5eb86f92004-07-26 12:53:41 +000015078 {
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000015079 arg = get_tv_string_chk(&argvars[0]);
15080 if (arg == NULL)
15081 nr = 0; /* type error; errmsg already given */
15082 else if (STRCMP(arg, "$") == 0)
Bram Moolenaar5eb86f92004-07-26 12:53:41 +000015083 twin = lastwin;
15084 else if (STRCMP(arg, "#") == 0)
15085 {
15086 twin = prevwin;
15087 if (prevwin == NULL)
15088 nr = 0;
15089 }
15090 else
15091 {
15092 EMSG2(_(e_invexpr2), arg);
15093 nr = 0;
15094 }
15095 }
15096
15097 if (nr > 0)
15098 for (wp = firstwin; wp != twin; wp = wp->w_next)
15099 ++nr;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015100#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015101 rettv->vval.v_number = nr;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015102}
15103
15104/*
15105 * "winrestcmd()" function
15106 */
15107/* ARGSUSED */
15108 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015109f_winrestcmd(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000015110 typval_T *argvars;
15111 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015112{
15113#ifdef FEAT_WINDOWS
15114 win_T *wp;
15115 int winnr = 1;
15116 garray_T ga;
15117 char_u buf[50];
15118
15119 ga_init2(&ga, (int)sizeof(char), 70);
15120 for (wp = firstwin; wp != NULL; wp = wp->w_next)
15121 {
15122 sprintf((char *)buf, "%dresize %d|", winnr, wp->w_height);
15123 ga_concat(&ga, buf);
15124# ifdef FEAT_VERTSPLIT
15125 sprintf((char *)buf, "vert %dresize %d|", winnr, wp->w_width);
15126 ga_concat(&ga, buf);
15127# endif
15128 ++winnr;
15129 }
Bram Moolenaar269ec652004-07-29 08:43:53 +000015130 ga_append(&ga, NUL);
Bram Moolenaar071d4272004-06-13 20:20:40 +000015131
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015132 rettv->vval.v_string = ga.ga_data;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015133#else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015134 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015135#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015136 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015137}
15138
15139/*
15140 * "winwidth(nr)" function
15141 */
15142 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015143f_winwidth(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000015144 typval_T *argvars;
15145 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015146{
15147 win_T *wp;
15148
15149 wp = find_win_by_nr(&argvars[0]);
15150 if (wp == NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015151 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015152 else
15153#ifdef FEAT_VERTSPLIT
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015154 rettv->vval.v_number = wp->w_width;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015155#else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015156 rettv->vval.v_number = Columns;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015157#endif
15158}
15159
Bram Moolenaar071d4272004-06-13 20:20:40 +000015160/*
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000015161 * "writefile()" function
15162 */
15163 static void
15164f_writefile(argvars, rettv)
15165 typval_T *argvars;
15166 typval_T *rettv;
15167{
15168 int binary = FALSE;
15169 char_u *fname;
15170 FILE *fd;
15171 listitem_T *li;
15172 char_u *s;
15173 int ret = 0;
15174 int c;
15175
15176 if (argvars[0].v_type != VAR_LIST)
15177 {
15178 EMSG2(_(e_listarg), "writefile()");
15179 return;
15180 }
15181 if (argvars[0].vval.v_list == NULL)
15182 return;
15183
15184 if (argvars[2].v_type != VAR_UNKNOWN
15185 && STRCMP(get_tv_string(&argvars[2]), "b") == 0)
15186 binary = TRUE;
15187
15188 /* Always open the file in binary mode, library functions have a mind of
15189 * their own about CR-LF conversion. */
15190 fname = get_tv_string(&argvars[1]);
15191 if (*fname == NUL || (fd = mch_fopen((char *)fname, WRITEBIN)) == NULL)
15192 {
15193 EMSG2(_(e_notcreate), *fname == NUL ? (char_u *)_("<empty>") : fname);
15194 ret = -1;
15195 }
15196 else
15197 {
15198 for (li = argvars[0].vval.v_list->lv_first; li != NULL;
15199 li = li->li_next)
15200 {
15201 for (s = get_tv_string(&li->li_tv); *s != NUL; ++s)
15202 {
15203 if (*s == '\n')
15204 c = putc(NUL, fd);
15205 else
15206 c = putc(*s, fd);
15207 if (c == EOF)
15208 {
15209 ret = -1;
15210 break;
15211 }
15212 }
15213 if (!binary || li->li_next != NULL)
15214 if (putc('\n', fd) == EOF)
15215 {
15216 ret = -1;
15217 break;
15218 }
15219 if (ret < 0)
15220 {
15221 EMSG(_(e_write));
15222 break;
15223 }
15224 }
15225 fclose(fd);
15226 }
15227
15228 rettv->vval.v_number = ret;
15229}
15230
15231/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000015232 * Translate a String variable into a position.
15233 */
15234 static pos_T *
15235var2fpos(varp, lnum)
Bram Moolenaar33570922005-01-25 22:26:29 +000015236 typval_T *varp;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015237 int lnum; /* TRUE when $ is last line */
15238{
15239 char_u *name;
15240 static pos_T pos;
15241 pos_T *pp;
15242
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000015243 name = get_tv_string_chk(varp);
15244 if (name == NULL)
15245 return NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015246 if (name[0] == '.') /* cursor */
15247 return &curwin->w_cursor;
15248 if (name[0] == '\'') /* mark */
15249 {
15250 pp = getmark(name[1], FALSE);
15251 if (pp == NULL || pp == (pos_T *)-1 || pp->lnum <= 0)
15252 return NULL;
15253 return pp;
15254 }
15255 if (name[0] == '$') /* last column or line */
15256 {
15257 if (lnum)
15258 {
15259 pos.lnum = curbuf->b_ml.ml_line_count;
15260 pos.col = 0;
15261 }
15262 else
15263 {
15264 pos.lnum = curwin->w_cursor.lnum;
15265 pos.col = (colnr_T)STRLEN(ml_get_curline());
15266 }
15267 return &pos;
15268 }
15269 return NULL;
15270}
15271
15272/*
15273 * Get the length of an environment variable name.
15274 * Advance "arg" to the first character after the name.
15275 * Return 0 for error.
15276 */
15277 static int
15278get_env_len(arg)
15279 char_u **arg;
15280{
15281 char_u *p;
15282 int len;
15283
15284 for (p = *arg; vim_isIDc(*p); ++p)
15285 ;
15286 if (p == *arg) /* no name found */
15287 return 0;
15288
15289 len = (int)(p - *arg);
15290 *arg = p;
15291 return len;
15292}
15293
15294/*
15295 * Get the length of the name of a function or internal variable.
15296 * "arg" is advanced to the first non-white character after the name.
15297 * Return 0 if something is wrong.
15298 */
15299 static int
15300get_id_len(arg)
15301 char_u **arg;
15302{
15303 char_u *p;
15304 int len;
15305
15306 /* Find the end of the name. */
15307 for (p = *arg; eval_isnamec(*p); ++p)
15308 ;
15309 if (p == *arg) /* no name found */
15310 return 0;
15311
15312 len = (int)(p - *arg);
15313 *arg = skipwhite(p);
15314
15315 return len;
15316}
15317
15318/*
Bram Moolenaara7043832005-01-21 11:56:39 +000015319 * Get the length of the name of a variable or function.
15320 * Only the name is recognized, does not handle ".key" or "[idx]".
Bram Moolenaar071d4272004-06-13 20:20:40 +000015321 * "arg" is advanced to the first non-white character after the name.
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000015322 * Return -1 if curly braces expansion failed.
15323 * Return 0 if something else is wrong.
Bram Moolenaar071d4272004-06-13 20:20:40 +000015324 * If the name contains 'magic' {}'s, expand them and return the
15325 * expanded name in an allocated string via 'alias' - caller must free.
15326 */
15327 static int
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000015328get_name_len(arg, alias, evaluate, verbose)
Bram Moolenaar071d4272004-06-13 20:20:40 +000015329 char_u **arg;
15330 char_u **alias;
15331 int evaluate;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000015332 int verbose;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015333{
15334 int len;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015335 char_u *p;
15336 char_u *expr_start;
15337 char_u *expr_end;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015338
15339 *alias = NULL; /* default to no alias */
15340
15341 if ((*arg)[0] == K_SPECIAL && (*arg)[1] == KS_EXTRA
15342 && (*arg)[2] == (int)KE_SNR)
15343 {
15344 /* hard coded <SNR>, already translated */
15345 *arg += 3;
15346 return get_id_len(arg) + 3;
15347 }
15348 len = eval_fname_script(*arg);
15349 if (len > 0)
15350 {
15351 /* literal "<SID>", "s:" or "<SNR>" */
15352 *arg += len;
15353 }
15354
Bram Moolenaar071d4272004-06-13 20:20:40 +000015355 /*
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015356 * Find the end of the name; check for {} construction.
Bram Moolenaar071d4272004-06-13 20:20:40 +000015357 */
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +000015358 p = find_name_end(*arg, &expr_start, &expr_end,
15359 len > 0 ? 0 : FNE_CHECK_START);
Bram Moolenaar071d4272004-06-13 20:20:40 +000015360 if (expr_start != NULL)
15361 {
15362 char_u *temp_string;
15363
15364 if (!evaluate)
15365 {
15366 len += (int)(p - *arg);
15367 *arg = skipwhite(p);
15368 return len;
15369 }
15370
15371 /*
15372 * Include any <SID> etc in the expanded string:
15373 * Thus the -len here.
15374 */
15375 temp_string = make_expanded_name(*arg - len, expr_start, expr_end, p);
15376 if (temp_string == NULL)
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000015377 return -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015378 *alias = temp_string;
15379 *arg = skipwhite(p);
15380 return (int)STRLEN(temp_string);
15381 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000015382
15383 len += get_id_len(arg);
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000015384 if (len == 0 && verbose)
Bram Moolenaar071d4272004-06-13 20:20:40 +000015385 EMSG2(_(e_invexpr2), *arg);
15386
15387 return len;
15388}
15389
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015390/*
15391 * Find the end of a variable or function name, taking care of magic braces.
15392 * If "expr_start" is not NULL then "expr_start" and "expr_end" are set to the
15393 * start and end of the first magic braces item.
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +000015394 * "flags" can have FNE_INCL_BR and FNE_CHECK_START.
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015395 * Return a pointer to just after the name. Equal to "arg" if there is no
15396 * valid name.
15397 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000015398 static char_u *
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +000015399find_name_end(arg, expr_start, expr_end, flags)
Bram Moolenaar071d4272004-06-13 20:20:40 +000015400 char_u *arg;
15401 char_u **expr_start;
15402 char_u **expr_end;
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +000015403 int flags;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015404{
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015405 int mb_nest = 0;
15406 int br_nest = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015407 char_u *p;
15408
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015409 if (expr_start != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000015410 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015411 *expr_start = NULL;
15412 *expr_end = NULL;
15413 }
15414
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +000015415 /* Quick check for valid starting character. */
15416 if ((flags & FNE_CHECK_START) && !eval_isnamec1(*arg) && *arg != '{')
15417 return arg;
15418
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015419 for (p = arg; *p != NUL
15420 && (eval_isnamec(*p)
Bram Moolenaare9a41262005-01-15 22:18:47 +000015421 || *p == '{'
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +000015422 || ((flags & FNE_INCL_BR) && (*p == '[' || *p == '.'))
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015423 || mb_nest != 0
Bram Moolenaar8af24422005-08-08 22:06:28 +000015424 || br_nest != 0); mb_ptr_adv(p))
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015425 {
Bram Moolenaar8af24422005-08-08 22:06:28 +000015426 if (*p == '\'')
15427 {
15428 /* skip over 'string' to avoid counting [ and ] inside it. */
15429 for (p = p + 1; *p != NUL && *p != '\''; mb_ptr_adv(p))
15430 ;
15431 if (*p == NUL)
15432 break;
15433 }
15434 else if (*p == '"')
15435 {
15436 /* skip over "str\"ing" to avoid counting [ and ] inside it. */
15437 for (p = p + 1; *p != NUL && *p != '"'; mb_ptr_adv(p))
15438 if (*p == '\\' && p[1] != NUL)
15439 ++p;
15440 if (*p == NUL)
15441 break;
15442 }
15443
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015444 if (mb_nest == 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +000015445 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015446 if (*p == '[')
15447 ++br_nest;
15448 else if (*p == ']')
15449 --br_nest;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015450 }
Bram Moolenaar8af24422005-08-08 22:06:28 +000015451
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015452 if (br_nest == 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +000015453 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015454 if (*p == '{')
15455 {
15456 mb_nest++;
15457 if (expr_start != NULL && *expr_start == NULL)
15458 *expr_start = p;
15459 }
15460 else if (*p == '}')
15461 {
15462 mb_nest--;
15463 if (expr_start != NULL && mb_nest == 0 && *expr_end == NULL)
15464 *expr_end = p;
15465 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000015466 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000015467 }
15468
15469 return p;
15470}
15471
15472/*
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000015473 * Expands out the 'magic' {}'s in a variable/function name.
15474 * Note that this can call itself recursively, to deal with
15475 * constructs like foo{bar}{baz}{bam}
15476 * The four pointer arguments point to "foo{expre}ss{ion}bar"
15477 * "in_start" ^
15478 * "expr_start" ^
15479 * "expr_end" ^
15480 * "in_end" ^
15481 *
15482 * Returns a new allocated string, which the caller must free.
15483 * Returns NULL for failure.
15484 */
15485 static char_u *
15486make_expanded_name(in_start, expr_start, expr_end, in_end)
15487 char_u *in_start;
15488 char_u *expr_start;
15489 char_u *expr_end;
15490 char_u *in_end;
15491{
15492 char_u c1;
15493 char_u *retval = NULL;
15494 char_u *temp_result;
15495 char_u *nextcmd = NULL;
15496
15497 if (expr_end == NULL || in_end == NULL)
15498 return NULL;
15499 *expr_start = NUL;
15500 *expr_end = NUL;
15501 c1 = *in_end;
15502 *in_end = NUL;
15503
15504 temp_result = eval_to_string(expr_start + 1, &nextcmd);
15505 if (temp_result != NULL && nextcmd == NULL)
15506 {
15507 retval = alloc((unsigned)(STRLEN(temp_result) + (expr_start - in_start)
15508 + (in_end - expr_end) + 1));
15509 if (retval != NULL)
15510 {
15511 STRCPY(retval, in_start);
15512 STRCAT(retval, temp_result);
15513 STRCAT(retval, expr_end + 1);
15514 }
15515 }
15516 vim_free(temp_result);
15517
15518 *in_end = c1; /* put char back for error messages */
15519 *expr_start = '{';
15520 *expr_end = '}';
15521
15522 if (retval != NULL)
15523 {
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +000015524 temp_result = find_name_end(retval, &expr_start, &expr_end, 0);
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000015525 if (expr_start != NULL)
15526 {
15527 /* Further expansion! */
15528 temp_result = make_expanded_name(retval, expr_start,
15529 expr_end, temp_result);
15530 vim_free(retval);
15531 retval = temp_result;
15532 }
15533 }
15534
15535 return retval;
15536}
15537
15538/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000015539 * Return TRUE if character "c" can be used in a variable or function name.
Bram Moolenaare9a41262005-01-15 22:18:47 +000015540 * Does not include '{' or '}' for magic braces.
Bram Moolenaar071d4272004-06-13 20:20:40 +000015541 */
15542 static int
15543eval_isnamec(c)
15544 int c;
15545{
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +000015546 return (ASCII_ISALNUM(c) || c == '_' || c == ':' || c == AUTOLOAD_CHAR);
15547}
15548
15549/*
15550 * Return TRUE if character "c" can be used as the first character in a
15551 * variable or function name (excluding '{' and '}').
15552 */
15553 static int
15554eval_isnamec1(c)
15555 int c;
15556{
15557 return (ASCII_ISALPHA(c) || c == '_');
Bram Moolenaar071d4272004-06-13 20:20:40 +000015558}
15559
15560/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000015561 * Set number v: variable to "val".
15562 */
15563 void
15564set_vim_var_nr(idx, val)
15565 int idx;
15566 long val;
15567{
Bram Moolenaare9a41262005-01-15 22:18:47 +000015568 vimvars[idx].vv_nr = val;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015569}
15570
15571/*
Bram Moolenaar19a09a12005-03-04 23:39:37 +000015572 * Get number v: variable value.
Bram Moolenaar071d4272004-06-13 20:20:40 +000015573 */
15574 long
15575get_vim_var_nr(idx)
15576 int idx;
15577{
Bram Moolenaare9a41262005-01-15 22:18:47 +000015578 return vimvars[idx].vv_nr;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015579}
15580
Bram Moolenaar19a09a12005-03-04 23:39:37 +000015581#if defined(FEAT_AUTOCMD) || defined(PROTO)
15582/*
15583 * Get string v: variable value. Uses a static buffer, can only be used once.
15584 */
15585 char_u *
15586get_vim_var_str(idx)
15587 int idx;
15588{
15589 return get_tv_string(&vimvars[idx].vv_tv);
15590}
15591#endif
15592
Bram Moolenaar071d4272004-06-13 20:20:40 +000015593/*
15594 * Set v:count, v:count1 and v:prevcount.
15595 */
15596 void
15597set_vcount(count, count1)
15598 long count;
15599 long count1;
15600{
Bram Moolenaare9a41262005-01-15 22:18:47 +000015601 vimvars[VV_PREVCOUNT].vv_nr = vimvars[VV_COUNT].vv_nr;
15602 vimvars[VV_COUNT].vv_nr = count;
15603 vimvars[VV_COUNT1].vv_nr = count1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015604}
15605
15606/*
15607 * Set string v: variable to a copy of "val".
15608 */
15609 void
15610set_vim_var_string(idx, val, len)
15611 int idx;
15612 char_u *val;
15613 int len; /* length of "val" to use or -1 (whole string) */
15614{
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000015615 /* Need to do this (at least) once, since we can't initialize a union.
15616 * Will always be invoked when "v:progname" is set. */
15617 vimvars[VV_VERSION].vv_nr = VIM_VERSION_100;
15618
Bram Moolenaare9a41262005-01-15 22:18:47 +000015619 vim_free(vimvars[idx].vv_str);
Bram Moolenaar071d4272004-06-13 20:20:40 +000015620 if (val == NULL)
Bram Moolenaare9a41262005-01-15 22:18:47 +000015621 vimvars[idx].vv_str = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015622 else if (len == -1)
Bram Moolenaare9a41262005-01-15 22:18:47 +000015623 vimvars[idx].vv_str = vim_strsave(val);
Bram Moolenaar071d4272004-06-13 20:20:40 +000015624 else
Bram Moolenaare9a41262005-01-15 22:18:47 +000015625 vimvars[idx].vv_str = vim_strnsave(val, len);
Bram Moolenaar071d4272004-06-13 20:20:40 +000015626}
15627
15628/*
15629 * Set v:register if needed.
15630 */
15631 void
15632set_reg_var(c)
15633 int c;
15634{
15635 char_u regname;
15636
15637 if (c == 0 || c == ' ')
15638 regname = '"';
15639 else
15640 regname = c;
15641 /* Avoid free/alloc when the value is already right. */
Bram Moolenaare9a41262005-01-15 22:18:47 +000015642 if (vimvars[VV_REG].vv_str == NULL || vimvars[VV_REG].vv_str[0] != c)
Bram Moolenaar071d4272004-06-13 20:20:40 +000015643 set_vim_var_string(VV_REG, &regname, 1);
15644}
15645
15646/*
15647 * Get or set v:exception. If "oldval" == NULL, return the current value.
15648 * Otherwise, restore the value to "oldval" and return NULL.
15649 * Must always be called in pairs to save and restore v:exception! Does not
15650 * take care of memory allocations.
15651 */
15652 char_u *
15653v_exception(oldval)
15654 char_u *oldval;
15655{
15656 if (oldval == NULL)
Bram Moolenaare9a41262005-01-15 22:18:47 +000015657 return vimvars[VV_EXCEPTION].vv_str;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015658
Bram Moolenaare9a41262005-01-15 22:18:47 +000015659 vimvars[VV_EXCEPTION].vv_str = oldval;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015660 return NULL;
15661}
15662
15663/*
15664 * Get or set v:throwpoint. If "oldval" == NULL, return the current value.
15665 * Otherwise, restore the value to "oldval" and return NULL.
15666 * Must always be called in pairs to save and restore v:throwpoint! Does not
15667 * take care of memory allocations.
15668 */
15669 char_u *
15670v_throwpoint(oldval)
15671 char_u *oldval;
15672{
15673 if (oldval == NULL)
Bram Moolenaare9a41262005-01-15 22:18:47 +000015674 return vimvars[VV_THROWPOINT].vv_str;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015675
Bram Moolenaare9a41262005-01-15 22:18:47 +000015676 vimvars[VV_THROWPOINT].vv_str = oldval;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015677 return NULL;
15678}
15679
15680#if defined(FEAT_AUTOCMD) || defined(PROTO)
15681/*
15682 * Set v:cmdarg.
15683 * If "eap" != NULL, use "eap" to generate the value and return the old value.
15684 * If "oldarg" != NULL, restore the value to "oldarg" and return NULL.
15685 * Must always be called in pairs!
15686 */
15687 char_u *
15688set_cmdarg(eap, oldarg)
15689 exarg_T *eap;
15690 char_u *oldarg;
15691{
15692 char_u *oldval;
15693 char_u *newval;
15694 unsigned len;
15695
Bram Moolenaare9a41262005-01-15 22:18:47 +000015696 oldval = vimvars[VV_CMDARG].vv_str;
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +000015697 if (eap == NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000015698 {
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +000015699 vim_free(oldval);
Bram Moolenaare9a41262005-01-15 22:18:47 +000015700 vimvars[VV_CMDARG].vv_str = oldarg;
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +000015701 return NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015702 }
15703
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +000015704 if (eap->force_bin == FORCE_BIN)
15705 len = 6;
15706 else if (eap->force_bin == FORCE_NOBIN)
15707 len = 8;
15708 else
15709 len = 0;
15710 if (eap->force_ff != 0)
15711 len += (unsigned)STRLEN(eap->cmd + eap->force_ff) + 6;
15712# ifdef FEAT_MBYTE
15713 if (eap->force_enc != 0)
15714 len += (unsigned)STRLEN(eap->cmd + eap->force_enc) + 7;
15715# endif
15716
15717 newval = alloc(len + 1);
15718 if (newval == NULL)
15719 return NULL;
15720
15721 if (eap->force_bin == FORCE_BIN)
15722 sprintf((char *)newval, " ++bin");
15723 else if (eap->force_bin == FORCE_NOBIN)
15724 sprintf((char *)newval, " ++nobin");
15725 else
15726 *newval = NUL;
15727 if (eap->force_ff != 0)
15728 sprintf((char *)newval + STRLEN(newval), " ++ff=%s",
15729 eap->cmd + eap->force_ff);
15730# ifdef FEAT_MBYTE
15731 if (eap->force_enc != 0)
15732 sprintf((char *)newval + STRLEN(newval), " ++enc=%s",
15733 eap->cmd + eap->force_enc);
15734# endif
Bram Moolenaare9a41262005-01-15 22:18:47 +000015735 vimvars[VV_CMDARG].vv_str = newval;
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +000015736 return oldval;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015737}
15738#endif
15739
15740/*
15741 * Get the value of internal variable "name".
15742 * Return OK or FAIL.
15743 */
15744 static int
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000015745get_var_tv(name, len, rettv, verbose)
Bram Moolenaar071d4272004-06-13 20:20:40 +000015746 char_u *name;
15747 int len; /* length of "name" */
Bram Moolenaar33570922005-01-25 22:26:29 +000015748 typval_T *rettv; /* NULL when only checking existence */
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000015749 int verbose; /* may give error message */
Bram Moolenaar071d4272004-06-13 20:20:40 +000015750{
15751 int ret = OK;
Bram Moolenaar33570922005-01-25 22:26:29 +000015752 typval_T *tv = NULL;
15753 typval_T atv;
15754 dictitem_T *v;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015755 int cc;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015756
15757 /* truncate the name, so that we can use strcmp() */
15758 cc = name[len];
15759 name[len] = NUL;
15760
15761 /*
15762 * Check for "b:changedtick".
15763 */
15764 if (STRCMP(name, "b:changedtick") == 0)
15765 {
Bram Moolenaare9a41262005-01-15 22:18:47 +000015766 atv.v_type = VAR_NUMBER;
15767 atv.vval.v_number = curbuf->b_changedtick;
15768 tv = &atv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015769 }
15770
15771 /*
Bram Moolenaar071d4272004-06-13 20:20:40 +000015772 * Check for user-defined variables.
15773 */
15774 else
15775 {
Bram Moolenaara7043832005-01-21 11:56:39 +000015776 v = find_var(name, NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +000015777 if (v != NULL)
Bram Moolenaar33570922005-01-25 22:26:29 +000015778 tv = &v->di_tv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015779 }
15780
Bram Moolenaare9a41262005-01-15 22:18:47 +000015781 if (tv == NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000015782 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000015783 if (rettv != NULL && verbose)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015784 EMSG2(_(e_undefvar), name);
Bram Moolenaar071d4272004-06-13 20:20:40 +000015785 ret = FAIL;
15786 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015787 else if (rettv != NULL)
Bram Moolenaare9a41262005-01-15 22:18:47 +000015788 copy_tv(tv, rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000015789
15790 name[len] = cc;
15791
15792 return ret;
15793}
15794
15795/*
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000015796 * Handle expr[expr], expr[expr:expr] subscript and .name lookup.
15797 * Also handle function call with Funcref variable: func(expr)
15798 * Can all be combined: dict.func(expr)[idx]['func'](expr)
15799 */
15800 static int
15801handle_subscript(arg, rettv, evaluate, verbose)
15802 char_u **arg;
15803 typval_T *rettv;
15804 int evaluate; /* do more than finding the end */
15805 int verbose; /* give error messages */
15806{
15807 int ret = OK;
15808 dict_T *selfdict = NULL;
15809 char_u *s;
15810 int len;
Bram Moolenaard9fba312005-06-26 22:34:35 +000015811 typval_T functv;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000015812
15813 while (ret == OK
15814 && (**arg == '['
15815 || (**arg == '.' && rettv->v_type == VAR_DICT)
15816 || (**arg == '(' && rettv->v_type == VAR_FUNC))
15817 && !vim_iswhite(*(*arg - 1)))
15818 {
15819 if (**arg == '(')
15820 {
Bram Moolenaard9fba312005-06-26 22:34:35 +000015821 /* need to copy the funcref so that we can clear rettv */
15822 functv = *rettv;
15823 rettv->v_type = VAR_UNKNOWN;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000015824
15825 /* Invoke the function. Recursive! */
Bram Moolenaard9fba312005-06-26 22:34:35 +000015826 s = functv.vval.v_string;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000015827 ret = get_func_tv(s, STRLEN(s), rettv, arg,
Bram Moolenaard9fba312005-06-26 22:34:35 +000015828 curwin->w_cursor.lnum, curwin->w_cursor.lnum,
15829 &len, evaluate, selfdict);
15830
15831 /* Clear the funcref afterwards, so that deleting it while
15832 * evaluating the arguments is possible (see test55). */
15833 clear_tv(&functv);
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000015834
15835 /* Stop the expression evaluation when immediately aborting on
15836 * error, or when an interrupt occurred or an exception was thrown
15837 * but not caught. */
15838 if (aborting())
15839 {
15840 if (ret == OK)
15841 clear_tv(rettv);
15842 ret = FAIL;
15843 }
15844 dict_unref(selfdict);
15845 selfdict = NULL;
15846 }
15847 else /* **arg == '[' || **arg == '.' */
15848 {
15849 dict_unref(selfdict);
15850 if (rettv->v_type == VAR_DICT)
15851 {
15852 selfdict = rettv->vval.v_dict;
15853 if (selfdict != NULL)
15854 ++selfdict->dv_refcount;
15855 }
15856 else
15857 selfdict = NULL;
15858 if (eval_index(arg, rettv, evaluate, verbose) == FAIL)
15859 {
15860 clear_tv(rettv);
15861 ret = FAIL;
15862 }
15863 }
15864 }
15865 dict_unref(selfdict);
15866 return ret;
15867}
15868
15869/*
Bram Moolenaar49cd9572005-01-03 21:06:01 +000015870 * Allocate memory for a variable type-value, and make it emtpy (0 or NULL
15871 * value).
15872 */
Bram Moolenaar33570922005-01-25 22:26:29 +000015873 static typval_T *
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015874alloc_tv()
Bram Moolenaar49cd9572005-01-03 21:06:01 +000015875{
Bram Moolenaar33570922005-01-25 22:26:29 +000015876 return (typval_T *)alloc_clear((unsigned)sizeof(typval_T));
Bram Moolenaar49cd9572005-01-03 21:06:01 +000015877}
15878
15879/*
15880 * Allocate memory for a variable type-value, and assign a string to it.
Bram Moolenaar071d4272004-06-13 20:20:40 +000015881 * The string "s" must have been allocated, it is consumed.
15882 * Return NULL for out of memory, the variable otherwise.
15883 */
Bram Moolenaar33570922005-01-25 22:26:29 +000015884 static typval_T *
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015885alloc_string_tv(s)
Bram Moolenaar071d4272004-06-13 20:20:40 +000015886 char_u *s;
15887{
Bram Moolenaar33570922005-01-25 22:26:29 +000015888 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015889
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015890 rettv = alloc_tv();
15891 if (rettv != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000015892 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015893 rettv->v_type = VAR_STRING;
15894 rettv->vval.v_string = s;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015895 }
15896 else
15897 vim_free(s);
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015898 return rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015899}
15900
15901/*
Bram Moolenaar49cd9572005-01-03 21:06:01 +000015902 * Free the memory for a variable type-value.
Bram Moolenaar071d4272004-06-13 20:20:40 +000015903 */
15904 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015905free_tv(varp)
Bram Moolenaar33570922005-01-25 22:26:29 +000015906 typval_T *varp;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015907{
15908 if (varp != NULL)
15909 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +000015910 switch (varp->v_type)
15911 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +000015912 case VAR_FUNC:
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000015913 func_unref(varp->vval.v_string);
15914 /*FALLTHROUGH*/
15915 case VAR_STRING:
Bram Moolenaar49cd9572005-01-03 21:06:01 +000015916 vim_free(varp->vval.v_string);
15917 break;
15918 case VAR_LIST:
15919 list_unref(varp->vval.v_list);
15920 break;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000015921 case VAR_DICT:
15922 dict_unref(varp->vval.v_dict);
15923 break;
Bram Moolenaar758711c2005-02-02 23:11:38 +000015924 case VAR_NUMBER:
15925 case VAR_UNKNOWN:
15926 break;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000015927 default:
Bram Moolenaar758711c2005-02-02 23:11:38 +000015928 EMSG2(_(e_intern2), "free_tv()");
Bram Moolenaar49cd9572005-01-03 21:06:01 +000015929 break;
15930 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000015931 vim_free(varp);
15932 }
15933}
15934
15935/*
15936 * Free the memory for a variable value and set the value to NULL or 0.
15937 */
Bram Moolenaar87e25fd2005-07-27 21:13:01 +000015938 void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015939clear_tv(varp)
Bram Moolenaar33570922005-01-25 22:26:29 +000015940 typval_T *varp;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015941{
15942 if (varp != NULL)
15943 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +000015944 switch (varp->v_type)
Bram Moolenaar071d4272004-06-13 20:20:40 +000015945 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +000015946 case VAR_FUNC:
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000015947 func_unref(varp->vval.v_string);
15948 /*FALLTHROUGH*/
15949 case VAR_STRING:
Bram Moolenaar49cd9572005-01-03 21:06:01 +000015950 vim_free(varp->vval.v_string);
15951 varp->vval.v_string = NULL;
15952 break;
15953 case VAR_LIST:
15954 list_unref(varp->vval.v_list);
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000015955 varp->vval.v_list = NULL;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000015956 break;
Bram Moolenaar8c711452005-01-14 21:53:12 +000015957 case VAR_DICT:
15958 dict_unref(varp->vval.v_dict);
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000015959 varp->vval.v_dict = NULL;
Bram Moolenaar8c711452005-01-14 21:53:12 +000015960 break;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015961 case VAR_NUMBER:
Bram Moolenaar49cd9572005-01-03 21:06:01 +000015962 varp->vval.v_number = 0;
15963 break;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015964 case VAR_UNKNOWN:
15965 break;
15966 default:
15967 EMSG2(_(e_intern2), "clear_tv()");
Bram Moolenaar071d4272004-06-13 20:20:40 +000015968 }
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000015969 varp->v_lock = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015970 }
15971}
15972
15973/*
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015974 * Set the value of a variable to NULL without freeing items.
15975 */
15976 static void
15977init_tv(varp)
Bram Moolenaar33570922005-01-25 22:26:29 +000015978 typval_T *varp;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015979{
15980 if (varp != NULL)
Bram Moolenaar33570922005-01-25 22:26:29 +000015981 vim_memset(varp, 0, sizeof(typval_T));
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015982}
15983
15984/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000015985 * Get the number value of a variable.
15986 * If it is a String variable, uses vim_str2nr().
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000015987 * For incompatible types, return 0.
15988 * get_tv_number_chk() is similar to get_tv_number(), but informs the
15989 * caller of incompatible types: it sets *denote to TRUE if "denote"
15990 * is not NULL or returns -1 otherwise.
Bram Moolenaar071d4272004-06-13 20:20:40 +000015991 */
15992 static long
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015993get_tv_number(varp)
Bram Moolenaar33570922005-01-25 22:26:29 +000015994 typval_T *varp;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015995{
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000015996 int error = FALSE;
15997
15998 return get_tv_number_chk(varp, &error); /* return 0L on error */
15999}
16000
Bram Moolenaar4be06f92005-07-29 22:36:03 +000016001 long
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000016002get_tv_number_chk(varp, denote)
16003 typval_T *varp;
16004 int *denote;
16005{
Bram Moolenaar49cd9572005-01-03 21:06:01 +000016006 long n = 0L;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016007
Bram Moolenaar49cd9572005-01-03 21:06:01 +000016008 switch (varp->v_type)
Bram Moolenaar071d4272004-06-13 20:20:40 +000016009 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +000016010 case VAR_NUMBER:
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000016011 return (long)(varp->vval.v_number);
Bram Moolenaar49cd9572005-01-03 21:06:01 +000016012 case VAR_FUNC:
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000016013 EMSG(_("E703: Using a Funcref as a number"));
Bram Moolenaar49cd9572005-01-03 21:06:01 +000016014 break;
16015 case VAR_STRING:
16016 if (varp->vval.v_string != NULL)
16017 vim_str2nr(varp->vval.v_string, NULL, NULL,
16018 TRUE, TRUE, &n, NULL);
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000016019 return n;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000016020 case VAR_LIST:
Bram Moolenaar758711c2005-02-02 23:11:38 +000016021 EMSG(_("E745: Using a List as a number"));
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000016022 break;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000016023 case VAR_DICT:
16024 EMSG(_("E728: Using a Dictionary as a number"));
16025 break;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000016026 default:
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000016027 EMSG2(_(e_intern2), "get_tv_number()");
Bram Moolenaar49cd9572005-01-03 21:06:01 +000016028 break;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016029 }
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000016030 if (denote == NULL) /* useful for values that must be unsigned */
16031 n = -1;
16032 else
16033 *denote = TRUE;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000016034 return n;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016035}
16036
16037/*
Bram Moolenaar661b1822005-07-28 22:36:45 +000016038 * Get the lnum from the first argument.
16039 * Also accepts ".", "$", etc., but that only works for the current buffer.
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000016040 * Returns -1 on error.
Bram Moolenaar071d4272004-06-13 20:20:40 +000016041 */
16042 static linenr_T
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016043get_tv_lnum(argvars)
Bram Moolenaar33570922005-01-25 22:26:29 +000016044 typval_T *argvars;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016045{
Bram Moolenaar33570922005-01-25 22:26:29 +000016046 typval_T rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016047 linenr_T lnum;
16048
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000016049 lnum = get_tv_number_chk(&argvars[0], NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +000016050 if (lnum == 0) /* no valid number, try using line() */
16051 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016052 rettv.v_type = VAR_NUMBER;
16053 f_line(argvars, &rettv);
16054 lnum = rettv.vval.v_number;
16055 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000016056 }
16057 return lnum;
16058}
16059
16060/*
Bram Moolenaar661b1822005-07-28 22:36:45 +000016061 * Get the lnum from the first argument.
16062 * Also accepts "$", then "buf" is used.
16063 * Returns 0 on error.
16064 */
16065 static linenr_T
16066get_tv_lnum_buf(argvars, buf)
16067 typval_T *argvars;
16068 buf_T *buf;
16069{
16070 if (argvars[0].v_type == VAR_STRING
16071 && argvars[0].vval.v_string != NULL
16072 && argvars[0].vval.v_string[0] == '$'
16073 && buf != NULL)
16074 return buf->b_ml.ml_line_count;
16075 return get_tv_number_chk(&argvars[0], NULL);
16076}
16077
16078/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000016079 * Get the string value of a variable.
16080 * If it is a Number variable, the number is converted into a string.
Bram Moolenaara7043832005-01-21 11:56:39 +000016081 * get_tv_string() uses a single, static buffer. YOU CAN ONLY USE IT ONCE!
16082 * get_tv_string_buf() uses a given buffer.
Bram Moolenaar071d4272004-06-13 20:20:40 +000016083 * If the String variable has never been set, return an empty string.
16084 * Never returns NULL;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000016085 * get_tv_string_chk() and get_tv_string_buf_chk() are similar, but return
16086 * NULL on error.
Bram Moolenaar071d4272004-06-13 20:20:40 +000016087 */
16088 static char_u *
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016089get_tv_string(varp)
Bram Moolenaar33570922005-01-25 22:26:29 +000016090 typval_T *varp;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016091{
16092 static char_u mybuf[NUMBUFLEN];
16093
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016094 return get_tv_string_buf(varp, mybuf);
Bram Moolenaar071d4272004-06-13 20:20:40 +000016095}
16096
16097 static char_u *
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016098get_tv_string_buf(varp, buf)
Bram Moolenaar33570922005-01-25 22:26:29 +000016099 typval_T *varp;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000016100 char_u *buf;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016101{
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000016102 char_u *res = get_tv_string_buf_chk(varp, buf);
16103
16104 return res != NULL ? res : (char_u *)"";
16105}
16106
Bram Moolenaar4be06f92005-07-29 22:36:03 +000016107 char_u *
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000016108get_tv_string_chk(varp)
16109 typval_T *varp;
16110{
16111 static char_u mybuf[NUMBUFLEN];
16112
16113 return get_tv_string_buf_chk(varp, mybuf);
16114}
16115
16116 static char_u *
16117get_tv_string_buf_chk(varp, buf)
16118 typval_T *varp;
16119 char_u *buf;
16120{
Bram Moolenaar49cd9572005-01-03 21:06:01 +000016121 switch (varp->v_type)
Bram Moolenaar071d4272004-06-13 20:20:40 +000016122 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +000016123 case VAR_NUMBER:
16124 sprintf((char *)buf, "%ld", (long)varp->vval.v_number);
16125 return buf;
16126 case VAR_FUNC:
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000016127 EMSG(_("E729: using Funcref as a String"));
Bram Moolenaar49cd9572005-01-03 21:06:01 +000016128 break;
16129 case VAR_LIST:
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000016130 EMSG(_("E730: using List as a String"));
Bram Moolenaar8c711452005-01-14 21:53:12 +000016131 break;
16132 case VAR_DICT:
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000016133 EMSG(_("E731: using Dictionary as a String"));
Bram Moolenaar49cd9572005-01-03 21:06:01 +000016134 break;
16135 case VAR_STRING:
16136 if (varp->vval.v_string != NULL)
16137 return varp->vval.v_string;
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000016138 return (char_u *)"";
Bram Moolenaar49cd9572005-01-03 21:06:01 +000016139 default:
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016140 EMSG2(_(e_intern2), "get_tv_string_buf()");
Bram Moolenaar49cd9572005-01-03 21:06:01 +000016141 break;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016142 }
Bram Moolenaar9ba0eb82005-06-13 22:28:56 +000016143 return NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016144}
16145
16146/*
16147 * Find variable "name" in the list of variables.
16148 * Return a pointer to it if found, NULL if not found.
Bram Moolenaar49cd9572005-01-03 21:06:01 +000016149 * Careful: "a:0" variables don't have a name.
Bram Moolenaara7043832005-01-21 11:56:39 +000016150 * When "htp" is not NULL we are writing to the variable, set "htp" to the
Bram Moolenaar33570922005-01-25 22:26:29 +000016151 * hashtab_T used.
Bram Moolenaar071d4272004-06-13 20:20:40 +000016152 */
Bram Moolenaar33570922005-01-25 22:26:29 +000016153 static dictitem_T *
Bram Moolenaara7043832005-01-21 11:56:39 +000016154find_var(name, htp)
Bram Moolenaar071d4272004-06-13 20:20:40 +000016155 char_u *name;
Bram Moolenaar33570922005-01-25 22:26:29 +000016156 hashtab_T **htp;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016157{
Bram Moolenaar071d4272004-06-13 20:20:40 +000016158 char_u *varname;
Bram Moolenaar33570922005-01-25 22:26:29 +000016159 hashtab_T *ht;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016160
Bram Moolenaara7043832005-01-21 11:56:39 +000016161 ht = find_var_ht(name, &varname);
16162 if (htp != NULL)
16163 *htp = ht;
16164 if (ht == NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000016165 return NULL;
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000016166 return find_var_in_ht(ht, varname, htp != NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +000016167}
16168
16169/*
Bram Moolenaar33570922005-01-25 22:26:29 +000016170 * Find variable "varname" in hashtab "ht".
Bram Moolenaara7043832005-01-21 11:56:39 +000016171 * Returns NULL if not found.
Bram Moolenaar071d4272004-06-13 20:20:40 +000016172 */
Bram Moolenaar33570922005-01-25 22:26:29 +000016173 static dictitem_T *
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000016174find_var_in_ht(ht, varname, writing)
Bram Moolenaar33570922005-01-25 22:26:29 +000016175 hashtab_T *ht;
Bram Moolenaara7043832005-01-21 11:56:39 +000016176 char_u *varname;
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000016177 int writing;
Bram Moolenaara7043832005-01-21 11:56:39 +000016178{
Bram Moolenaar33570922005-01-25 22:26:29 +000016179 hashitem_T *hi;
16180
16181 if (*varname == NUL)
16182 {
16183 /* Must be something like "s:", otherwise "ht" would be NULL. */
16184 switch (varname[-2])
16185 {
16186 case 's': return &SCRIPT_SV(current_SID).sv_var;
16187 case 'g': return &globvars_var;
16188 case 'v': return &vimvars_var;
16189 case 'b': return &curbuf->b_bufvar;
16190 case 'w': return &curwin->w_winvar;
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +000016191 case 'l': return current_funccal == NULL
16192 ? NULL : &current_funccal->l_vars_var;
16193 case 'a': return current_funccal == NULL
16194 ? NULL : &current_funccal->l_avars_var;
Bram Moolenaar33570922005-01-25 22:26:29 +000016195 }
16196 return NULL;
16197 }
Bram Moolenaara7043832005-01-21 11:56:39 +000016198
16199 hi = hash_find(ht, varname);
16200 if (HASHITEM_EMPTY(hi))
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000016201 {
16202 /* For global variables we may try auto-loading the script. If it
Bram Moolenaar87e25fd2005-07-27 21:13:01 +000016203 * worked find the variable again. Don't auto-load a script if it was
16204 * loaded already, otherwise it would be loaded every time when
16205 * checking if a function name is a Funcref variable. */
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000016206 if (ht == &globvarht && !writing
Bram Moolenaar87e25fd2005-07-27 21:13:01 +000016207 && script_autoload(varname, FALSE) && !aborting())
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000016208 hi = hash_find(ht, varname);
16209 if (HASHITEM_EMPTY(hi))
16210 return NULL;
16211 }
Bram Moolenaar33570922005-01-25 22:26:29 +000016212 return HI2DI(hi);
Bram Moolenaara7043832005-01-21 11:56:39 +000016213}
16214
16215/*
Bram Moolenaar33570922005-01-25 22:26:29 +000016216 * Find the hashtab used for a variable name.
Bram Moolenaara7043832005-01-21 11:56:39 +000016217 * Set "varname" to the start of name without ':'.
16218 */
Bram Moolenaar33570922005-01-25 22:26:29 +000016219 static hashtab_T *
Bram Moolenaara7043832005-01-21 11:56:39 +000016220find_var_ht(name, varname)
Bram Moolenaar071d4272004-06-13 20:20:40 +000016221 char_u *name;
16222 char_u **varname;
16223{
Bram Moolenaar75c50c42005-06-04 22:06:24 +000016224 hashitem_T *hi;
16225
Bram Moolenaar071d4272004-06-13 20:20:40 +000016226 if (name[1] != ':')
16227 {
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +000016228 /* The name must not start with a colon or #. */
16229 if (name[0] == ':' || name[0] == AUTOLOAD_CHAR)
Bram Moolenaar071d4272004-06-13 20:20:40 +000016230 return NULL;
16231 *varname = name;
Bram Moolenaar532c7802005-01-27 14:44:31 +000016232
16233 /* "version" is "v:version" in all scopes */
Bram Moolenaar75c50c42005-06-04 22:06:24 +000016234 hi = hash_find(&compat_hashtab, name);
16235 if (!HASHITEM_EMPTY(hi))
Bram Moolenaar532c7802005-01-27 14:44:31 +000016236 return &compat_hashtab;
16237
Bram Moolenaar071d4272004-06-13 20:20:40 +000016238 if (current_funccal == NULL)
Bram Moolenaar33570922005-01-25 22:26:29 +000016239 return &globvarht; /* global variable */
16240 return &current_funccal->l_vars.dv_hashtab; /* l: variable */
Bram Moolenaar071d4272004-06-13 20:20:40 +000016241 }
16242 *varname = name + 2;
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000016243 if (*name == 'g') /* global variable */
16244 return &globvarht;
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +000016245 /* There must be no ':' or '#' in the rest of the name, unless g: is used
16246 */
16247 if (vim_strchr(name + 2, ':') != NULL
16248 || vim_strchr(name + 2, AUTOLOAD_CHAR) != NULL)
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000016249 return NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016250 if (*name == 'b') /* buffer variable */
Bram Moolenaar33570922005-01-25 22:26:29 +000016251 return &curbuf->b_vars.dv_hashtab;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016252 if (*name == 'w') /* window variable */
Bram Moolenaar33570922005-01-25 22:26:29 +000016253 return &curwin->w_vars.dv_hashtab;
Bram Moolenaar33570922005-01-25 22:26:29 +000016254 if (*name == 'v') /* v: variable */
16255 return &vimvarht;
16256 if (*name == 'a' && current_funccal != NULL) /* function argument */
16257 return &current_funccal->l_avars.dv_hashtab;
16258 if (*name == 'l' && current_funccal != NULL) /* local function variable */
16259 return &current_funccal->l_vars.dv_hashtab;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016260 if (*name == 's' /* script variable */
16261 && current_SID > 0 && current_SID <= ga_scripts.ga_len)
16262 return &SCRIPT_VARS(current_SID);
16263 return NULL;
16264}
16265
16266/*
16267 * Get the string value of a (global/local) variable.
16268 * Returns NULL when it doesn't exist.
16269 */
16270 char_u *
16271get_var_value(name)
16272 char_u *name;
16273{
Bram Moolenaar33570922005-01-25 22:26:29 +000016274 dictitem_T *v;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016275
Bram Moolenaara7043832005-01-21 11:56:39 +000016276 v = find_var(name, NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +000016277 if (v == NULL)
16278 return NULL;
Bram Moolenaar33570922005-01-25 22:26:29 +000016279 return get_tv_string(&v->di_tv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000016280}
16281
16282/*
Bram Moolenaar33570922005-01-25 22:26:29 +000016283 * Allocate a new hashtab for a sourced script. It will be used while
Bram Moolenaar071d4272004-06-13 20:20:40 +000016284 * sourcing this script and when executing functions defined in the script.
16285 */
16286 void
16287new_script_vars(id)
16288 scid_T id;
16289{
Bram Moolenaara7043832005-01-21 11:56:39 +000016290 int i;
Bram Moolenaar33570922005-01-25 22:26:29 +000016291 hashtab_T *ht;
16292 scriptvar_T *sv;
Bram Moolenaara7043832005-01-21 11:56:39 +000016293
Bram Moolenaar071d4272004-06-13 20:20:40 +000016294 if (ga_grow(&ga_scripts, (int)(id - ga_scripts.ga_len)) == OK)
16295 {
Bram Moolenaara7043832005-01-21 11:56:39 +000016296 /* Re-allocating ga_data means that an ht_array pointing to
16297 * ht_smallarray becomes invalid. We can recognize this: ht_mask is
Bram Moolenaar33570922005-01-25 22:26:29 +000016298 * at its init value. Also reset "v_dict", it's always the same. */
Bram Moolenaara7043832005-01-21 11:56:39 +000016299 for (i = 1; i <= ga_scripts.ga_len; ++i)
16300 {
16301 ht = &SCRIPT_VARS(i);
16302 if (ht->ht_mask == HT_INIT_SIZE - 1)
16303 ht->ht_array = ht->ht_smallarray;
Bram Moolenaar33570922005-01-25 22:26:29 +000016304 sv = &SCRIPT_SV(i);
16305 sv->sv_var.di_tv.vval.v_dict = &sv->sv_dict;
Bram Moolenaara7043832005-01-21 11:56:39 +000016306 }
16307
Bram Moolenaar071d4272004-06-13 20:20:40 +000016308 while (ga_scripts.ga_len < id)
16309 {
Bram Moolenaar33570922005-01-25 22:26:29 +000016310 sv = &SCRIPT_SV(ga_scripts.ga_len + 1);
16311 init_var_dict(&sv->sv_dict, &sv->sv_var);
Bram Moolenaar071d4272004-06-13 20:20:40 +000016312 ++ga_scripts.ga_len;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016313 }
16314 }
16315}
16316
16317/*
Bram Moolenaar33570922005-01-25 22:26:29 +000016318 * Initialize dictionary "dict" as a scope and set variable "dict_var" to
16319 * point to it.
Bram Moolenaar071d4272004-06-13 20:20:40 +000016320 */
16321 void
Bram Moolenaar33570922005-01-25 22:26:29 +000016322init_var_dict(dict, dict_var)
16323 dict_T *dict;
16324 dictitem_T *dict_var;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016325{
Bram Moolenaar33570922005-01-25 22:26:29 +000016326 hash_init(&dict->dv_hashtab);
16327 dict->dv_refcount = 99999;
16328 dict_var->di_tv.vval.v_dict = dict;
16329 dict_var->di_tv.v_type = VAR_DICT;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000016330 dict_var->di_tv.v_lock = VAR_FIXED;
Bram Moolenaar33570922005-01-25 22:26:29 +000016331 dict_var->di_flags = DI_FLAGS_RO | DI_FLAGS_FIX;
16332 dict_var->di_key[0] = NUL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016333}
16334
16335/*
16336 * Clean up a list of internal variables.
Bram Moolenaar33570922005-01-25 22:26:29 +000016337 * Frees all allocated variables and the value they contain.
16338 * Clears hashtab "ht", does not free it.
Bram Moolenaar071d4272004-06-13 20:20:40 +000016339 */
16340 void
Bram Moolenaara7043832005-01-21 11:56:39 +000016341vars_clear(ht)
Bram Moolenaar33570922005-01-25 22:26:29 +000016342 hashtab_T *ht;
16343{
16344 vars_clear_ext(ht, TRUE);
16345}
16346
16347/*
16348 * Like vars_clear(), but only free the value if "free_val" is TRUE.
16349 */
16350 static void
16351vars_clear_ext(ht, free_val)
16352 hashtab_T *ht;
16353 int free_val;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016354{
Bram Moolenaara7043832005-01-21 11:56:39 +000016355 int todo;
Bram Moolenaar33570922005-01-25 22:26:29 +000016356 hashitem_T *hi;
16357 dictitem_T *v;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016358
Bram Moolenaar33570922005-01-25 22:26:29 +000016359 hash_lock(ht);
Bram Moolenaara7043832005-01-21 11:56:39 +000016360 todo = ht->ht_used;
16361 for (hi = ht->ht_array; todo > 0; ++hi)
16362 {
16363 if (!HASHITEM_EMPTY(hi))
16364 {
16365 --todo;
16366
Bram Moolenaar33570922005-01-25 22:26:29 +000016367 /* Free the variable. Don't remove it from the hashtab,
Bram Moolenaara7043832005-01-21 11:56:39 +000016368 * ht_array might change then. hash_clear() takes care of it
16369 * later. */
Bram Moolenaar33570922005-01-25 22:26:29 +000016370 v = HI2DI(hi);
16371 if (free_val)
16372 clear_tv(&v->di_tv);
16373 if ((v->di_flags & DI_FLAGS_FIX) == 0)
16374 vim_free(v);
Bram Moolenaara7043832005-01-21 11:56:39 +000016375 }
16376 }
16377 hash_clear(ht);
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +000016378 ht->ht_used = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016379}
16380
Bram Moolenaara7043832005-01-21 11:56:39 +000016381/*
Bram Moolenaar33570922005-01-25 22:26:29 +000016382 * Delete a variable from hashtab "ht" at item "hi".
16383 * Clear the variable value and free the dictitem.
Bram Moolenaara7043832005-01-21 11:56:39 +000016384 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000016385 static void
Bram Moolenaara7043832005-01-21 11:56:39 +000016386delete_var(ht, hi)
Bram Moolenaar33570922005-01-25 22:26:29 +000016387 hashtab_T *ht;
16388 hashitem_T *hi;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016389{
Bram Moolenaar33570922005-01-25 22:26:29 +000016390 dictitem_T *di = HI2DI(hi);
Bram Moolenaara7043832005-01-21 11:56:39 +000016391
16392 hash_remove(ht, hi);
Bram Moolenaar33570922005-01-25 22:26:29 +000016393 clear_tv(&di->di_tv);
16394 vim_free(di);
Bram Moolenaar071d4272004-06-13 20:20:40 +000016395}
16396
16397/*
16398 * List the value of one internal variable.
16399 */
16400 static void
16401list_one_var(v, prefix)
Bram Moolenaar33570922005-01-25 22:26:29 +000016402 dictitem_T *v;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016403 char_u *prefix;
16404{
Bram Moolenaar49cd9572005-01-03 21:06:01 +000016405 char_u *tofree;
16406 char_u *s;
Bram Moolenaar8a283e52005-01-06 23:28:25 +000016407 char_u numbuf[NUMBUFLEN];
Bram Moolenaar49cd9572005-01-03 21:06:01 +000016408
Bram Moolenaar33570922005-01-25 22:26:29 +000016409 s = echo_string(&v->di_tv, &tofree, numbuf);
16410 list_one_var_a(prefix, v->di_key, v->di_tv.v_type,
Bram Moolenaar49cd9572005-01-03 21:06:01 +000016411 s == NULL ? (char_u *)"" : s);
16412 vim_free(tofree);
Bram Moolenaar071d4272004-06-13 20:20:40 +000016413}
16414
Bram Moolenaar071d4272004-06-13 20:20:40 +000016415 static void
16416list_one_var_a(prefix, name, type, string)
16417 char_u *prefix;
16418 char_u *name;
16419 int type;
16420 char_u *string;
16421{
16422 msg_attr(prefix, 0); /* don't use msg(), it overwrites "v:statusmsg" */
16423 if (name != NULL) /* "a:" vars don't have a name stored */
16424 msg_puts(name);
16425 msg_putchar(' ');
16426 msg_advance(22);
16427 if (type == VAR_NUMBER)
16428 msg_putchar('#');
Bram Moolenaar49cd9572005-01-03 21:06:01 +000016429 else if (type == VAR_FUNC)
16430 msg_putchar('*');
16431 else if (type == VAR_LIST)
16432 {
16433 msg_putchar('[');
16434 if (*string == '[')
16435 ++string;
16436 }
Bram Moolenaar8c711452005-01-14 21:53:12 +000016437 else if (type == VAR_DICT)
16438 {
16439 msg_putchar('{');
16440 if (*string == '{')
16441 ++string;
16442 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000016443 else
16444 msg_putchar(' ');
Bram Moolenaar49cd9572005-01-03 21:06:01 +000016445
Bram Moolenaar071d4272004-06-13 20:20:40 +000016446 msg_outtrans(string);
Bram Moolenaar49cd9572005-01-03 21:06:01 +000016447
16448 if (type == VAR_FUNC)
16449 msg_puts((char_u *)"()");
Bram Moolenaar071d4272004-06-13 20:20:40 +000016450}
16451
16452/*
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016453 * Set variable "name" to value in "tv".
Bram Moolenaar071d4272004-06-13 20:20:40 +000016454 * If the variable already exists, the value is updated.
16455 * Otherwise the variable is created.
16456 */
16457 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016458set_var(name, tv, copy)
Bram Moolenaar071d4272004-06-13 20:20:40 +000016459 char_u *name;
Bram Moolenaar33570922005-01-25 22:26:29 +000016460 typval_T *tv;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016461 int copy; /* make copy of value in "tv" */
Bram Moolenaar071d4272004-06-13 20:20:40 +000016462{
Bram Moolenaar33570922005-01-25 22:26:29 +000016463 dictitem_T *v;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016464 char_u *varname;
Bram Moolenaar33570922005-01-25 22:26:29 +000016465 hashtab_T *ht;
Bram Moolenaar92124a32005-06-17 22:03:40 +000016466 char_u *p;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016467
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016468 if (tv->v_type == VAR_FUNC)
Bram Moolenaar49cd9572005-01-03 21:06:01 +000016469 {
16470 if (!(vim_strchr((char_u *)"wbs", name[0]) != NULL && name[1] == ':')
16471 && !ASCII_ISUPPER((name[0] != NUL && name[1] == ':')
16472 ? name[2] : name[0]))
16473 {
Bram Moolenaare49b69a2005-01-08 16:11:57 +000016474 EMSG2(_("E704: Funcref variable name must start with a capital: %s"), name);
Bram Moolenaar49cd9572005-01-03 21:06:01 +000016475 return;
16476 }
16477 if (function_exists(name))
16478 {
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +000016479 EMSG2(_("E705: Variable name conflicts with existing function: %s"),
Bram Moolenaar81bf7082005-02-12 14:31:42 +000016480 name);
Bram Moolenaar49cd9572005-01-03 21:06:01 +000016481 return;
16482 }
16483 }
16484
Bram Moolenaara7043832005-01-21 11:56:39 +000016485 ht = find_var_ht(name, &varname);
Bram Moolenaar33570922005-01-25 22:26:29 +000016486 if (ht == NULL || *varname == NUL)
Bram Moolenaara7043832005-01-21 11:56:39 +000016487 {
Bram Moolenaar92124a32005-06-17 22:03:40 +000016488 EMSG2(_(e_illvar), name);
Bram Moolenaara7043832005-01-21 11:56:39 +000016489 return;
16490 }
16491
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000016492 v = find_var_in_ht(ht, varname, TRUE);
Bram Moolenaar33570922005-01-25 22:26:29 +000016493 if (v != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000016494 {
Bram Moolenaar33570922005-01-25 22:26:29 +000016495 /* existing variable, need to clear the value */
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000016496 if (var_check_ro(v->di_flags, name)
16497 || tv_check_lock(v->di_tv.v_lock, name))
Bram Moolenaar33570922005-01-25 22:26:29 +000016498 return;
16499 if (v->di_tv.v_type != tv->v_type
16500 && !((v->di_tv.v_type == VAR_STRING
16501 || v->di_tv.v_type == VAR_NUMBER)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016502 && (tv->v_type == VAR_STRING
16503 || tv->v_type == VAR_NUMBER)))
Bram Moolenaar49cd9572005-01-03 21:06:01 +000016504 {
Bram Moolenaare49b69a2005-01-08 16:11:57 +000016505 EMSG2(_("E706: Variable type mismatch for: %s"), name);
Bram Moolenaar49cd9572005-01-03 21:06:01 +000016506 return;
16507 }
Bram Moolenaar33570922005-01-25 22:26:29 +000016508
16509 /*
Bram Moolenaar758711c2005-02-02 23:11:38 +000016510 * Handle setting internal v: variables separately: we don't change
16511 * the type.
Bram Moolenaar33570922005-01-25 22:26:29 +000016512 */
16513 if (ht == &vimvarht)
16514 {
16515 if (v->di_tv.v_type == VAR_STRING)
16516 {
16517 vim_free(v->di_tv.vval.v_string);
16518 if (copy || tv->v_type != VAR_STRING)
16519 v->di_tv.vval.v_string = vim_strsave(get_tv_string(tv));
16520 else
16521 {
16522 /* Take over the string to avoid an extra alloc/free. */
16523 v->di_tv.vval.v_string = tv->vval.v_string;
16524 tv->vval.v_string = NULL;
16525 }
16526 }
16527 else if (v->di_tv.v_type != VAR_NUMBER)
16528 EMSG2(_(e_intern2), "set_var()");
16529 else
16530 v->di_tv.vval.v_number = get_tv_number(tv);
16531 return;
16532 }
16533
16534 clear_tv(&v->di_tv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000016535 }
16536 else /* add a new variable */
16537 {
Bram Moolenaar92124a32005-06-17 22:03:40 +000016538 /* Make sure the variable name is valid. */
16539 for (p = varname; *p != NUL; ++p)
Bram Moolenaara5792f52005-11-23 21:25:05 +000016540 if (!eval_isnamec1(*p) && (p == varname || !VIM_ISDIGIT(*p))
16541 && *p != AUTOLOAD_CHAR)
Bram Moolenaar92124a32005-06-17 22:03:40 +000016542 {
16543 EMSG2(_(e_illvar), varname);
16544 return;
16545 }
16546
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000016547 v = (dictitem_T *)alloc((unsigned)(sizeof(dictitem_T)
16548 + STRLEN(varname)));
Bram Moolenaara7043832005-01-21 11:56:39 +000016549 if (v == NULL)
16550 return;
Bram Moolenaar33570922005-01-25 22:26:29 +000016551 STRCPY(v->di_key, varname);
Bram Moolenaar33570922005-01-25 22:26:29 +000016552 if (hash_add(ht, DI2HIKEY(v)) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000016553 {
Bram Moolenaara7043832005-01-21 11:56:39 +000016554 vim_free(v);
Bram Moolenaar071d4272004-06-13 20:20:40 +000016555 return;
16556 }
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000016557 v->di_flags = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016558 }
Bram Moolenaara7043832005-01-21 11:56:39 +000016559
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016560 if (copy || tv->v_type == VAR_NUMBER)
Bram Moolenaar33570922005-01-25 22:26:29 +000016561 copy_tv(tv, &v->di_tv);
Bram Moolenaar1c2fda22005-01-02 11:43:19 +000016562 else
16563 {
Bram Moolenaar33570922005-01-25 22:26:29 +000016564 v->di_tv = *tv;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000016565 v->di_tv.v_lock = 0;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016566 init_tv(tv);
Bram Moolenaar1c2fda22005-01-02 11:43:19 +000016567 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000016568}
16569
Bram Moolenaar49cd9572005-01-03 21:06:01 +000016570/*
Bram Moolenaar33570922005-01-25 22:26:29 +000016571 * Return TRUE if di_flags "flags" indicate read-only variable "name".
16572 * Also give an error message.
16573 */
16574 static int
16575var_check_ro(flags, name)
16576 int flags;
16577 char_u *name;
16578{
16579 if (flags & DI_FLAGS_RO)
16580 {
16581 EMSG2(_(e_readonlyvar), name);
16582 return TRUE;
16583 }
16584 if ((flags & DI_FLAGS_RO_SBX) && sandbox)
16585 {
16586 EMSG2(_(e_readonlysbx), name);
16587 return TRUE;
16588 }
16589 return FALSE;
16590}
16591
16592/*
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000016593 * Return TRUE if typeval "tv" is set to be locked (immutable).
16594 * Also give an error message, using "name".
16595 */
16596 static int
16597tv_check_lock(lock, name)
16598 int lock;
16599 char_u *name;
16600{
16601 if (lock & VAR_LOCKED)
16602 {
16603 EMSG2(_("E741: Value is locked: %s"),
16604 name == NULL ? (char_u *)_("Unknown") : name);
16605 return TRUE;
16606 }
16607 if (lock & VAR_FIXED)
16608 {
16609 EMSG2(_("E742: Cannot change value of %s"),
16610 name == NULL ? (char_u *)_("Unknown") : name);
16611 return TRUE;
16612 }
16613 return FALSE;
16614}
16615
16616/*
Bram Moolenaar33570922005-01-25 22:26:29 +000016617 * Copy the values from typval_T "from" to typval_T "to".
Bram Moolenaar49cd9572005-01-03 21:06:01 +000016618 * When needed allocates string or increases reference count.
Bram Moolenaare9a41262005-01-15 22:18:47 +000016619 * Does not make a copy of a list or dict but copies the reference!
Bram Moolenaar49cd9572005-01-03 21:06:01 +000016620 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000016621 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016622copy_tv(from, to)
Bram Moolenaar33570922005-01-25 22:26:29 +000016623 typval_T *from;
16624 typval_T *to;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016625{
Bram Moolenaar49cd9572005-01-03 21:06:01 +000016626 to->v_type = from->v_type;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000016627 to->v_lock = 0;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000016628 switch (from->v_type)
16629 {
16630 case VAR_NUMBER:
16631 to->vval.v_number = from->vval.v_number;
16632 break;
16633 case VAR_STRING:
16634 case VAR_FUNC:
16635 if (from->vval.v_string == NULL)
16636 to->vval.v_string = NULL;
16637 else
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000016638 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +000016639 to->vval.v_string = vim_strsave(from->vval.v_string);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000016640 if (from->v_type == VAR_FUNC)
16641 func_ref(to->vval.v_string);
16642 }
Bram Moolenaar49cd9572005-01-03 21:06:01 +000016643 break;
16644 case VAR_LIST:
16645 if (from->vval.v_list == NULL)
16646 to->vval.v_list = NULL;
16647 else
16648 {
16649 to->vval.v_list = from->vval.v_list;
16650 ++to->vval.v_list->lv_refcount;
16651 }
16652 break;
Bram Moolenaar8c711452005-01-14 21:53:12 +000016653 case VAR_DICT:
16654 if (from->vval.v_dict == NULL)
16655 to->vval.v_dict = NULL;
16656 else
16657 {
16658 to->vval.v_dict = from->vval.v_dict;
16659 ++to->vval.v_dict->dv_refcount;
16660 }
16661 break;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000016662 default:
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016663 EMSG2(_(e_intern2), "copy_tv()");
Bram Moolenaar49cd9572005-01-03 21:06:01 +000016664 break;
16665 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000016666}
16667
16668/*
Bram Moolenaare9a41262005-01-15 22:18:47 +000016669 * Make a copy of an item.
16670 * Lists and Dictionaries are also copied. A deep copy if "deep" is set.
Bram Moolenaar81bf7082005-02-12 14:31:42 +000016671 * For deepcopy() "copyID" is zero for a full copy or the ID for when a
16672 * reference to an already copied list/dict can be used.
16673 * Returns FAIL or OK.
Bram Moolenaare9a41262005-01-15 22:18:47 +000016674 */
Bram Moolenaar81bf7082005-02-12 14:31:42 +000016675 static int
16676item_copy(from, to, deep, copyID)
Bram Moolenaar33570922005-01-25 22:26:29 +000016677 typval_T *from;
16678 typval_T *to;
Bram Moolenaare9a41262005-01-15 22:18:47 +000016679 int deep;
Bram Moolenaar81bf7082005-02-12 14:31:42 +000016680 int copyID;
Bram Moolenaare9a41262005-01-15 22:18:47 +000016681{
16682 static int recurse = 0;
Bram Moolenaar81bf7082005-02-12 14:31:42 +000016683 int ret = OK;
Bram Moolenaare9a41262005-01-15 22:18:47 +000016684
Bram Moolenaar33570922005-01-25 22:26:29 +000016685 if (recurse >= DICT_MAXNEST)
Bram Moolenaare9a41262005-01-15 22:18:47 +000016686 {
16687 EMSG(_("E698: variable nested too deep for making a copy"));
Bram Moolenaar81bf7082005-02-12 14:31:42 +000016688 return FAIL;
Bram Moolenaare9a41262005-01-15 22:18:47 +000016689 }
16690 ++recurse;
16691
16692 switch (from->v_type)
16693 {
16694 case VAR_NUMBER:
16695 case VAR_STRING:
16696 case VAR_FUNC:
16697 copy_tv(from, to);
16698 break;
16699 case VAR_LIST:
16700 to->v_type = VAR_LIST;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000016701 to->v_lock = 0;
Bram Moolenaar81bf7082005-02-12 14:31:42 +000016702 if (from->vval.v_list == NULL)
16703 to->vval.v_list = NULL;
16704 else if (copyID != 0 && from->vval.v_list->lv_copyID == copyID)
16705 {
16706 /* use the copy made earlier */
16707 to->vval.v_list = from->vval.v_list->lv_copylist;
16708 ++to->vval.v_list->lv_refcount;
16709 }
16710 else
16711 to->vval.v_list = list_copy(from->vval.v_list, deep, copyID);
16712 if (to->vval.v_list == NULL)
16713 ret = FAIL;
Bram Moolenaare9a41262005-01-15 22:18:47 +000016714 break;
16715 case VAR_DICT:
16716 to->v_type = VAR_DICT;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000016717 to->v_lock = 0;
Bram Moolenaar81bf7082005-02-12 14:31:42 +000016718 if (from->vval.v_dict == NULL)
16719 to->vval.v_dict = NULL;
16720 else if (copyID != 0 && from->vval.v_dict->dv_copyID == copyID)
16721 {
16722 /* use the copy made earlier */
16723 to->vval.v_dict = from->vval.v_dict->dv_copydict;
16724 ++to->vval.v_dict->dv_refcount;
16725 }
16726 else
16727 to->vval.v_dict = dict_copy(from->vval.v_dict, deep, copyID);
16728 if (to->vval.v_dict == NULL)
16729 ret = FAIL;
Bram Moolenaare9a41262005-01-15 22:18:47 +000016730 break;
16731 default:
16732 EMSG2(_(e_intern2), "item_copy()");
Bram Moolenaar81bf7082005-02-12 14:31:42 +000016733 ret = FAIL;
Bram Moolenaare9a41262005-01-15 22:18:47 +000016734 }
16735 --recurse;
Bram Moolenaar81bf7082005-02-12 14:31:42 +000016736 return ret;
Bram Moolenaare9a41262005-01-15 22:18:47 +000016737}
16738
16739/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000016740 * ":echo expr1 ..." print each argument separated with a space, add a
16741 * newline at the end.
16742 * ":echon expr1 ..." print each argument plain.
16743 */
16744 void
16745ex_echo(eap)
16746 exarg_T *eap;
16747{
16748 char_u *arg = eap->arg;
Bram Moolenaar33570922005-01-25 22:26:29 +000016749 typval_T rettv;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000016750 char_u *tofree;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016751 char_u *p;
16752 int needclr = TRUE;
16753 int atstart = TRUE;
Bram Moolenaar8a283e52005-01-06 23:28:25 +000016754 char_u numbuf[NUMBUFLEN];
Bram Moolenaar071d4272004-06-13 20:20:40 +000016755
16756 if (eap->skip)
16757 ++emsg_skip;
16758 while (*arg != NUL && *arg != '|' && *arg != '\n' && !got_int)
16759 {
16760 p = arg;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016761 if (eval1(&arg, &rettv, !eap->skip) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000016762 {
16763 /*
16764 * Report the invalid expression unless the expression evaluation
16765 * has been cancelled due to an aborting error, an interrupt, or an
16766 * exception.
16767 */
16768 if (!aborting())
16769 EMSG2(_(e_invexpr2), p);
16770 break;
16771 }
16772 if (!eap->skip)
16773 {
16774 if (atstart)
16775 {
16776 atstart = FALSE;
16777 /* Call msg_start() after eval1(), evaluating the expression
16778 * may cause a message to appear. */
16779 if (eap->cmdidx == CMD_echo)
16780 msg_start();
16781 }
16782 else if (eap->cmdidx == CMD_echo)
16783 msg_puts_attr((char_u *)" ", echo_attr);
Bram Moolenaar81bf7082005-02-12 14:31:42 +000016784 p = echo_string(&rettv, &tofree, numbuf);
16785 if (p != NULL)
16786 for ( ; *p != NUL && !got_int; ++p)
Bram Moolenaar071d4272004-06-13 20:20:40 +000016787 {
Bram Moolenaar81bf7082005-02-12 14:31:42 +000016788 if (*p == '\n' || *p == '\r' || *p == TAB)
Bram Moolenaar071d4272004-06-13 20:20:40 +000016789 {
Bram Moolenaar81bf7082005-02-12 14:31:42 +000016790 if (*p != TAB && needclr)
16791 {
16792 /* remove any text still there from the command */
16793 msg_clr_eos();
16794 needclr = FALSE;
16795 }
16796 msg_putchar_attr(*p, echo_attr);
Bram Moolenaar071d4272004-06-13 20:20:40 +000016797 }
16798 else
Bram Moolenaar81bf7082005-02-12 14:31:42 +000016799 {
16800#ifdef FEAT_MBYTE
16801 if (has_mbyte)
16802 {
Bram Moolenaar0fa313a2005-08-10 21:07:57 +000016803 int i = (*mb_ptr2len)(p);
Bram Moolenaar81bf7082005-02-12 14:31:42 +000016804
16805 (void)msg_outtrans_len_attr(p, i, echo_attr);
16806 p += i - 1;
16807 }
16808 else
Bram Moolenaar071d4272004-06-13 20:20:40 +000016809#endif
Bram Moolenaar81bf7082005-02-12 14:31:42 +000016810 (void)msg_outtrans_len_attr(p, 1, echo_attr);
16811 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000016812 }
Bram Moolenaar49cd9572005-01-03 21:06:01 +000016813 vim_free(tofree);
Bram Moolenaar071d4272004-06-13 20:20:40 +000016814 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016815 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000016816 arg = skipwhite(arg);
16817 }
16818 eap->nextcmd = check_nextcmd(arg);
16819
16820 if (eap->skip)
16821 --emsg_skip;
16822 else
16823 {
16824 /* remove text that may still be there from the command */
16825 if (needclr)
16826 msg_clr_eos();
16827 if (eap->cmdidx == CMD_echo)
16828 msg_end();
16829 }
16830}
16831
16832/*
16833 * ":echohl {name}".
16834 */
16835 void
16836ex_echohl(eap)
16837 exarg_T *eap;
16838{
16839 int id;
16840
16841 id = syn_name2id(eap->arg);
16842 if (id == 0)
16843 echo_attr = 0;
16844 else
16845 echo_attr = syn_id2attr(id);
16846}
16847
16848/*
16849 * ":execute expr1 ..." execute the result of an expression.
16850 * ":echomsg expr1 ..." Print a message
16851 * ":echoerr expr1 ..." Print an error
16852 * Each gets spaces around each argument and a newline at the end for
16853 * echo commands
16854 */
16855 void
16856ex_execute(eap)
16857 exarg_T *eap;
16858{
16859 char_u *arg = eap->arg;
Bram Moolenaar33570922005-01-25 22:26:29 +000016860 typval_T rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016861 int ret = OK;
16862 char_u *p;
16863 garray_T ga;
16864 int len;
16865 int save_did_emsg;
16866
16867 ga_init2(&ga, 1, 80);
16868
16869 if (eap->skip)
16870 ++emsg_skip;
16871 while (*arg != NUL && *arg != '|' && *arg != '\n')
16872 {
16873 p = arg;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016874 if (eval1(&arg, &rettv, !eap->skip) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000016875 {
16876 /*
16877 * Report the invalid expression unless the expression evaluation
16878 * has been cancelled due to an aborting error, an interrupt, or an
16879 * exception.
16880 */
16881 if (!aborting())
16882 EMSG2(_(e_invexpr2), p);
16883 ret = FAIL;
16884 break;
16885 }
16886
16887 if (!eap->skip)
16888 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016889 p = get_tv_string(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000016890 len = (int)STRLEN(p);
16891 if (ga_grow(&ga, len + 2) == FAIL)
16892 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016893 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000016894 ret = FAIL;
16895 break;
16896 }
16897 if (ga.ga_len)
Bram Moolenaar071d4272004-06-13 20:20:40 +000016898 ((char_u *)(ga.ga_data))[ga.ga_len++] = ' ';
Bram Moolenaar071d4272004-06-13 20:20:40 +000016899 STRCPY((char_u *)(ga.ga_data) + ga.ga_len, p);
Bram Moolenaar071d4272004-06-13 20:20:40 +000016900 ga.ga_len += len;
16901 }
16902
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016903 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000016904 arg = skipwhite(arg);
16905 }
16906
16907 if (ret != FAIL && ga.ga_data != NULL)
16908 {
16909 if (eap->cmdidx == CMD_echomsg)
16910 MSG_ATTR(ga.ga_data, echo_attr);
16911 else if (eap->cmdidx == CMD_echoerr)
16912 {
16913 /* We don't want to abort following commands, restore did_emsg. */
16914 save_did_emsg = did_emsg;
16915 EMSG((char_u *)ga.ga_data);
16916 if (!force_abort)
16917 did_emsg = save_did_emsg;
16918 }
16919 else if (eap->cmdidx == CMD_execute)
16920 do_cmdline((char_u *)ga.ga_data,
16921 eap->getline, eap->cookie, DOCMD_NOWAIT|DOCMD_VERBOSE);
16922 }
16923
16924 ga_clear(&ga);
16925
16926 if (eap->skip)
16927 --emsg_skip;
16928
16929 eap->nextcmd = check_nextcmd(arg);
16930}
16931
16932/*
16933 * Skip over the name of an option: "&option", "&g:option" or "&l:option".
16934 * "arg" points to the "&" or '+' when called, to "option" when returning.
16935 * Returns NULL when no option name found. Otherwise pointer to the char
16936 * after the option name.
16937 */
16938 static char_u *
16939find_option_end(arg, opt_flags)
16940 char_u **arg;
16941 int *opt_flags;
16942{
16943 char_u *p = *arg;
16944
16945 ++p;
16946 if (*p == 'g' && p[1] == ':')
16947 {
16948 *opt_flags = OPT_GLOBAL;
16949 p += 2;
16950 }
16951 else if (*p == 'l' && p[1] == ':')
16952 {
16953 *opt_flags = OPT_LOCAL;
16954 p += 2;
16955 }
16956 else
16957 *opt_flags = 0;
16958
16959 if (!ASCII_ISALPHA(*p))
16960 return NULL;
16961 *arg = p;
16962
16963 if (p[0] == 't' && p[1] == '_' && p[2] != NUL && p[3] != NUL)
16964 p += 4; /* termcap option */
16965 else
16966 while (ASCII_ISALPHA(*p))
16967 ++p;
16968 return p;
16969}
16970
16971/*
16972 * ":function"
16973 */
16974 void
16975ex_function(eap)
16976 exarg_T *eap;
16977{
16978 char_u *theline;
16979 int j;
16980 int c;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016981 int saved_did_emsg;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016982 char_u *name = NULL;
16983 char_u *p;
16984 char_u *arg;
16985 garray_T newargs;
16986 garray_T newlines;
16987 int varargs = FALSE;
16988 int mustend = FALSE;
16989 int flags = 0;
16990 ufunc_T *fp;
16991 int indent;
16992 int nesting;
16993 char_u *skip_until = NULL;
Bram Moolenaar33570922005-01-25 22:26:29 +000016994 dictitem_T *v;
16995 funcdict_T fudi;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000016996 static int func_nr = 0; /* number for nameless function */
16997 int paren;
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000016998 hashtab_T *ht;
16999 int todo;
17000 hashitem_T *hi;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017001
17002 /*
17003 * ":function" without argument: list functions.
17004 */
17005 if (ends_excmd(*eap->arg))
17006 {
17007 if (!eap->skip)
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000017008 {
Bram Moolenaar038eb0e2005-02-27 22:43:26 +000017009 todo = func_hashtab.ht_used;
17010 for (hi = func_hashtab.ht_array; todo > 0 && !got_int; ++hi)
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000017011 {
17012 if (!HASHITEM_EMPTY(hi))
17013 {
17014 --todo;
17015 fp = HI2UF(hi);
17016 if (!isdigit(*fp->uf_name))
17017 list_func_head(fp, FALSE);
17018 }
17019 }
17020 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000017021 eap->nextcmd = check_nextcmd(eap->arg);
17022 return;
17023 }
17024
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000017025 /*
Bram Moolenaardd2436f2005-09-05 22:14:46 +000017026 * ":function /pat": list functions matching pattern.
17027 */
17028 if (*eap->arg == '/')
17029 {
17030 p = skip_regexp(eap->arg + 1, '/', TRUE, NULL);
17031 if (!eap->skip)
17032 {
17033 regmatch_T regmatch;
17034
17035 c = *p;
17036 *p = NUL;
17037 regmatch.regprog = vim_regcomp(eap->arg + 1, RE_MAGIC);
17038 *p = c;
17039 if (regmatch.regprog != NULL)
17040 {
17041 regmatch.rm_ic = p_ic;
17042
17043 todo = func_hashtab.ht_used;
17044 for (hi = func_hashtab.ht_array; todo > 0 && !got_int; ++hi)
17045 {
17046 if (!HASHITEM_EMPTY(hi))
17047 {
17048 --todo;
17049 fp = HI2UF(hi);
17050 if (!isdigit(*fp->uf_name)
17051 && vim_regexec(&regmatch, fp->uf_name, 0))
17052 list_func_head(fp, FALSE);
17053 }
17054 }
17055 }
17056 }
17057 if (*p == '/')
17058 ++p;
17059 eap->nextcmd = check_nextcmd(p);
17060 return;
17061 }
17062
17063 /*
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000017064 * Get the function name. There are these situations:
17065 * func normal function name
17066 * "name" == func, "fudi.fd_dict" == NULL
17067 * dict.func new dictionary entry
17068 * "name" == NULL, "fudi.fd_dict" set,
17069 * "fudi.fd_di" == NULL, "fudi.fd_newkey" == func
17070 * dict.func existing dict entry with a Funcref
Bram Moolenaard857f0e2005-06-21 22:37:39 +000017071 * "name" == func, "fudi.fd_dict" set,
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000017072 * "fudi.fd_di" set, "fudi.fd_newkey" == NULL
17073 * dict.func existing dict entry that's not a Funcref
17074 * "name" == NULL, "fudi.fd_dict" set,
17075 * "fudi.fd_di" set, "fudi.fd_newkey" == NULL
17076 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000017077 p = eap->arg;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000017078 name = trans_function_name(&p, eap->skip, 0, &fudi);
17079 paren = (vim_strchr(p, '(') != NULL);
17080 if (name == NULL && (fudi.fd_dict == NULL || !paren) && !eap->skip)
Bram Moolenaar071d4272004-06-13 20:20:40 +000017081 {
17082 /*
17083 * Return on an invalid expression in braces, unless the expression
17084 * evaluation has been cancelled due to an aborting error, an
17085 * interrupt, or an exception.
17086 */
17087 if (!aborting())
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000017088 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000017089 if (!eap->skip && fudi.fd_newkey != NULL)
17090 EMSG2(_(e_dictkey), fudi.fd_newkey);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000017091 vim_free(fudi.fd_newkey);
Bram Moolenaar071d4272004-06-13 20:20:40 +000017092 return;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000017093 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000017094 else
17095 eap->skip = TRUE;
17096 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000017097 /* An error in a function call during evaluation of an expression in magic
17098 * braces should not cause the function not to be defined. */
17099 saved_did_emsg = did_emsg;
17100 did_emsg = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017101
17102 /*
17103 * ":function func" with only function name: list function.
17104 */
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000017105 if (!paren)
Bram Moolenaar071d4272004-06-13 20:20:40 +000017106 {
17107 if (!ends_excmd(*skipwhite(p)))
17108 {
17109 EMSG(_(e_trailing));
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000017110 goto ret_free;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017111 }
17112 eap->nextcmd = check_nextcmd(p);
17113 if (eap->nextcmd != NULL)
17114 *p = NUL;
17115 if (!eap->skip && !got_int)
17116 {
17117 fp = find_func(name);
17118 if (fp != NULL)
17119 {
17120 list_func_head(fp, TRUE);
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000017121 for (j = 0; j < fp->uf_lines.ga_len && !got_int; ++j)
Bram Moolenaar071d4272004-06-13 20:20:40 +000017122 {
17123 msg_putchar('\n');
17124 msg_outnum((long)(j + 1));
17125 if (j < 9)
17126 msg_putchar(' ');
17127 if (j < 99)
17128 msg_putchar(' ');
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000017129 msg_prt_line(FUNCLINE(fp, j), FALSE);
Bram Moolenaar071d4272004-06-13 20:20:40 +000017130 out_flush(); /* show a line at a time */
17131 ui_breakcheck();
17132 }
17133 if (!got_int)
17134 {
17135 msg_putchar('\n');
17136 msg_puts((char_u *)" endfunction");
17137 }
17138 }
17139 else
Bram Moolenaar81bf7082005-02-12 14:31:42 +000017140 emsg_funcname("E123: Undefined function: %s", name);
Bram Moolenaar071d4272004-06-13 20:20:40 +000017141 }
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000017142 goto ret_free;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017143 }
17144
17145 /*
17146 * ":function name(arg1, arg2)" Define function.
17147 */
17148 p = skipwhite(p);
17149 if (*p != '(')
17150 {
17151 if (!eap->skip)
17152 {
17153 EMSG2(_("E124: Missing '(': %s"), eap->arg);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000017154 goto ret_free;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017155 }
17156 /* attempt to continue by skipping some text */
17157 if (vim_strchr(p, '(') != NULL)
17158 p = vim_strchr(p, '(');
17159 }
17160 p = skipwhite(p + 1);
17161
17162 ga_init2(&newargs, (int)sizeof(char_u *), 3);
17163 ga_init2(&newlines, (int)sizeof(char_u *), 3);
17164
Bram Moolenaard857f0e2005-06-21 22:37:39 +000017165 if (!eap->skip)
17166 {
17167 /* Check the name of the function. */
17168 if (name != NULL)
17169 arg = name;
17170 else
17171 arg = fudi.fd_newkey;
17172 if (arg != NULL)
17173 {
17174 if (*arg == K_SPECIAL)
17175 j = 3;
17176 else
17177 j = 0;
17178 while (arg[j] != NUL && (j == 0 ? eval_isnamec1(arg[j])
17179 : eval_isnamec(arg[j])))
17180 ++j;
17181 if (arg[j] != NUL)
17182 emsg_funcname(_(e_invarg2), arg);
17183 }
17184 }
17185
Bram Moolenaar071d4272004-06-13 20:20:40 +000017186 /*
17187 * Isolate the arguments: "arg1, arg2, ...)"
17188 */
17189 while (*p != ')')
17190 {
17191 if (p[0] == '.' && p[1] == '.' && p[2] == '.')
17192 {
17193 varargs = TRUE;
17194 p += 3;
17195 mustend = TRUE;
17196 }
17197 else
17198 {
17199 arg = p;
17200 while (ASCII_ISALNUM(*p) || *p == '_')
17201 ++p;
17202 if (arg == p || isdigit(*arg)
17203 || (p - arg == 9 && STRNCMP(arg, "firstline", 9) == 0)
17204 || (p - arg == 8 && STRNCMP(arg, "lastline", 8) == 0))
17205 {
17206 if (!eap->skip)
17207 EMSG2(_("E125: Illegal argument: %s"), arg);
17208 break;
17209 }
17210 if (ga_grow(&newargs, 1) == FAIL)
17211 goto erret;
17212 c = *p;
17213 *p = NUL;
17214 arg = vim_strsave(arg);
17215 if (arg == NULL)
17216 goto erret;
17217 ((char_u **)(newargs.ga_data))[newargs.ga_len] = arg;
17218 *p = c;
17219 newargs.ga_len++;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017220 if (*p == ',')
17221 ++p;
17222 else
17223 mustend = TRUE;
17224 }
17225 p = skipwhite(p);
17226 if (mustend && *p != ')')
17227 {
17228 if (!eap->skip)
17229 EMSG2(_(e_invarg2), eap->arg);
17230 break;
17231 }
17232 }
17233 ++p; /* skip the ')' */
17234
Bram Moolenaare9a41262005-01-15 22:18:47 +000017235 /* find extra arguments "range", "dict" and "abort" */
Bram Moolenaar071d4272004-06-13 20:20:40 +000017236 for (;;)
17237 {
17238 p = skipwhite(p);
17239 if (STRNCMP(p, "range", 5) == 0)
17240 {
17241 flags |= FC_RANGE;
17242 p += 5;
17243 }
Bram Moolenaare9a41262005-01-15 22:18:47 +000017244 else if (STRNCMP(p, "dict", 4) == 0)
17245 {
17246 flags |= FC_DICT;
17247 p += 4;
17248 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000017249 else if (STRNCMP(p, "abort", 5) == 0)
17250 {
17251 flags |= FC_ABORT;
17252 p += 5;
17253 }
17254 else
17255 break;
17256 }
17257
17258 if (*p != NUL && *p != '"' && *p != '\n' && !eap->skip && !did_emsg)
17259 EMSG(_(e_trailing));
17260
17261 /*
17262 * Read the body of the function, until ":endfunction" is found.
17263 */
17264 if (KeyTyped)
17265 {
17266 /* Check if the function already exists, don't let the user type the
17267 * whole function before telling him it doesn't work! For a script we
17268 * need to skip the body to be able to find what follows. */
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000017269 if (!eap->skip && !eap->forceit)
17270 {
17271 if (fudi.fd_dict != NULL && fudi.fd_newkey == NULL)
17272 EMSG(_(e_funcdict));
17273 else if (name != NULL && find_func(name) != NULL)
Bram Moolenaar81bf7082005-02-12 14:31:42 +000017274 emsg_funcname(e_funcexts, name);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000017275 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000017276
Bram Moolenaard857f0e2005-06-21 22:37:39 +000017277 if (!eap->skip && did_emsg)
17278 goto erret;
17279
Bram Moolenaar071d4272004-06-13 20:20:40 +000017280 msg_putchar('\n'); /* don't overwrite the function name */
17281 cmdline_row = msg_row;
17282 }
17283
17284 indent = 2;
17285 nesting = 0;
17286 for (;;)
17287 {
17288 msg_scroll = TRUE;
17289 need_wait_return = FALSE;
17290 if (eap->getline == NULL)
17291 theline = getcmdline(':', 0L, indent);
17292 else
17293 theline = eap->getline(':', eap->cookie, indent);
17294 if (KeyTyped)
17295 lines_left = Rows - 1;
17296 if (theline == NULL)
17297 {
17298 EMSG(_("E126: Missing :endfunction"));
17299 goto erret;
17300 }
17301
17302 if (skip_until != NULL)
17303 {
17304 /* between ":append" and "." and between ":python <<EOF" and "EOF"
17305 * don't check for ":endfunc". */
17306 if (STRCMP(theline, skip_until) == 0)
17307 {
17308 vim_free(skip_until);
17309 skip_until = NULL;
17310 }
17311 }
17312 else
17313 {
17314 /* skip ':' and blanks*/
17315 for (p = theline; vim_iswhite(*p) || *p == ':'; ++p)
17316 ;
17317
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000017318 /* Check for "endfunction". */
17319 if (checkforcmd(&p, "endfunction", 4) && nesting-- == 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +000017320 {
17321 vim_free(theline);
17322 break;
17323 }
17324
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000017325 /* Increase indent inside "if", "while", "for" and "try", decrease
Bram Moolenaar071d4272004-06-13 20:20:40 +000017326 * at "end". */
17327 if (indent > 2 && STRNCMP(p, "end", 3) == 0)
17328 indent -= 2;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000017329 else if (STRNCMP(p, "if", 2) == 0
17330 || STRNCMP(p, "wh", 2) == 0
17331 || STRNCMP(p, "for", 3) == 0
Bram Moolenaar071d4272004-06-13 20:20:40 +000017332 || STRNCMP(p, "try", 3) == 0)
17333 indent += 2;
17334
17335 /* Check for defining a function inside this function. */
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000017336 if (checkforcmd(&p, "function", 2))
Bram Moolenaar071d4272004-06-13 20:20:40 +000017337 {
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000017338 if (*p == '!')
17339 p = skipwhite(p + 1);
Bram Moolenaar071d4272004-06-13 20:20:40 +000017340 p += eval_fname_script(p);
17341 if (ASCII_ISALPHA(*p))
17342 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000017343 vim_free(trans_function_name(&p, TRUE, 0, NULL));
Bram Moolenaar071d4272004-06-13 20:20:40 +000017344 if (*skipwhite(p) == '(')
17345 {
17346 ++nesting;
17347 indent += 2;
17348 }
17349 }
17350 }
17351
17352 /* Check for ":append" or ":insert". */
17353 p = skip_range(p, NULL);
17354 if ((p[0] == 'a' && (!ASCII_ISALPHA(p[1]) || p[1] == 'p'))
17355 || (p[0] == 'i'
17356 && (!ASCII_ISALPHA(p[1]) || (p[1] == 'n'
17357 && (!ASCII_ISALPHA(p[2]) || (p[2] == 's'))))))
17358 skip_until = vim_strsave((char_u *)".");
17359
17360 /* Check for ":python <<EOF", ":tcl <<EOF", etc. */
17361 arg = skipwhite(skiptowhite(p));
17362 if (arg[0] == '<' && arg[1] =='<'
17363 && ((p[0] == 'p' && p[1] == 'y'
17364 && (!ASCII_ISALPHA(p[2]) || p[2] == 't'))
17365 || (p[0] == 'p' && p[1] == 'e'
17366 && (!ASCII_ISALPHA(p[2]) || p[2] == 'r'))
17367 || (p[0] == 't' && p[1] == 'c'
17368 && (!ASCII_ISALPHA(p[2]) || p[2] == 'l'))
17369 || (p[0] == 'r' && p[1] == 'u' && p[2] == 'b'
17370 && (!ASCII_ISALPHA(p[3]) || p[3] == 'y'))
Bram Moolenaar325b7a22004-07-05 15:58:32 +000017371 || (p[0] == 'm' && p[1] == 'z'
17372 && (!ASCII_ISALPHA(p[2]) || p[2] == 's'))
Bram Moolenaar071d4272004-06-13 20:20:40 +000017373 ))
17374 {
17375 /* ":python <<" continues until a dot, like ":append" */
17376 p = skipwhite(arg + 2);
17377 if (*p == NUL)
17378 skip_until = vim_strsave((char_u *)".");
17379 else
17380 skip_until = vim_strsave(p);
17381 }
17382 }
17383
17384 /* Add the line to the function. */
17385 if (ga_grow(&newlines, 1) == FAIL)
Bram Moolenaar29a1c1d2005-06-24 23:11:15 +000017386 {
17387 vim_free(theline);
Bram Moolenaar071d4272004-06-13 20:20:40 +000017388 goto erret;
Bram Moolenaar29a1c1d2005-06-24 23:11:15 +000017389 }
17390
17391 /* Copy the line to newly allocated memory. get_one_sourceline()
17392 * allocates 250 bytes per line, this saves 80% on average. The cost
17393 * is an extra alloc/free. */
17394 p = vim_strsave(theline);
17395 if (p != NULL)
17396 {
17397 vim_free(theline);
17398 theline = p;
17399 }
17400
Bram Moolenaar071d4272004-06-13 20:20:40 +000017401 ((char_u **)(newlines.ga_data))[newlines.ga_len] = theline;
17402 newlines.ga_len++;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017403 }
17404
17405 /* Don't define the function when skipping commands or when an error was
17406 * detected. */
17407 if (eap->skip || did_emsg)
17408 goto erret;
17409
17410 /*
17411 * If there are no errors, add the function
17412 */
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000017413 if (fudi.fd_dict == NULL)
Bram Moolenaar49cd9572005-01-03 21:06:01 +000017414 {
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000017415 v = find_var(name, &ht);
Bram Moolenaar33570922005-01-25 22:26:29 +000017416 if (v != NULL && v->di_tv.v_type == VAR_FUNC)
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000017417 {
Bram Moolenaar81bf7082005-02-12 14:31:42 +000017418 emsg_funcname("E707: Function name conflicts with variable: %s",
17419 name);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000017420 goto erret;
17421 }
Bram Moolenaar49cd9572005-01-03 21:06:01 +000017422
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000017423 fp = find_func(name);
17424 if (fp != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000017425 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000017426 if (!eap->forceit)
17427 {
Bram Moolenaar81bf7082005-02-12 14:31:42 +000017428 emsg_funcname(e_funcexts, name);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000017429 goto erret;
17430 }
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000017431 if (fp->uf_calls > 0)
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000017432 {
Bram Moolenaar81bf7082005-02-12 14:31:42 +000017433 emsg_funcname("E127: Cannot redefine function %s: It is in use",
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000017434 name);
17435 goto erret;
17436 }
17437 /* redefine existing function */
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000017438 ga_clear_strings(&(fp->uf_args));
17439 ga_clear_strings(&(fp->uf_lines));
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000017440 vim_free(name);
17441 name = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017442 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000017443 }
17444 else
17445 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000017446 char numbuf[20];
17447
17448 fp = NULL;
17449 if (fudi.fd_newkey == NULL && !eap->forceit)
17450 {
17451 EMSG(_(e_funcdict));
17452 goto erret;
17453 }
Bram Moolenaar758711c2005-02-02 23:11:38 +000017454 if (fudi.fd_di == NULL)
17455 {
17456 /* Can't add a function to a locked dictionary */
17457 if (tv_check_lock(fudi.fd_dict->dv_lock, eap->arg))
17458 goto erret;
17459 }
17460 /* Can't change an existing function if it is locked */
17461 else if (tv_check_lock(fudi.fd_di->di_tv.v_lock, eap->arg))
17462 goto erret;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000017463
17464 /* Give the function a sequential number. Can only be used with a
17465 * Funcref! */
17466 vim_free(name);
17467 sprintf(numbuf, "%d", ++func_nr);
17468 name = vim_strsave((char_u *)numbuf);
17469 if (name == NULL)
17470 goto erret;
17471 }
17472
17473 if (fp == NULL)
17474 {
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +000017475 if (fudi.fd_dict == NULL && vim_strchr(name, AUTOLOAD_CHAR) != NULL)
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000017476 {
17477 int slen, plen;
17478 char_u *scriptname;
17479
17480 /* Check that the autoload name matches the script name. */
17481 j = FAIL;
17482 if (sourcing_name != NULL)
17483 {
17484 scriptname = autoload_name(name);
17485 if (scriptname != NULL)
17486 {
17487 p = vim_strchr(scriptname, '/');
17488 plen = STRLEN(p);
17489 slen = STRLEN(sourcing_name);
17490 if (slen > plen && fnamecmp(p,
17491 sourcing_name + slen - plen) == 0)
17492 j = OK;
17493 vim_free(scriptname);
17494 }
17495 }
17496 if (j == FAIL)
17497 {
17498 EMSG2(_("E746: Function name does not match script file name: %s"), name);
17499 goto erret;
17500 }
17501 }
17502
17503 fp = (ufunc_T *)alloc((unsigned)(sizeof(ufunc_T) + STRLEN(name)));
Bram Moolenaar071d4272004-06-13 20:20:40 +000017504 if (fp == NULL)
17505 goto erret;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000017506
17507 if (fudi.fd_dict != NULL)
17508 {
17509 if (fudi.fd_di == NULL)
17510 {
17511 /* add new dict entry */
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000017512 fudi.fd_di = dictitem_alloc(fudi.fd_newkey);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000017513 if (fudi.fd_di == NULL)
17514 {
17515 vim_free(fp);
17516 goto erret;
17517 }
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000017518 if (dict_add(fudi.fd_dict, fudi.fd_di) == FAIL)
17519 {
17520 vim_free(fudi.fd_di);
17521 goto erret;
17522 }
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000017523 }
17524 else
17525 /* overwrite existing dict entry */
17526 clear_tv(&fudi.fd_di->di_tv);
17527 fudi.fd_di->di_tv.v_type = VAR_FUNC;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000017528 fudi.fd_di->di_tv.v_lock = 0;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000017529 fudi.fd_di->di_tv.vval.v_string = vim_strsave(name);
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000017530 fp->uf_refcount = 1;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000017531 }
17532
Bram Moolenaar071d4272004-06-13 20:20:40 +000017533 /* insert the new function in the function list */
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000017534 STRCPY(fp->uf_name, name);
17535 hash_add(&func_hashtab, UF2HIKEY(fp));
Bram Moolenaar071d4272004-06-13 20:20:40 +000017536 }
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000017537 fp->uf_args = newargs;
17538 fp->uf_lines = newlines;
Bram Moolenaar05159a02005-02-26 23:04:13 +000017539#ifdef FEAT_PROFILE
17540 fp->uf_tml_count = NULL;
17541 fp->uf_tml_total = NULL;
17542 fp->uf_tml_self = NULL;
17543 fp->uf_profiling = FALSE;
17544 if (prof_def_func())
17545 func_do_profile(fp);
17546#endif
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000017547 fp->uf_varargs = varargs;
17548 fp->uf_flags = flags;
17549 fp->uf_calls = 0;
17550 fp->uf_script_ID = current_SID;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000017551 goto ret_free;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017552
17553erret:
Bram Moolenaar071d4272004-06-13 20:20:40 +000017554 ga_clear_strings(&newargs);
17555 ga_clear_strings(&newlines);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000017556ret_free:
17557 vim_free(skip_until);
17558 vim_free(fudi.fd_newkey);
Bram Moolenaar071d4272004-06-13 20:20:40 +000017559 vim_free(name);
Bram Moolenaar071d4272004-06-13 20:20:40 +000017560 did_emsg |= saved_did_emsg;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017561}
17562
17563/*
17564 * Get a function name, translating "<SID>" and "<SNR>".
Bram Moolenaara7043832005-01-21 11:56:39 +000017565 * Also handles a Funcref in a List or Dictionary.
Bram Moolenaar071d4272004-06-13 20:20:40 +000017566 * Returns the function name in allocated memory, or NULL for failure.
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000017567 * flags:
17568 * TFN_INT: internal function name OK
17569 * TFN_QUIET: be quiet
Bram Moolenaar071d4272004-06-13 20:20:40 +000017570 * Advances "pp" to just after the function name (if no error).
17571 */
17572 static char_u *
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000017573trans_function_name(pp, skip, flags, fdp)
Bram Moolenaar071d4272004-06-13 20:20:40 +000017574 char_u **pp;
17575 int skip; /* only find the end, don't evaluate */
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000017576 int flags;
Bram Moolenaar33570922005-01-25 22:26:29 +000017577 funcdict_T *fdp; /* return: info about dictionary used */
Bram Moolenaar071d4272004-06-13 20:20:40 +000017578{
Bram Moolenaar7480b5c2005-01-16 22:07:38 +000017579 char_u *name = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017580 char_u *start;
17581 char_u *end;
17582 int lead;
17583 char_u sid_buf[20];
Bram Moolenaar071d4272004-06-13 20:20:40 +000017584 int len;
Bram Moolenaar33570922005-01-25 22:26:29 +000017585 lval_T lv;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000017586
17587 if (fdp != NULL)
Bram Moolenaar33570922005-01-25 22:26:29 +000017588 vim_memset(fdp, 0, sizeof(funcdict_T));
Bram Moolenaar071d4272004-06-13 20:20:40 +000017589 start = *pp;
Bram Moolenaara7043832005-01-21 11:56:39 +000017590
17591 /* Check for hard coded <SNR>: already translated function ID (from a user
17592 * command). */
17593 if ((*pp)[0] == K_SPECIAL && (*pp)[1] == KS_EXTRA
17594 && (*pp)[2] == (int)KE_SNR)
17595 {
17596 *pp += 3;
17597 len = get_id_len(pp) + 3;
17598 return vim_strnsave(start, len);
17599 }
17600
17601 /* A name starting with "<SID>" or "<SNR>" is local to a script. But
17602 * don't skip over "s:", get_lval() needs it for "s:dict.func". */
Bram Moolenaar071d4272004-06-13 20:20:40 +000017603 lead = eval_fname_script(start);
Bram Moolenaara7043832005-01-21 11:56:39 +000017604 if (lead > 2)
Bram Moolenaar071d4272004-06-13 20:20:40 +000017605 start += lead;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +000017606
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +000017607 end = get_lval(start, NULL, &lv, FALSE, skip, flags & TFN_QUIET,
17608 lead > 2 ? 0 : FNE_CHECK_START);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +000017609 if (end == start)
17610 {
17611 if (!skip)
17612 EMSG(_("E129: Function name required"));
17613 goto theend;
17614 }
Bram Moolenaara7043832005-01-21 11:56:39 +000017615 if (end == NULL || (lv.ll_tv != NULL && (lead > 2 || lv.ll_range)))
Bram Moolenaar7480b5c2005-01-16 22:07:38 +000017616 {
17617 /*
17618 * Report an invalid expression in braces, unless the expression
17619 * evaluation has been cancelled due to an aborting error, an
17620 * interrupt, or an exception.
17621 */
17622 if (!aborting())
17623 {
17624 if (end != NULL)
17625 EMSG2(_(e_invarg2), start);
17626 }
17627 else
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +000017628 *pp = find_name_end(start, NULL, NULL, FNE_INCL_BR);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +000017629 goto theend;
17630 }
17631
17632 if (lv.ll_tv != NULL)
17633 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000017634 if (fdp != NULL)
17635 {
17636 fdp->fd_dict = lv.ll_dict;
17637 fdp->fd_newkey = lv.ll_newkey;
17638 lv.ll_newkey = NULL;
17639 fdp->fd_di = lv.ll_di;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000017640 }
Bram Moolenaar7480b5c2005-01-16 22:07:38 +000017641 if (lv.ll_tv->v_type == VAR_FUNC && lv.ll_tv->vval.v_string != NULL)
17642 {
17643 name = vim_strsave(lv.ll_tv->vval.v_string);
17644 *pp = end;
17645 }
17646 else
17647 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000017648 if (!skip && !(flags & TFN_QUIET) && (fdp == NULL
17649 || lv.ll_dict == NULL || fdp->fd_newkey == NULL))
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000017650 EMSG(_(e_funcref));
17651 else
17652 *pp = end;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +000017653 name = NULL;
17654 }
17655 goto theend;
17656 }
17657
17658 if (lv.ll_name == NULL)
17659 {
17660 /* Error found, but continue after the function name. */
17661 *pp = end;
17662 goto theend;
17663 }
17664
17665 if (lv.ll_exp_name != NULL)
17666 len = STRLEN(lv.ll_exp_name);
17667 else
Bram Moolenaara7043832005-01-21 11:56:39 +000017668 {
17669 if (lead == 2) /* skip over "s:" */
17670 lv.ll_name += 2;
17671 len = (int)(end - lv.ll_name);
17672 }
Bram Moolenaar7480b5c2005-01-16 22:07:38 +000017673
17674 /*
17675 * Copy the function name to allocated memory.
17676 * Accept <SID>name() inside a script, translate into <SNR>123_name().
17677 * Accept <SNR>123_name() outside a script.
17678 */
17679 if (skip)
17680 lead = 0; /* do nothing */
17681 else if (lead > 0)
17682 {
17683 lead = 3;
17684 if (eval_fname_sid(*pp)) /* If it's "<SID>" */
17685 {
17686 if (current_SID <= 0)
17687 {
17688 EMSG(_(e_usingsid));
17689 goto theend;
17690 }
17691 sprintf((char *)sid_buf, "%ld_", (long)current_SID);
17692 lead += (int)STRLEN(sid_buf);
17693 }
17694 }
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +000017695 else if (!(flags & TFN_INT) && builtin_function(lv.ll_name))
Bram Moolenaar7480b5c2005-01-16 22:07:38 +000017696 {
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +000017697 EMSG2(_("E128: Function name must start with a capital or contain a colon: %s"), lv.ll_name);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +000017698 goto theend;
17699 }
17700 name = alloc((unsigned)(len + lead + 1));
17701 if (name != NULL)
17702 {
17703 if (lead > 0)
17704 {
17705 name[0] = K_SPECIAL;
17706 name[1] = KS_EXTRA;
17707 name[2] = (int)KE_SNR;
Bram Moolenaara7043832005-01-21 11:56:39 +000017708 if (lead > 3) /* If it's "<SID>" */
Bram Moolenaar7480b5c2005-01-16 22:07:38 +000017709 STRCPY(name + 3, sid_buf);
17710 }
17711 mch_memmove(name + lead, lv.ll_name, (size_t)len);
17712 name[len + lead] = NUL;
17713 }
17714 *pp = end;
17715
17716theend:
17717 clear_lval(&lv);
17718 return name;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017719}
17720
17721/*
17722 * Return 5 if "p" starts with "<SID>" or "<SNR>" (ignoring case).
17723 * Return 2 if "p" starts with "s:".
17724 * Return 0 otherwise.
17725 */
17726 static int
17727eval_fname_script(p)
17728 char_u *p;
17729{
17730 if (p[0] == '<' && (STRNICMP(p + 1, "SID>", 4) == 0
17731 || STRNICMP(p + 1, "SNR>", 4) == 0))
17732 return 5;
17733 if (p[0] == 's' && p[1] == ':')
17734 return 2;
17735 return 0;
17736}
17737
17738/*
17739 * Return TRUE if "p" starts with "<SID>" or "s:".
17740 * Only works if eval_fname_script() returned non-zero for "p"!
17741 */
17742 static int
17743eval_fname_sid(p)
17744 char_u *p;
17745{
17746 return (*p == 's' || TOUPPER_ASC(p[2]) == 'I');
17747}
17748
17749/*
17750 * List the head of the function: "name(arg1, arg2)".
17751 */
17752 static void
17753list_func_head(fp, indent)
17754 ufunc_T *fp;
17755 int indent;
17756{
17757 int j;
17758
17759 msg_start();
17760 if (indent)
17761 MSG_PUTS(" ");
17762 MSG_PUTS("function ");
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000017763 if (fp->uf_name[0] == K_SPECIAL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000017764 {
17765 MSG_PUTS_ATTR("<SNR>", hl_attr(HLF_8));
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000017766 msg_puts(fp->uf_name + 3);
Bram Moolenaar071d4272004-06-13 20:20:40 +000017767 }
17768 else
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000017769 msg_puts(fp->uf_name);
Bram Moolenaar071d4272004-06-13 20:20:40 +000017770 msg_putchar('(');
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000017771 for (j = 0; j < fp->uf_args.ga_len; ++j)
Bram Moolenaar071d4272004-06-13 20:20:40 +000017772 {
17773 if (j)
17774 MSG_PUTS(", ");
17775 msg_puts(FUNCARG(fp, j));
17776 }
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000017777 if (fp->uf_varargs)
Bram Moolenaar071d4272004-06-13 20:20:40 +000017778 {
17779 if (j)
17780 MSG_PUTS(", ");
17781 MSG_PUTS("...");
17782 }
17783 msg_putchar(')');
Bram Moolenaarcafda4f2005-09-06 19:25:11 +000017784 msg_clr_eos();
Bram Moolenaar5b8d8fd2005-08-16 23:01:50 +000017785 if (p_verbose > 0)
17786 last_set_msg(fp->uf_script_ID);
Bram Moolenaar071d4272004-06-13 20:20:40 +000017787}
17788
17789/*
17790 * Find a function by name, return pointer to it in ufuncs.
17791 * Return NULL for unknown function.
17792 */
17793 static ufunc_T *
17794find_func(name)
17795 char_u *name;
17796{
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000017797 hashitem_T *hi;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017798
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000017799 hi = hash_find(&func_hashtab, name);
17800 if (!HASHITEM_EMPTY(hi))
17801 return HI2UF(hi);
17802 return NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017803}
17804
Bram Moolenaar29a1c1d2005-06-24 23:11:15 +000017805#if defined(EXITFREE) || defined(PROTO)
17806 void
17807free_all_functions()
17808{
17809 hashitem_T *hi;
17810
17811 /* Need to start all over every time, because func_free() may change the
17812 * hash table. */
17813 while (func_hashtab.ht_used > 0)
17814 for (hi = func_hashtab.ht_array; ; ++hi)
17815 if (!HASHITEM_EMPTY(hi))
17816 {
17817 func_free(HI2UF(hi));
17818 break;
17819 }
17820}
17821#endif
17822
Bram Moolenaar49cd9572005-01-03 21:06:01 +000017823/*
17824 * Return TRUE if a function "name" exists.
17825 */
17826 static int
17827function_exists(name)
17828 char_u *name;
17829{
17830 char_u *p = name;
17831 int n = FALSE;
17832
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000017833 p = trans_function_name(&p, FALSE, TFN_INT|TFN_QUIET, NULL);
Bram Moolenaar49cd9572005-01-03 21:06:01 +000017834 if (p != NULL)
17835 {
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +000017836 if (builtin_function(p))
Bram Moolenaar49cd9572005-01-03 21:06:01 +000017837 n = (find_internal_func(p) >= 0);
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +000017838 else
17839 n = (find_func(p) != NULL);
Bram Moolenaar49cd9572005-01-03 21:06:01 +000017840 vim_free(p);
17841 }
17842 return n;
17843}
17844
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +000017845/*
17846 * Return TRUE if "name" looks like a builtin function name: starts with a
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +000017847 * lower case letter and doesn't contain a ':' or AUTOLOAD_CHAR.
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +000017848 */
17849 static int
17850builtin_function(name)
17851 char_u *name;
17852{
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +000017853 return ASCII_ISLOWER(name[0]) && vim_strchr(name, ':') == NULL
17854 && vim_strchr(name, AUTOLOAD_CHAR) == NULL;
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +000017855}
17856
Bram Moolenaar05159a02005-02-26 23:04:13 +000017857#if defined(FEAT_PROFILE) || defined(PROTO)
17858/*
17859 * Start profiling function "fp".
17860 */
17861 static void
17862func_do_profile(fp)
17863 ufunc_T *fp;
17864{
17865 fp->uf_tm_count = 0;
17866 profile_zero(&fp->uf_tm_self);
17867 profile_zero(&fp->uf_tm_total);
17868 if (fp->uf_tml_count == NULL)
17869 fp->uf_tml_count = (int *)alloc_clear((unsigned)
17870 (sizeof(int) * fp->uf_lines.ga_len));
17871 if (fp->uf_tml_total == NULL)
17872 fp->uf_tml_total = (proftime_T *)alloc_clear((unsigned)
17873 (sizeof(proftime_T) * fp->uf_lines.ga_len));
17874 if (fp->uf_tml_self == NULL)
17875 fp->uf_tml_self = (proftime_T *)alloc_clear((unsigned)
17876 (sizeof(proftime_T) * fp->uf_lines.ga_len));
17877 fp->uf_tml_idx = -1;
17878 if (fp->uf_tml_count == NULL || fp->uf_tml_total == NULL
17879 || fp->uf_tml_self == NULL)
17880 return; /* out of memory */
17881
17882 fp->uf_profiling = TRUE;
17883}
17884
17885/*
17886 * Dump the profiling results for all functions in file "fd".
17887 */
17888 void
17889func_dump_profile(fd)
17890 FILE *fd;
17891{
17892 hashitem_T *hi;
17893 int todo;
17894 ufunc_T *fp;
17895 int i;
Bram Moolenaar73830342005-02-28 22:48:19 +000017896 ufunc_T **sorttab;
17897 int st_len = 0;
Bram Moolenaar05159a02005-02-26 23:04:13 +000017898
17899 todo = func_hashtab.ht_used;
Bram Moolenaar73830342005-02-28 22:48:19 +000017900 sorttab = (ufunc_T **)alloc((unsigned)(sizeof(ufunc_T) * todo));
17901
Bram Moolenaar05159a02005-02-26 23:04:13 +000017902 for (hi = func_hashtab.ht_array; todo > 0; ++hi)
17903 {
17904 if (!HASHITEM_EMPTY(hi))
17905 {
17906 --todo;
17907 fp = HI2UF(hi);
17908 if (fp->uf_profiling)
17909 {
Bram Moolenaar73830342005-02-28 22:48:19 +000017910 if (sorttab != NULL)
17911 sorttab[st_len++] = fp;
17912
Bram Moolenaar05159a02005-02-26 23:04:13 +000017913 if (fp->uf_name[0] == K_SPECIAL)
17914 fprintf(fd, "FUNCTION <SNR>%s()\n", fp->uf_name + 3);
17915 else
17916 fprintf(fd, "FUNCTION %s()\n", fp->uf_name);
17917 if (fp->uf_tm_count == 1)
17918 fprintf(fd, "Called 1 time\n");
17919 else
17920 fprintf(fd, "Called %d times\n", fp->uf_tm_count);
17921 fprintf(fd, "Total time: %s\n", profile_msg(&fp->uf_tm_total));
17922 fprintf(fd, " Self time: %s\n", profile_msg(&fp->uf_tm_self));
17923 fprintf(fd, "\n");
17924 fprintf(fd, "count total (s) self (s)\n");
17925
17926 for (i = 0; i < fp->uf_lines.ga_len; ++i)
17927 {
Bram Moolenaar73830342005-02-28 22:48:19 +000017928 prof_func_line(fd, fp->uf_tml_count[i],
17929 &fp->uf_tml_total[i], &fp->uf_tml_self[i], TRUE);
Bram Moolenaar05159a02005-02-26 23:04:13 +000017930 fprintf(fd, "%s\n", FUNCLINE(fp, i));
17931 }
17932 fprintf(fd, "\n");
17933 }
17934 }
17935 }
Bram Moolenaar73830342005-02-28 22:48:19 +000017936
17937 if (sorttab != NULL && st_len > 0)
17938 {
17939 qsort((void *)sorttab, (size_t)st_len, sizeof(ufunc_T *),
17940 prof_total_cmp);
17941 prof_sort_list(fd, sorttab, st_len, "TOTAL", FALSE);
17942 qsort((void *)sorttab, (size_t)st_len, sizeof(ufunc_T *),
17943 prof_self_cmp);
17944 prof_sort_list(fd, sorttab, st_len, "SELF", TRUE);
17945 }
Bram Moolenaar05159a02005-02-26 23:04:13 +000017946}
Bram Moolenaar73830342005-02-28 22:48:19 +000017947
17948 static void
17949prof_sort_list(fd, sorttab, st_len, title, prefer_self)
17950 FILE *fd;
17951 ufunc_T **sorttab;
17952 int st_len;
17953 char *title;
17954 int prefer_self; /* when equal print only self time */
17955{
17956 int i;
17957 ufunc_T *fp;
17958
17959 fprintf(fd, "FUNCTIONS SORTED ON %s TIME\n", title);
17960 fprintf(fd, "count total (s) self (s) function\n");
17961 for (i = 0; i < 20 && i < st_len; ++i)
17962 {
17963 fp = sorttab[i];
17964 prof_func_line(fd, fp->uf_tm_count, &fp->uf_tm_total, &fp->uf_tm_self,
17965 prefer_self);
17966 if (fp->uf_name[0] == K_SPECIAL)
17967 fprintf(fd, " <SNR>%s()\n", fp->uf_name + 3);
17968 else
17969 fprintf(fd, " %s()\n", fp->uf_name);
17970 }
17971 fprintf(fd, "\n");
17972}
17973
17974/*
17975 * Print the count and times for one function or function line.
17976 */
17977 static void
17978prof_func_line(fd, count, total, self, prefer_self)
17979 FILE *fd;
17980 int count;
17981 proftime_T *total;
17982 proftime_T *self;
17983 int prefer_self; /* when equal print only self time */
17984{
17985 if (count > 0)
17986 {
17987 fprintf(fd, "%5d ", count);
17988 if (prefer_self && profile_equal(total, self))
17989 fprintf(fd, " ");
17990 else
17991 fprintf(fd, "%s ", profile_msg(total));
17992 if (!prefer_self && profile_equal(total, self))
17993 fprintf(fd, " ");
17994 else
17995 fprintf(fd, "%s ", profile_msg(self));
17996 }
17997 else
17998 fprintf(fd, " ");
17999}
18000
18001/*
18002 * Compare function for total time sorting.
18003 */
18004 static int
18005#ifdef __BORLANDC__
18006_RTLENTRYF
18007#endif
18008prof_total_cmp(s1, s2)
18009 const void *s1;
18010 const void *s2;
18011{
18012 ufunc_T *p1, *p2;
18013
18014 p1 = *(ufunc_T **)s1;
18015 p2 = *(ufunc_T **)s2;
18016 return profile_cmp(&p1->uf_tm_total, &p2->uf_tm_total);
18017}
18018
18019/*
18020 * Compare function for self time sorting.
18021 */
18022 static int
18023#ifdef __BORLANDC__
18024_RTLENTRYF
18025#endif
18026prof_self_cmp(s1, s2)
18027 const void *s1;
18028 const void *s2;
18029{
18030 ufunc_T *p1, *p2;
18031
18032 p1 = *(ufunc_T **)s1;
18033 p2 = *(ufunc_T **)s2;
18034 return profile_cmp(&p1->uf_tm_self, &p2->uf_tm_self);
18035}
18036
Bram Moolenaar05159a02005-02-26 23:04:13 +000018037#endif
18038
Bram Moolenaar87e25fd2005-07-27 21:13:01 +000018039/* The names of packages that once were loaded is remembered. */
18040static garray_T ga_loaded = {0, 0, sizeof(char_u *), 4, NULL};
18041
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +000018042/*
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000018043 * If "name" has a package name try autoloading the script for it.
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +000018044 * Return TRUE if a package was loaded.
18045 */
18046 static int
Bram Moolenaar87e25fd2005-07-27 21:13:01 +000018047script_autoload(name, reload)
18048 char_u *name;
18049 int reload; /* load script again when already loaded */
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +000018050{
18051 char_u *p;
Bram Moolenaar87e25fd2005-07-27 21:13:01 +000018052 char_u *scriptname, *tofree;
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +000018053 int ret = FALSE;
Bram Moolenaar87e25fd2005-07-27 21:13:01 +000018054 int i;
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +000018055
Bram Moolenaar87e25fd2005-07-27 21:13:01 +000018056 /* If there is no '#' after name[0] there is no package name. */
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +000018057 p = vim_strchr(name, AUTOLOAD_CHAR);
Bram Moolenaar87e25fd2005-07-27 21:13:01 +000018058 if (p == NULL || p == name)
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +000018059 return FALSE;
18060
Bram Moolenaar87e25fd2005-07-27 21:13:01 +000018061 tofree = scriptname = autoload_name(name);
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000018062
Bram Moolenaar87e25fd2005-07-27 21:13:01 +000018063 /* Find the name in the list of previously loaded package names. Skip
18064 * "autoload/", it's always the same. */
18065 for (i = 0; i < ga_loaded.ga_len; ++i)
18066 if (STRCMP(((char_u **)ga_loaded.ga_data)[i] + 9, scriptname + 9) == 0)
18067 break;
18068 if (!reload && i < ga_loaded.ga_len)
18069 ret = FALSE; /* was loaded already */
18070 else
18071 {
18072 /* Remember the name if it wasn't loaded already. */
18073 if (i == ga_loaded.ga_len && ga_grow(&ga_loaded, 1) == OK)
18074 {
18075 ((char_u **)ga_loaded.ga_data)[ga_loaded.ga_len++] = scriptname;
18076 tofree = NULL;
18077 }
18078
18079 /* Try loading the package from $VIMRUNTIME/autoload/<name>.vim */
Bram Moolenaar90cfdbe2005-08-12 19:59:19 +000018080 if (source_runtime(scriptname, FALSE) == OK)
Bram Moolenaar87e25fd2005-07-27 21:13:01 +000018081 ret = TRUE;
18082 }
18083
18084 vim_free(tofree);
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000018085 return ret;
18086}
18087
18088/*
18089 * Return the autoload script name for a function or variable name.
18090 * Returns NULL when out of memory.
18091 */
18092 static char_u *
18093autoload_name(name)
18094 char_u *name;
18095{
18096 char_u *p;
18097 char_u *scriptname;
18098
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +000018099 /* Get the script file name: replace '#' with '/', append ".vim". */
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +000018100 scriptname = alloc((unsigned)(STRLEN(name) + 14));
18101 if (scriptname == NULL)
18102 return FALSE;
18103 STRCPY(scriptname, "autoload/");
18104 STRCAT(scriptname, name);
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +000018105 *vim_strrchr(scriptname, AUTOLOAD_CHAR) = NUL;
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +000018106 STRCAT(scriptname, ".vim");
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +000018107 while ((p = vim_strchr(scriptname, AUTOLOAD_CHAR)) != NULL)
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +000018108 *p = '/';
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000018109 return scriptname;
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +000018110}
18111
Bram Moolenaar071d4272004-06-13 20:20:40 +000018112#if defined(FEAT_CMDL_COMPL) || defined(PROTO)
18113
18114/*
18115 * Function given to ExpandGeneric() to obtain the list of user defined
18116 * function names.
18117 */
18118 char_u *
18119get_user_func_name(xp, idx)
18120 expand_T *xp;
18121 int idx;
18122{
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000018123 static long_u done;
18124 static hashitem_T *hi;
18125 ufunc_T *fp;
Bram Moolenaar071d4272004-06-13 20:20:40 +000018126
18127 if (idx == 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +000018128 {
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000018129 done = 0;
18130 hi = func_hashtab.ht_array;
18131 }
18132 if (done < func_hashtab.ht_used)
18133 {
18134 if (done++ > 0)
18135 ++hi;
18136 while (HASHITEM_EMPTY(hi))
18137 ++hi;
18138 fp = HI2UF(hi);
18139
18140 if (STRLEN(fp->uf_name) + 4 >= IOSIZE)
18141 return fp->uf_name; /* prevents overflow */
Bram Moolenaar071d4272004-06-13 20:20:40 +000018142
18143 cat_func_name(IObuff, fp);
18144 if (xp->xp_context != EXPAND_USER_FUNC)
18145 {
18146 STRCAT(IObuff, "(");
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000018147 if (!fp->uf_varargs && fp->uf_args.ga_len == 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +000018148 STRCAT(IObuff, ")");
18149 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000018150 return IObuff;
18151 }
18152 return NULL;
18153}
18154
18155#endif /* FEAT_CMDL_COMPL */
18156
18157/*
18158 * Copy the function name of "fp" to buffer "buf".
18159 * "buf" must be able to hold the function name plus three bytes.
18160 * Takes care of script-local function names.
18161 */
18162 static void
18163cat_func_name(buf, fp)
18164 char_u *buf;
18165 ufunc_T *fp;
18166{
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000018167 if (fp->uf_name[0] == K_SPECIAL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000018168 {
18169 STRCPY(buf, "<SNR>");
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000018170 STRCAT(buf, fp->uf_name + 3);
Bram Moolenaar071d4272004-06-13 20:20:40 +000018171 }
18172 else
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000018173 STRCPY(buf, fp->uf_name);
Bram Moolenaar071d4272004-06-13 20:20:40 +000018174}
18175
18176/*
18177 * ":delfunction {name}"
18178 */
18179 void
18180ex_delfunction(eap)
18181 exarg_T *eap;
18182{
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000018183 ufunc_T *fp = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000018184 char_u *p;
18185 char_u *name;
Bram Moolenaar33570922005-01-25 22:26:29 +000018186 funcdict_T fudi;
Bram Moolenaar071d4272004-06-13 20:20:40 +000018187
18188 p = eap->arg;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000018189 name = trans_function_name(&p, eap->skip, 0, &fudi);
18190 vim_free(fudi.fd_newkey);
Bram Moolenaar071d4272004-06-13 20:20:40 +000018191 if (name == NULL)
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000018192 {
18193 if (fudi.fd_dict != NULL && !eap->skip)
18194 EMSG(_(e_funcref));
Bram Moolenaar071d4272004-06-13 20:20:40 +000018195 return;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000018196 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000018197 if (!ends_excmd(*skipwhite(p)))
18198 {
18199 vim_free(name);
18200 EMSG(_(e_trailing));
18201 return;
18202 }
18203 eap->nextcmd = check_nextcmd(p);
18204 if (eap->nextcmd != NULL)
18205 *p = NUL;
18206
18207 if (!eap->skip)
18208 fp = find_func(name);
18209 vim_free(name);
18210
18211 if (!eap->skip)
18212 {
18213 if (fp == NULL)
18214 {
Bram Moolenaar05159a02005-02-26 23:04:13 +000018215 EMSG2(_(e_nofunc), eap->arg);
Bram Moolenaar071d4272004-06-13 20:20:40 +000018216 return;
18217 }
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000018218 if (fp->uf_calls > 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +000018219 {
18220 EMSG2(_("E131: Cannot delete function %s: It is in use"), eap->arg);
18221 return;
18222 }
18223
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000018224 if (fudi.fd_dict != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000018225 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000018226 /* Delete the dict item that refers to the function, it will
18227 * invoke func_unref() and possibly delete the function. */
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000018228 dictitem_remove(fudi.fd_dict, fudi.fd_di);
Bram Moolenaar071d4272004-06-13 20:20:40 +000018229 }
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000018230 else
18231 func_free(fp);
18232 }
18233}
18234
18235/*
18236 * Free a function and remove it from the list of functions.
18237 */
18238 static void
18239func_free(fp)
18240 ufunc_T *fp;
18241{
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000018242 hashitem_T *hi;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000018243
18244 /* clear this function */
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000018245 ga_clear_strings(&(fp->uf_args));
18246 ga_clear_strings(&(fp->uf_lines));
Bram Moolenaar05159a02005-02-26 23:04:13 +000018247#ifdef FEAT_PROFILE
18248 vim_free(fp->uf_tml_count);
18249 vim_free(fp->uf_tml_total);
18250 vim_free(fp->uf_tml_self);
18251#endif
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000018252
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000018253 /* remove the function from the function hashtable */
18254 hi = hash_find(&func_hashtab, UF2HIKEY(fp));
18255 if (HASHITEM_EMPTY(hi))
18256 EMSG2(_(e_intern2), "func_free()");
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000018257 else
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000018258 hash_remove(&func_hashtab, hi);
18259
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000018260 vim_free(fp);
18261}
18262
18263/*
18264 * Unreference a Function: decrement the reference count and free it when it
18265 * becomes zero. Only for numbered functions.
18266 */
18267 static void
18268func_unref(name)
18269 char_u *name;
18270{
18271 ufunc_T *fp;
18272
18273 if (name != NULL && isdigit(*name))
18274 {
18275 fp = find_func(name);
18276 if (fp == NULL)
18277 EMSG2(_(e_intern2), "func_unref()");
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000018278 else if (--fp->uf_refcount <= 0)
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000018279 {
18280 /* Only delete it when it's not being used. Otherwise it's done
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000018281 * when "uf_calls" becomes zero. */
18282 if (fp->uf_calls == 0)
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000018283 func_free(fp);
18284 }
18285 }
18286}
18287
18288/*
18289 * Count a reference to a Function.
18290 */
18291 static void
18292func_ref(name)
18293 char_u *name;
18294{
18295 ufunc_T *fp;
18296
18297 if (name != NULL && isdigit(*name))
18298 {
18299 fp = find_func(name);
18300 if (fp == NULL)
18301 EMSG2(_(e_intern2), "func_ref()");
18302 else
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000018303 ++fp->uf_refcount;
Bram Moolenaar071d4272004-06-13 20:20:40 +000018304 }
18305}
18306
18307/*
18308 * Call a user function.
18309 */
18310 static void
Bram Moolenaare9a41262005-01-15 22:18:47 +000018311call_user_func(fp, argcount, argvars, rettv, firstline, lastline, selfdict)
Bram Moolenaar071d4272004-06-13 20:20:40 +000018312 ufunc_T *fp; /* pointer to function */
18313 int argcount; /* nr of args */
Bram Moolenaar33570922005-01-25 22:26:29 +000018314 typval_T *argvars; /* arguments */
18315 typval_T *rettv; /* return value */
Bram Moolenaar071d4272004-06-13 20:20:40 +000018316 linenr_T firstline; /* first line of range */
18317 linenr_T lastline; /* last line of range */
Bram Moolenaar33570922005-01-25 22:26:29 +000018318 dict_T *selfdict; /* Dictionary for "self" */
Bram Moolenaar071d4272004-06-13 20:20:40 +000018319{
Bram Moolenaar33570922005-01-25 22:26:29 +000018320 char_u *save_sourcing_name;
18321 linenr_T save_sourcing_lnum;
18322 scid_T save_current_SID;
18323 funccall_T fc;
Bram Moolenaar33570922005-01-25 22:26:29 +000018324 int save_did_emsg;
18325 static int depth = 0;
18326 dictitem_T *v;
18327 int fixvar_idx = 0; /* index in fixvar[] */
18328 int i;
18329 int ai;
18330 char_u numbuf[NUMBUFLEN];
18331 char_u *name;
Bram Moolenaar05159a02005-02-26 23:04:13 +000018332#ifdef FEAT_PROFILE
18333 proftime_T wait_start;
18334#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000018335
18336 /* If depth of calling is getting too high, don't execute the function */
18337 if (depth >= p_mfd)
18338 {
18339 EMSG(_("E132: Function call depth is higher than 'maxfuncdepth'"));
Bram Moolenaarc70646c2005-01-04 21:52:38 +000018340 rettv->v_type = VAR_NUMBER;
18341 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000018342 return;
18343 }
18344 ++depth;
18345
18346 line_breakcheck(); /* check for CTRL-C hit */
18347
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +000018348 fc.caller = current_funccal;
Bram Moolenaar33570922005-01-25 22:26:29 +000018349 current_funccal = &fc;
Bram Moolenaar071d4272004-06-13 20:20:40 +000018350 fc.func = fp;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000018351 fc.rettv = rettv;
18352 rettv->vval.v_number = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +000018353 fc.linenr = 0;
18354 fc.returned = FALSE;
18355 fc.level = ex_nesting_level;
Bram Moolenaar071d4272004-06-13 20:20:40 +000018356 /* Check if this function has a breakpoint. */
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000018357 fc.breakpoint = dbg_find_breakpoint(FALSE, fp->uf_name, (linenr_T)0);
Bram Moolenaar071d4272004-06-13 20:20:40 +000018358 fc.dbg_tick = debug_tick;
18359
Bram Moolenaar33570922005-01-25 22:26:29 +000018360 /*
18361 * Note about using fc.fixvar[]: This is an array of FIXVAR_CNT variables
18362 * with names up to VAR_SHORT_LEN long. This avoids having to alloc/free
18363 * each argument variable and saves a lot of time.
18364 */
18365 /*
18366 * Init l: variables.
18367 */
18368 init_var_dict(&fc.l_vars, &fc.l_vars_var);
Bram Moolenaara7043832005-01-21 11:56:39 +000018369 if (selfdict != NULL)
Bram Moolenaare9a41262005-01-15 22:18:47 +000018370 {
Bram Moolenaar33570922005-01-25 22:26:29 +000018371 /* Set l:self to "selfdict". */
18372 v = &fc.fixvar[fixvar_idx++].var;
18373 STRCPY(v->di_key, "self");
18374 v->di_flags = DI_FLAGS_RO + DI_FLAGS_FIX;
18375 hash_add(&fc.l_vars.dv_hashtab, DI2HIKEY(v));
18376 v->di_tv.v_type = VAR_DICT;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000018377 v->di_tv.v_lock = 0;
Bram Moolenaar33570922005-01-25 22:26:29 +000018378 v->di_tv.vval.v_dict = selfdict;
18379 ++selfdict->dv_refcount;
18380 }
Bram Moolenaare9a41262005-01-15 22:18:47 +000018381
Bram Moolenaar33570922005-01-25 22:26:29 +000018382 /*
18383 * Init a: variables.
18384 * Set a:0 to "argcount".
18385 * Set a:000 to a list with room for the "..." arguments.
18386 */
18387 init_var_dict(&fc.l_avars, &fc.l_avars_var);
18388 add_nr_var(&fc.l_avars, &fc.fixvar[fixvar_idx++].var, "0",
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000018389 (varnumber_T)(argcount - fp->uf_args.ga_len));
Bram Moolenaar33570922005-01-25 22:26:29 +000018390 v = &fc.fixvar[fixvar_idx++].var;
18391 STRCPY(v->di_key, "000");
18392 v->di_flags = DI_FLAGS_RO | DI_FLAGS_FIX;
18393 hash_add(&fc.l_avars.dv_hashtab, DI2HIKEY(v));
18394 v->di_tv.v_type = VAR_LIST;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000018395 v->di_tv.v_lock = VAR_FIXED;
Bram Moolenaar33570922005-01-25 22:26:29 +000018396 v->di_tv.vval.v_list = &fc.l_varlist;
18397 vim_memset(&fc.l_varlist, 0, sizeof(list_T));
18398 fc.l_varlist.lv_refcount = 99999;
18399
18400 /*
18401 * Set a:firstline to "firstline" and a:lastline to "lastline".
18402 * Set a:name to named arguments.
18403 * Set a:N to the "..." arguments.
18404 */
18405 add_nr_var(&fc.l_avars, &fc.fixvar[fixvar_idx++].var, "firstline",
18406 (varnumber_T)firstline);
18407 add_nr_var(&fc.l_avars, &fc.fixvar[fixvar_idx++].var, "lastline",
18408 (varnumber_T)lastline);
18409 for (i = 0; i < argcount; ++i)
18410 {
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000018411 ai = i - fp->uf_args.ga_len;
Bram Moolenaar33570922005-01-25 22:26:29 +000018412 if (ai < 0)
18413 /* named argument a:name */
18414 name = FUNCARG(fp, i);
18415 else
Bram Moolenaare9a41262005-01-15 22:18:47 +000018416 {
Bram Moolenaar33570922005-01-25 22:26:29 +000018417 /* "..." argument a:1, a:2, etc. */
18418 sprintf((char *)numbuf, "%d", ai + 1);
18419 name = numbuf;
18420 }
18421 if (fixvar_idx < FIXVAR_CNT && STRLEN(name) <= VAR_SHORT_LEN)
18422 {
18423 v = &fc.fixvar[fixvar_idx++].var;
18424 v->di_flags = DI_FLAGS_RO | DI_FLAGS_FIX;
18425 }
18426 else
18427 {
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000018428 v = (dictitem_T *)alloc((unsigned)(sizeof(dictitem_T)
18429 + STRLEN(name)));
Bram Moolenaar33570922005-01-25 22:26:29 +000018430 if (v == NULL)
18431 break;
18432 v->di_flags = DI_FLAGS_RO;
18433 }
18434 STRCPY(v->di_key, name);
18435 hash_add(&fc.l_avars.dv_hashtab, DI2HIKEY(v));
18436
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000018437 /* Note: the values are copied directly to avoid alloc/free.
18438 * "argvars" must have VAR_FIXED for v_lock. */
Bram Moolenaar33570922005-01-25 22:26:29 +000018439 v->di_tv = argvars[i];
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000018440 v->di_tv.v_lock = VAR_FIXED;
Bram Moolenaar33570922005-01-25 22:26:29 +000018441
18442 if (ai >= 0 && ai < MAX_FUNC_ARGS)
18443 {
18444 list_append(&fc.l_varlist, &fc.l_listitems[ai]);
18445 fc.l_listitems[ai].li_tv = argvars[i];
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000018446 fc.l_listitems[ai].li_tv.v_lock = VAR_FIXED;
Bram Moolenaare9a41262005-01-15 22:18:47 +000018447 }
18448 }
18449
Bram Moolenaar071d4272004-06-13 20:20:40 +000018450 /* Don't redraw while executing the function. */
18451 ++RedrawingDisabled;
18452 save_sourcing_name = sourcing_name;
18453 save_sourcing_lnum = sourcing_lnum;
18454 sourcing_lnum = 1;
18455 sourcing_name = alloc((unsigned)((save_sourcing_name == NULL ? 0
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000018456 : STRLEN(save_sourcing_name)) + STRLEN(fp->uf_name) + 13));
Bram Moolenaar071d4272004-06-13 20:20:40 +000018457 if (sourcing_name != NULL)
18458 {
18459 if (save_sourcing_name != NULL
18460 && STRNCMP(save_sourcing_name, "function ", 9) == 0)
18461 sprintf((char *)sourcing_name, "%s..", save_sourcing_name);
18462 else
18463 STRCPY(sourcing_name, "function ");
18464 cat_func_name(sourcing_name + STRLEN(sourcing_name), fp);
18465
18466 if (p_verbose >= 12)
18467 {
18468 ++no_wait_return;
Bram Moolenaar54ee7752005-05-31 22:22:17 +000018469 verbose_enter_scroll();
18470
Bram Moolenaar555b2802005-05-19 21:08:39 +000018471 smsg((char_u *)_("calling %s"), sourcing_name);
Bram Moolenaar071d4272004-06-13 20:20:40 +000018472 if (p_verbose >= 14)
18473 {
Bram Moolenaar071d4272004-06-13 20:20:40 +000018474 char_u buf[MSG_BUF_LEN];
Bram Moolenaar758711c2005-02-02 23:11:38 +000018475 char_u numbuf[NUMBUFLEN];
18476 char_u *tofree;
Bram Moolenaar071d4272004-06-13 20:20:40 +000018477
18478 msg_puts((char_u *)"(");
18479 for (i = 0; i < argcount; ++i)
18480 {
18481 if (i > 0)
18482 msg_puts((char_u *)", ");
Bram Moolenaar49cd9572005-01-03 21:06:01 +000018483 if (argvars[i].v_type == VAR_NUMBER)
18484 msg_outnum((long)argvars[i].vval.v_number);
Bram Moolenaar071d4272004-06-13 20:20:40 +000018485 else
18486 {
Bram Moolenaar758711c2005-02-02 23:11:38 +000018487 trunc_string(tv2string(&argvars[i], &tofree, numbuf),
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +000018488 buf, MSG_BUF_CLEN);
Bram Moolenaar071d4272004-06-13 20:20:40 +000018489 msg_puts(buf);
Bram Moolenaar758711c2005-02-02 23:11:38 +000018490 vim_free(tofree);
Bram Moolenaar071d4272004-06-13 20:20:40 +000018491 }
18492 }
18493 msg_puts((char_u *)")");
18494 }
18495 msg_puts((char_u *)"\n"); /* don't overwrite this either */
Bram Moolenaar54ee7752005-05-31 22:22:17 +000018496
18497 verbose_leave_scroll();
Bram Moolenaar071d4272004-06-13 20:20:40 +000018498 --no_wait_return;
18499 }
18500 }
Bram Moolenaar05159a02005-02-26 23:04:13 +000018501#ifdef FEAT_PROFILE
18502 if (do_profiling)
18503 {
18504 if (!fp->uf_profiling && has_profiling(FALSE, fp->uf_name, NULL))
18505 func_do_profile(fp);
18506 if (fp->uf_profiling
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +000018507 || (fc.caller != NULL && &fc.caller->func->uf_profiling))
Bram Moolenaar05159a02005-02-26 23:04:13 +000018508 {
18509 ++fp->uf_tm_count;
18510 profile_start(&fp->uf_tm_start);
18511 profile_zero(&fp->uf_tm_children);
18512 }
18513 script_prof_save(&wait_start);
18514 }
18515#endif
18516
Bram Moolenaar071d4272004-06-13 20:20:40 +000018517 save_current_SID = current_SID;
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000018518 current_SID = fp->uf_script_ID;
Bram Moolenaar071d4272004-06-13 20:20:40 +000018519 save_did_emsg = did_emsg;
18520 did_emsg = FALSE;
18521
18522 /* call do_cmdline() to execute the lines */
18523 do_cmdline(NULL, get_func_line, (void *)&fc,
18524 DOCMD_NOWAIT|DOCMD_VERBOSE|DOCMD_REPEAT);
18525
18526 --RedrawingDisabled;
18527
18528 /* when the function was aborted because of an error, return -1 */
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000018529 if ((did_emsg && (fp->uf_flags & FC_ABORT)) || rettv->v_type == VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +000018530 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000018531 clear_tv(rettv);
18532 rettv->v_type = VAR_NUMBER;
18533 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000018534 }
18535
Bram Moolenaar05159a02005-02-26 23:04:13 +000018536#ifdef FEAT_PROFILE
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +000018537 if (fp->uf_profiling || (fc.caller != NULL && &fc.caller->func->uf_profiling))
Bram Moolenaar05159a02005-02-26 23:04:13 +000018538 {
18539 profile_end(&fp->uf_tm_start);
18540 profile_sub_wait(&wait_start, &fp->uf_tm_start);
18541 profile_add(&fp->uf_tm_total, &fp->uf_tm_start);
18542 profile_add(&fp->uf_tm_self, &fp->uf_tm_start);
18543 profile_sub(&fp->uf_tm_self, &fp->uf_tm_children);
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +000018544 if (fc.caller != NULL && &fc.caller->func->uf_profiling)
Bram Moolenaar05159a02005-02-26 23:04:13 +000018545 {
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +000018546 profile_add(&fc.caller->func->uf_tm_children, &fp->uf_tm_start);
18547 profile_add(&fc.caller->func->uf_tml_children, &fp->uf_tm_start);
Bram Moolenaar05159a02005-02-26 23:04:13 +000018548 }
18549 }
18550#endif
18551
Bram Moolenaar071d4272004-06-13 20:20:40 +000018552 /* when being verbose, mention the return value */
18553 if (p_verbose >= 12)
18554 {
Bram Moolenaar071d4272004-06-13 20:20:40 +000018555 ++no_wait_return;
Bram Moolenaar54ee7752005-05-31 22:22:17 +000018556 verbose_enter_scroll();
Bram Moolenaar071d4272004-06-13 20:20:40 +000018557
Bram Moolenaar071d4272004-06-13 20:20:40 +000018558 if (aborting())
Bram Moolenaar555b2802005-05-19 21:08:39 +000018559 smsg((char_u *)_("%s aborted"), sourcing_name);
Bram Moolenaarc70646c2005-01-04 21:52:38 +000018560 else if (fc.rettv->v_type == VAR_NUMBER)
Bram Moolenaar555b2802005-05-19 21:08:39 +000018561 smsg((char_u *)_("%s returning #%ld"), sourcing_name,
18562 (long)fc.rettv->vval.v_number);
Bram Moolenaar758711c2005-02-02 23:11:38 +000018563 else
Bram Moolenaar071d4272004-06-13 20:20:40 +000018564 {
Bram Moolenaar758711c2005-02-02 23:11:38 +000018565 char_u buf[MSG_BUF_LEN];
18566 char_u numbuf[NUMBUFLEN];
18567 char_u *tofree;
18568
Bram Moolenaar555b2802005-05-19 21:08:39 +000018569 /* The value may be very long. Skip the middle part, so that we
18570 * have some idea how it starts and ends. smsg() would always
18571 * truncate it at the end. */
Bram Moolenaar758711c2005-02-02 23:11:38 +000018572 trunc_string(tv2string(fc.rettv, &tofree, numbuf),
Bram Moolenaar34cdc3e2005-05-18 22:24:46 +000018573 buf, MSG_BUF_CLEN);
Bram Moolenaar555b2802005-05-19 21:08:39 +000018574 smsg((char_u *)_("%s returning %s"), sourcing_name, buf);
Bram Moolenaar758711c2005-02-02 23:11:38 +000018575 vim_free(tofree);
Bram Moolenaar071d4272004-06-13 20:20:40 +000018576 }
18577 msg_puts((char_u *)"\n"); /* don't overwrite this either */
Bram Moolenaar54ee7752005-05-31 22:22:17 +000018578
18579 verbose_leave_scroll();
Bram Moolenaar071d4272004-06-13 20:20:40 +000018580 --no_wait_return;
18581 }
18582
18583 vim_free(sourcing_name);
18584 sourcing_name = save_sourcing_name;
18585 sourcing_lnum = save_sourcing_lnum;
18586 current_SID = save_current_SID;
Bram Moolenaar05159a02005-02-26 23:04:13 +000018587#ifdef FEAT_PROFILE
18588 if (do_profiling)
18589 script_prof_restore(&wait_start);
18590#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000018591
18592 if (p_verbose >= 12 && sourcing_name != NULL)
18593 {
18594 ++no_wait_return;
Bram Moolenaar54ee7752005-05-31 22:22:17 +000018595 verbose_enter_scroll();
18596
Bram Moolenaar555b2802005-05-19 21:08:39 +000018597 smsg((char_u *)_("continuing in %s"), sourcing_name);
Bram Moolenaar071d4272004-06-13 20:20:40 +000018598 msg_puts((char_u *)"\n"); /* don't overwrite this either */
Bram Moolenaar54ee7752005-05-31 22:22:17 +000018599
18600 verbose_leave_scroll();
Bram Moolenaar071d4272004-06-13 20:20:40 +000018601 --no_wait_return;
18602 }
18603
18604 did_emsg |= save_did_emsg;
Bram Moolenaar9a50b1b2005-06-27 22:48:21 +000018605 current_funccal = fc.caller;
Bram Moolenaar071d4272004-06-13 20:20:40 +000018606
Bram Moolenaar33570922005-01-25 22:26:29 +000018607 /* The a: variables typevals were not alloced, only free the allocated
18608 * variables. */
18609 vars_clear_ext(&fc.l_avars.dv_hashtab, FALSE);
18610
18611 vars_clear(&fc.l_vars.dv_hashtab); /* free all l: variables */
Bram Moolenaar071d4272004-06-13 20:20:40 +000018612 --depth;
18613}
18614
18615/*
Bram Moolenaar33570922005-01-25 22:26:29 +000018616 * Add a number variable "name" to dict "dp" with value "nr".
18617 */
18618 static void
18619add_nr_var(dp, v, name, nr)
18620 dict_T *dp;
18621 dictitem_T *v;
18622 char *name;
18623 varnumber_T nr;
18624{
18625 STRCPY(v->di_key, name);
18626 v->di_flags = DI_FLAGS_RO | DI_FLAGS_FIX;
18627 hash_add(&dp->dv_hashtab, DI2HIKEY(v));
18628 v->di_tv.v_type = VAR_NUMBER;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000018629 v->di_tv.v_lock = VAR_FIXED;
Bram Moolenaar33570922005-01-25 22:26:29 +000018630 v->di_tv.vval.v_number = nr;
18631}
18632
18633/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000018634 * ":return [expr]"
18635 */
18636 void
18637ex_return(eap)
18638 exarg_T *eap;
18639{
18640 char_u *arg = eap->arg;
Bram Moolenaar33570922005-01-25 22:26:29 +000018641 typval_T rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000018642 int returning = FALSE;
18643
18644 if (current_funccal == NULL)
18645 {
18646 EMSG(_("E133: :return not inside a function"));
18647 return;
18648 }
18649
18650 if (eap->skip)
18651 ++emsg_skip;
18652
18653 eap->nextcmd = NULL;
18654 if ((*arg != NUL && *arg != '|' && *arg != '\n')
Bram Moolenaarc70646c2005-01-04 21:52:38 +000018655 && eval0(arg, &rettv, &eap->nextcmd, !eap->skip) != FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000018656 {
18657 if (!eap->skip)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000018658 returning = do_return(eap, FALSE, TRUE, &rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000018659 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000018660 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000018661 }
18662 /* It's safer to return also on error. */
18663 else if (!eap->skip)
18664 {
18665 /*
18666 * Return unless the expression evaluation has been cancelled due to an
18667 * aborting error, an interrupt, or an exception.
18668 */
18669 if (!aborting())
18670 returning = do_return(eap, FALSE, TRUE, NULL);
18671 }
18672
18673 /* When skipping or the return gets pending, advance to the next command
18674 * in this line (!returning). Otherwise, ignore the rest of the line.
18675 * Following lines will be ignored by get_func_line(). */
18676 if (returning)
18677 eap->nextcmd = NULL;
18678 else if (eap->nextcmd == NULL) /* no argument */
18679 eap->nextcmd = check_nextcmd(arg);
18680
18681 if (eap->skip)
18682 --emsg_skip;
18683}
18684
18685/*
18686 * Return from a function. Possibly makes the return pending. Also called
18687 * for a pending return at the ":endtry" or after returning from an extra
18688 * do_cmdline(). "reanimate" is used in the latter case. "is_cmd" is set
Bram Moolenaar33570922005-01-25 22:26:29 +000018689 * when called due to a ":return" command. "rettv" may point to a typval_T
Bram Moolenaarc70646c2005-01-04 21:52:38 +000018690 * with the return rettv. Returns TRUE when the return can be carried out,
Bram Moolenaar071d4272004-06-13 20:20:40 +000018691 * FALSE when the return gets pending.
18692 */
18693 int
Bram Moolenaarc70646c2005-01-04 21:52:38 +000018694do_return(eap, reanimate, is_cmd, rettv)
Bram Moolenaar071d4272004-06-13 20:20:40 +000018695 exarg_T *eap;
18696 int reanimate;
18697 int is_cmd;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000018698 void *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000018699{
18700 int idx;
18701 struct condstack *cstack = eap->cstack;
18702
18703 if (reanimate)
18704 /* Undo the return. */
18705 current_funccal->returned = FALSE;
18706
18707 /*
18708 * Cleanup (and inactivate) conditionals, but stop when a try conditional
18709 * not in its finally clause (which then is to be executed next) is found.
18710 * In this case, make the ":return" pending for execution at the ":endtry".
18711 * Otherwise, return normally.
18712 */
18713 idx = cleanup_conditionals(eap->cstack, 0, TRUE);
18714 if (idx >= 0)
18715 {
18716 cstack->cs_pending[idx] = CSTP_RETURN;
18717
18718 if (!is_cmd && !reanimate)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000018719 /* A pending return again gets pending. "rettv" points to an
18720 * allocated variable with the rettv of the original ":return"'s
Bram Moolenaar071d4272004-06-13 20:20:40 +000018721 * argument if present or is NULL else. */
Bram Moolenaarc70646c2005-01-04 21:52:38 +000018722 cstack->cs_rettv[idx] = rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000018723 else
18724 {
18725 /* When undoing a return in order to make it pending, get the stored
Bram Moolenaarc70646c2005-01-04 21:52:38 +000018726 * return rettv. */
Bram Moolenaar071d4272004-06-13 20:20:40 +000018727 if (reanimate)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000018728 rettv = current_funccal->rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000018729
Bram Moolenaarc70646c2005-01-04 21:52:38 +000018730 if (rettv != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000018731 {
18732 /* Store the value of the pending return. */
Bram Moolenaarc70646c2005-01-04 21:52:38 +000018733 if ((cstack->cs_rettv[idx] = alloc_tv()) != NULL)
Bram Moolenaar33570922005-01-25 22:26:29 +000018734 *(typval_T *)cstack->cs_rettv[idx] = *(typval_T *)rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000018735 else
18736 EMSG(_(e_outofmem));
18737 }
18738 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000018739 cstack->cs_rettv[idx] = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000018740
18741 if (reanimate)
18742 {
18743 /* The pending return value could be overwritten by a ":return"
18744 * without argument in a finally clause; reset the default
18745 * return value. */
Bram Moolenaarc70646c2005-01-04 21:52:38 +000018746 current_funccal->rettv->v_type = VAR_NUMBER;
18747 current_funccal->rettv->vval.v_number = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +000018748 }
18749 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +000018750 report_make_pending(CSTP_RETURN, rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000018751 }
18752 else
18753 {
18754 current_funccal->returned = TRUE;
18755
18756 /* If the return is carried out now, store the return value. For
18757 * a return immediately after reanimation, the value is already
18758 * there. */
Bram Moolenaarc70646c2005-01-04 21:52:38 +000018759 if (!reanimate && rettv != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000018760 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000018761 clear_tv(current_funccal->rettv);
Bram Moolenaar33570922005-01-25 22:26:29 +000018762 *current_funccal->rettv = *(typval_T *)rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000018763 if (!is_cmd)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000018764 vim_free(rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000018765 }
18766 }
18767
18768 return idx < 0;
18769}
18770
18771/*
18772 * Free the variable with a pending return value.
18773 */
18774 void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000018775discard_pending_return(rettv)
18776 void *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000018777{
Bram Moolenaar33570922005-01-25 22:26:29 +000018778 free_tv((typval_T *)rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000018779}
18780
18781/*
Bram Moolenaarc70646c2005-01-04 21:52:38 +000018782 * Generate a return command for producing the value of "rettv". The result
Bram Moolenaar071d4272004-06-13 20:20:40 +000018783 * is an allocated string. Used by report_pending() for verbose messages.
18784 */
18785 char_u *
Bram Moolenaarc70646c2005-01-04 21:52:38 +000018786get_return_cmd(rettv)
18787 void *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000018788{
Bram Moolenaar81bf7082005-02-12 14:31:42 +000018789 char_u *s = NULL;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000018790 char_u *tofree = NULL;
Bram Moolenaar8a283e52005-01-06 23:28:25 +000018791 char_u numbuf[NUMBUFLEN];
Bram Moolenaar071d4272004-06-13 20:20:40 +000018792
Bram Moolenaar81bf7082005-02-12 14:31:42 +000018793 if (rettv != NULL)
Bram Moolenaar33570922005-01-25 22:26:29 +000018794 s = echo_string((typval_T *)rettv, &tofree, numbuf);
Bram Moolenaar81bf7082005-02-12 14:31:42 +000018795 if (s == NULL)
18796 s = (char_u *)"";
Bram Moolenaarc70646c2005-01-04 21:52:38 +000018797
18798 STRCPY(IObuff, ":return ");
18799 STRNCPY(IObuff + 8, s, IOSIZE - 8);
18800 if (STRLEN(s) + 8 >= IOSIZE)
18801 STRCPY(IObuff + IOSIZE - 4, "...");
18802 vim_free(tofree);
18803 return vim_strsave(IObuff);
Bram Moolenaar071d4272004-06-13 20:20:40 +000018804}
18805
18806/*
18807 * Get next function line.
18808 * Called by do_cmdline() to get the next line.
18809 * Returns allocated string, or NULL for end of function.
18810 */
18811/* ARGSUSED */
18812 char_u *
18813get_func_line(c, cookie, indent)
18814 int c; /* not used */
18815 void *cookie;
18816 int indent; /* not used */
18817{
Bram Moolenaar33570922005-01-25 22:26:29 +000018818 funccall_T *fcp = (funccall_T *)cookie;
Bram Moolenaar05159a02005-02-26 23:04:13 +000018819 ufunc_T *fp = fcp->func;
18820 char_u *retval;
18821 garray_T *gap; /* growarray with function lines */
Bram Moolenaar071d4272004-06-13 20:20:40 +000018822
18823 /* If breakpoints have been added/deleted need to check for it. */
18824 if (fcp->dbg_tick != debug_tick)
18825 {
Bram Moolenaar05159a02005-02-26 23:04:13 +000018826 fcp->breakpoint = dbg_find_breakpoint(FALSE, fp->uf_name,
Bram Moolenaar071d4272004-06-13 20:20:40 +000018827 sourcing_lnum);
18828 fcp->dbg_tick = debug_tick;
18829 }
Bram Moolenaar05159a02005-02-26 23:04:13 +000018830#ifdef FEAT_PROFILE
18831 if (do_profiling)
18832 func_line_end(cookie);
18833#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000018834
Bram Moolenaar05159a02005-02-26 23:04:13 +000018835 gap = &fp->uf_lines;
18836 if ((fp->uf_flags & FC_ABORT) && did_emsg && !aborted_in_try())
Bram Moolenaar071d4272004-06-13 20:20:40 +000018837 retval = NULL;
18838 else if (fcp->returned || fcp->linenr >= gap->ga_len)
18839 retval = NULL;
18840 else
18841 {
18842 retval = vim_strsave(((char_u **)(gap->ga_data))[fcp->linenr++]);
18843 sourcing_lnum = fcp->linenr;
Bram Moolenaar05159a02005-02-26 23:04:13 +000018844#ifdef FEAT_PROFILE
18845 if (do_profiling)
18846 func_line_start(cookie);
18847#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000018848 }
18849
18850 /* Did we encounter a breakpoint? */
18851 if (fcp->breakpoint != 0 && fcp->breakpoint <= sourcing_lnum)
18852 {
Bram Moolenaar05159a02005-02-26 23:04:13 +000018853 dbg_breakpoint(fp->uf_name, sourcing_lnum);
Bram Moolenaar071d4272004-06-13 20:20:40 +000018854 /* Find next breakpoint. */
Bram Moolenaar05159a02005-02-26 23:04:13 +000018855 fcp->breakpoint = dbg_find_breakpoint(FALSE, fp->uf_name,
Bram Moolenaar071d4272004-06-13 20:20:40 +000018856 sourcing_lnum);
18857 fcp->dbg_tick = debug_tick;
18858 }
18859
18860 return retval;
18861}
18862
Bram Moolenaar05159a02005-02-26 23:04:13 +000018863#if defined(FEAT_PROFILE) || defined(PROTO)
18864/*
18865 * Called when starting to read a function line.
18866 * "sourcing_lnum" must be correct!
18867 * When skipping lines it may not actually be executed, but we won't find out
18868 * until later and we need to store the time now.
18869 */
18870 void
18871func_line_start(cookie)
18872 void *cookie;
18873{
18874 funccall_T *fcp = (funccall_T *)cookie;
18875 ufunc_T *fp = fcp->func;
18876
18877 if (fp->uf_profiling && sourcing_lnum >= 1
18878 && sourcing_lnum <= fp->uf_lines.ga_len)
18879 {
18880 fp->uf_tml_idx = sourcing_lnum - 1;
18881 fp->uf_tml_execed = FALSE;
18882 profile_start(&fp->uf_tml_start);
18883 profile_zero(&fp->uf_tml_children);
18884 profile_get_wait(&fp->uf_tml_wait);
18885 }
18886}
18887
18888/*
18889 * Called when actually executing a function line.
18890 */
18891 void
18892func_line_exec(cookie)
18893 void *cookie;
18894{
18895 funccall_T *fcp = (funccall_T *)cookie;
18896 ufunc_T *fp = fcp->func;
18897
18898 if (fp->uf_profiling && fp->uf_tml_idx >= 0)
18899 fp->uf_tml_execed = TRUE;
18900}
18901
18902/*
18903 * Called when done with a function line.
18904 */
18905 void
18906func_line_end(cookie)
18907 void *cookie;
18908{
18909 funccall_T *fcp = (funccall_T *)cookie;
18910 ufunc_T *fp = fcp->func;
18911
18912 if (fp->uf_profiling && fp->uf_tml_idx >= 0)
18913 {
18914 if (fp->uf_tml_execed)
18915 {
18916 ++fp->uf_tml_count[fp->uf_tml_idx];
18917 profile_end(&fp->uf_tml_start);
18918 profile_sub_wait(&fp->uf_tml_wait, &fp->uf_tml_start);
18919 profile_add(&fp->uf_tml_self[fp->uf_tml_idx], &fp->uf_tml_start);
18920 profile_add(&fp->uf_tml_total[fp->uf_tml_idx], &fp->uf_tml_start);
18921 profile_sub(&fp->uf_tml_self[fp->uf_tml_idx], &fp->uf_tml_children);
18922 }
18923 fp->uf_tml_idx = -1;
18924 }
18925}
18926#endif
18927
Bram Moolenaar071d4272004-06-13 20:20:40 +000018928/*
18929 * Return TRUE if the currently active function should be ended, because a
18930 * return was encountered or an error occured. Used inside a ":while".
18931 */
18932 int
18933func_has_ended(cookie)
18934 void *cookie;
18935{
Bram Moolenaar33570922005-01-25 22:26:29 +000018936 funccall_T *fcp = (funccall_T *)cookie;
Bram Moolenaar071d4272004-06-13 20:20:40 +000018937
18938 /* Ignore the "abort" flag if the abortion behavior has been changed due to
18939 * an error inside a try conditional. */
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000018940 return (((fcp->func->uf_flags & FC_ABORT) && did_emsg && !aborted_in_try())
Bram Moolenaar071d4272004-06-13 20:20:40 +000018941 || fcp->returned);
18942}
18943
18944/*
18945 * return TRUE if cookie indicates a function which "abort"s on errors.
18946 */
18947 int
18948func_has_abort(cookie)
18949 void *cookie;
18950{
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000018951 return ((funccall_T *)cookie)->func->uf_flags & FC_ABORT;
Bram Moolenaar071d4272004-06-13 20:20:40 +000018952}
18953
18954#if defined(FEAT_VIMINFO) || defined(FEAT_SESSION)
18955typedef enum
18956{
18957 VAR_FLAVOUR_DEFAULT,
18958 VAR_FLAVOUR_SESSION,
18959 VAR_FLAVOUR_VIMINFO
18960} var_flavour_T;
18961
18962static var_flavour_T var_flavour __ARGS((char_u *varname));
18963
18964 static var_flavour_T
18965var_flavour(varname)
18966 char_u *varname;
18967{
18968 char_u *p = varname;
18969
18970 if (ASCII_ISUPPER(*p))
18971 {
18972 while (*(++p))
18973 if (ASCII_ISLOWER(*p))
18974 return VAR_FLAVOUR_SESSION;
18975 return VAR_FLAVOUR_VIMINFO;
18976 }
18977 else
18978 return VAR_FLAVOUR_DEFAULT;
18979}
18980#endif
18981
18982#if defined(FEAT_VIMINFO) || defined(PROTO)
18983/*
18984 * Restore global vars that start with a capital from the viminfo file
18985 */
18986 int
18987read_viminfo_varlist(virp, writing)
18988 vir_T *virp;
18989 int writing;
18990{
18991 char_u *tab;
18992 int is_string = FALSE;
Bram Moolenaar33570922005-01-25 22:26:29 +000018993 typval_T tv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000018994
18995 if (!writing && (find_viminfo_parameter('!') != NULL))
18996 {
18997 tab = vim_strchr(virp->vir_line + 1, '\t');
18998 if (tab != NULL)
18999 {
19000 *tab++ = '\0'; /* isolate the variable name */
19001 if (*tab == 'S') /* string var */
19002 is_string = TRUE;
19003
19004 tab = vim_strchr(tab, '\t');
19005 if (tab != NULL)
19006 {
Bram Moolenaar071d4272004-06-13 20:20:40 +000019007 if (is_string)
19008 {
Bram Moolenaar3d60ec22005-01-05 22:19:46 +000019009 tv.v_type = VAR_STRING;
19010 tv.vval.v_string = viminfo_readstring(virp,
Bram Moolenaar071d4272004-06-13 20:20:40 +000019011 (int)(tab - virp->vir_line + 1), TRUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +000019012 }
19013 else
19014 {
Bram Moolenaar3d60ec22005-01-05 22:19:46 +000019015 tv.v_type = VAR_NUMBER;
19016 tv.vval.v_number = atol((char *)tab + 1);
Bram Moolenaar071d4272004-06-13 20:20:40 +000019017 }
Bram Moolenaar3d60ec22005-01-05 22:19:46 +000019018 set_var(virp->vir_line + 1, &tv, FALSE);
19019 if (is_string)
19020 vim_free(tv.vval.v_string);
Bram Moolenaar071d4272004-06-13 20:20:40 +000019021 }
19022 }
19023 }
19024
19025 return viminfo_readline(virp);
19026}
19027
19028/*
19029 * Write global vars that start with a capital to the viminfo file
19030 */
19031 void
19032write_viminfo_varlist(fp)
19033 FILE *fp;
19034{
Bram Moolenaar33570922005-01-25 22:26:29 +000019035 hashitem_T *hi;
19036 dictitem_T *this_var;
Bram Moolenaara7043832005-01-21 11:56:39 +000019037 int todo;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000019038 char *s;
Bram Moolenaar81bf7082005-02-12 14:31:42 +000019039 char_u *p;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000019040 char_u *tofree;
Bram Moolenaar8a283e52005-01-06 23:28:25 +000019041 char_u numbuf[NUMBUFLEN];
Bram Moolenaar071d4272004-06-13 20:20:40 +000019042
19043 if (find_viminfo_parameter('!') == NULL)
19044 return;
19045
19046 fprintf(fp, _("\n# global variables:\n"));
Bram Moolenaara7043832005-01-21 11:56:39 +000019047
Bram Moolenaar33570922005-01-25 22:26:29 +000019048 todo = globvarht.ht_used;
19049 for (hi = globvarht.ht_array; todo > 0; ++hi)
Bram Moolenaar071d4272004-06-13 20:20:40 +000019050 {
Bram Moolenaara7043832005-01-21 11:56:39 +000019051 if (!HASHITEM_EMPTY(hi))
Bram Moolenaar071d4272004-06-13 20:20:40 +000019052 {
Bram Moolenaara7043832005-01-21 11:56:39 +000019053 --todo;
Bram Moolenaar33570922005-01-25 22:26:29 +000019054 this_var = HI2DI(hi);
19055 if (var_flavour(this_var->di_key) == VAR_FLAVOUR_VIMINFO)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000019056 {
Bram Moolenaar33570922005-01-25 22:26:29 +000019057 switch (this_var->di_tv.v_type)
Bram Moolenaara7043832005-01-21 11:56:39 +000019058 {
19059 case VAR_STRING: s = "STR"; break;
19060 case VAR_NUMBER: s = "NUM"; break;
19061 default: continue;
19062 }
Bram Moolenaar33570922005-01-25 22:26:29 +000019063 fprintf(fp, "!%s\t%s\t", this_var->di_key, s);
Bram Moolenaar81bf7082005-02-12 14:31:42 +000019064 p = echo_string(&this_var->di_tv, &tofree, numbuf);
19065 if (p != NULL)
19066 viminfo_writestring(fp, p);
Bram Moolenaara7043832005-01-21 11:56:39 +000019067 vim_free(tofree);
19068 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000019069 }
19070 }
19071}
19072#endif
19073
19074#if defined(FEAT_SESSION) || defined(PROTO)
19075 int
19076store_session_globals(fd)
19077 FILE *fd;
19078{
Bram Moolenaar33570922005-01-25 22:26:29 +000019079 hashitem_T *hi;
19080 dictitem_T *this_var;
Bram Moolenaara7043832005-01-21 11:56:39 +000019081 int todo;
Bram Moolenaar071d4272004-06-13 20:20:40 +000019082 char_u *p, *t;
19083
Bram Moolenaar33570922005-01-25 22:26:29 +000019084 todo = globvarht.ht_used;
19085 for (hi = globvarht.ht_array; todo > 0; ++hi)
Bram Moolenaar071d4272004-06-13 20:20:40 +000019086 {
Bram Moolenaara7043832005-01-21 11:56:39 +000019087 if (!HASHITEM_EMPTY(hi))
Bram Moolenaar071d4272004-06-13 20:20:40 +000019088 {
Bram Moolenaara7043832005-01-21 11:56:39 +000019089 --todo;
Bram Moolenaar33570922005-01-25 22:26:29 +000019090 this_var = HI2DI(hi);
19091 if ((this_var->di_tv.v_type == VAR_NUMBER
19092 || this_var->di_tv.v_type == VAR_STRING)
19093 && var_flavour(this_var->di_key) == VAR_FLAVOUR_SESSION)
Bram Moolenaar3d60ec22005-01-05 22:19:46 +000019094 {
Bram Moolenaara7043832005-01-21 11:56:39 +000019095 /* Escape special characters with a backslash. Turn a LF and
19096 * CR into \n and \r. */
Bram Moolenaar33570922005-01-25 22:26:29 +000019097 p = vim_strsave_escaped(get_tv_string(&this_var->di_tv),
Bram Moolenaara7043832005-01-21 11:56:39 +000019098 (char_u *)"\\\"\n\r");
19099 if (p == NULL) /* out of memory */
19100 break;
19101 for (t = p; *t != NUL; ++t)
19102 if (*t == '\n')
19103 *t = 'n';
19104 else if (*t == '\r')
19105 *t = 'r';
19106 if ((fprintf(fd, "let %s = %c%s%c",
Bram Moolenaar33570922005-01-25 22:26:29 +000019107 this_var->di_key,
19108 (this_var->di_tv.v_type == VAR_STRING) ? '"'
19109 : ' ',
19110 p,
19111 (this_var->di_tv.v_type == VAR_STRING) ? '"'
19112 : ' ') < 0)
Bram Moolenaara7043832005-01-21 11:56:39 +000019113 || put_eol(fd) == FAIL)
19114 {
19115 vim_free(p);
19116 return FAIL;
19117 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000019118 vim_free(p);
19119 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000019120 }
19121 }
19122 return OK;
19123}
19124#endif
19125
Bram Moolenaar661b1822005-07-28 22:36:45 +000019126/*
19127 * Display script name where an item was last set.
19128 * Should only be invoked when 'verbose' is non-zero.
19129 */
19130 void
19131last_set_msg(scriptID)
19132 scid_T scriptID;
19133{
Bram Moolenaarcafda4f2005-09-06 19:25:11 +000019134 char_u *p;
19135
Bram Moolenaar661b1822005-07-28 22:36:45 +000019136 if (scriptID != 0)
19137 {
Bram Moolenaarcafda4f2005-09-06 19:25:11 +000019138 p = home_replace_save(NULL, get_scriptname(scriptID));
19139 if (p != NULL)
19140 {
19141 verbose_enter();
19142 MSG_PUTS(_("\n\tLast set from "));
19143 MSG_PUTS(p);
19144 vim_free(p);
19145 verbose_leave();
19146 }
Bram Moolenaar661b1822005-07-28 22:36:45 +000019147 }
19148}
19149
Bram Moolenaar071d4272004-06-13 20:20:40 +000019150#endif /* FEAT_EVAL */
19151
19152#if defined(FEAT_MODIFY_FNAME) || defined(FEAT_EVAL) || defined(PROTO)
19153
19154
19155#ifdef WIN3264
19156/*
19157 * Functions for ":8" filename modifier: get 8.3 version of a filename.
19158 */
19159static int get_short_pathname __ARGS((char_u **fnamep, char_u **bufp, int *fnamelen));
19160static int shortpath_for_invalid_fname __ARGS((char_u **fname, char_u **bufp, int *fnamelen));
19161static int shortpath_for_partial __ARGS((char_u **fnamep, char_u **bufp, int *fnamelen));
19162
19163/*
19164 * Get the short pathname of a file.
19165 * Returns 1 on success. *fnamelen is 0 for nonexistant path.
19166 */
19167 static int
19168get_short_pathname(fnamep, bufp, fnamelen)
19169 char_u **fnamep;
19170 char_u **bufp;
19171 int *fnamelen;
19172{
19173 int l,len;
19174 char_u *newbuf;
19175
19176 len = *fnamelen;
19177
19178 l = GetShortPathName(*fnamep, *fnamep, len);
19179 if (l > len - 1)
19180 {
19181 /* If that doesn't work (not enough space), then save the string
19182 * and try again with a new buffer big enough
19183 */
19184 newbuf = vim_strnsave(*fnamep, l);
19185 if (newbuf == NULL)
19186 return 0;
19187
19188 vim_free(*bufp);
19189 *fnamep = *bufp = newbuf;
19190
19191 l = GetShortPathName(*fnamep,*fnamep,l+1);
19192
19193 /* Really should always succeed, as the buffer is big enough */
19194 }
19195
19196 *fnamelen = l;
19197 return 1;
19198}
19199
19200/*
19201 * Create a short path name. Returns the length of the buffer it needs.
19202 * Doesn't copy over the end of the buffer passed in.
19203 */
19204 static int
19205shortpath_for_invalid_fname(fname, bufp, fnamelen)
19206 char_u **fname;
19207 char_u **bufp;
19208 int *fnamelen;
19209{
19210 char_u *s, *p, *pbuf2, *pbuf3;
19211 char_u ch;
Bram Moolenaar75c50c42005-06-04 22:06:24 +000019212 int len, len2, plen, slen;
Bram Moolenaar071d4272004-06-13 20:20:40 +000019213
19214 /* Make a copy */
19215 len2 = *fnamelen;
19216 pbuf2 = vim_strnsave(*fname, len2);
19217 pbuf3 = NULL;
19218
19219 s = pbuf2 + len2 - 1; /* Find the end */
19220 slen = 1;
19221 plen = len2;
19222
Bram Moolenaar1cd871b2004-12-19 22:46:22 +000019223 if (after_pathsep(pbuf2, s + 1))
Bram Moolenaar071d4272004-06-13 20:20:40 +000019224 {
19225 --s;
19226 ++slen;
19227 --plen;
19228 }
19229
19230 do
19231 {
19232 /* Go back one path-seperator */
Bram Moolenaar1cd871b2004-12-19 22:46:22 +000019233 while (s > pbuf2 && !after_pathsep(pbuf2, s + 1))
Bram Moolenaar071d4272004-06-13 20:20:40 +000019234 {
19235 --s;
19236 ++slen;
19237 --plen;
19238 }
19239 if (s <= pbuf2)
19240 break;
19241
19242 /* Remeber the character that is about to be blatted */
19243 ch = *s;
19244 *s = 0; /* get_short_pathname requires a null-terminated string */
19245
19246 /* Try it in situ */
19247 p = pbuf2;
19248 if (!get_short_pathname(&p, &pbuf3, &plen))
19249 {
19250 vim_free(pbuf2);
19251 return -1;
19252 }
19253 *s = ch; /* Preserve the string */
19254 } while (plen == 0);
19255
19256 if (plen > 0)
19257 {
19258 /* Remeber the length of the new string. */
19259 *fnamelen = len = plen + slen;
19260 vim_free(*bufp);
19261 if (len > len2)
19262 {
19263 /* If there's not enough space in the currently allocated string,
19264 * then copy it to a buffer big enough.
19265 */
19266 *fname= *bufp = vim_strnsave(p, len);
19267 if (*fname == NULL)
19268 return -1;
19269 }
19270 else
19271 {
19272 /* Transfer pbuf2 to being the main buffer (it's big enough) */
19273 *fname = *bufp = pbuf2;
19274 if (p != pbuf2)
19275 strncpy(*fname, p, plen);
19276 pbuf2 = NULL;
19277 }
19278 /* Concat the next bit */
19279 strncpy(*fname + plen, s, slen);
19280 (*fname)[len] = '\0';
19281 }
19282 vim_free(pbuf3);
19283 vim_free(pbuf2);
19284 return 0;
19285}
19286
19287/*
19288 * Get a pathname for a partial path.
19289 */
19290 static int
19291shortpath_for_partial(fnamep, bufp, fnamelen)
19292 char_u **fnamep;
19293 char_u **bufp;
19294 int *fnamelen;
19295{
19296 int sepcount, len, tflen;
19297 char_u *p;
19298 char_u *pbuf, *tfname;
19299 int hasTilde;
19300
19301 /* Count up the path seperators from the RHS.. so we know which part
19302 * of the path to return.
19303 */
19304 sepcount = 0;
Bram Moolenaar1cd871b2004-12-19 22:46:22 +000019305 for (p = *fnamep; p < *fnamep + *fnamelen; mb_ptr_adv(p))
Bram Moolenaar071d4272004-06-13 20:20:40 +000019306 if (vim_ispathsep(*p))
19307 ++sepcount;
19308
19309 /* Need full path first (use expand_env() to remove a "~/") */
19310 hasTilde = (**fnamep == '~');
19311 if (hasTilde)
19312 pbuf = tfname = expand_env_save(*fnamep);
19313 else
19314 pbuf = tfname = FullName_save(*fnamep, FALSE);
19315
19316 len = tflen = STRLEN(tfname);
19317
19318 if (!get_short_pathname(&tfname, &pbuf, &len))
19319 return -1;
19320
19321 if (len == 0)
19322 {
19323 /* Don't have a valid filename, so shorten the rest of the
19324 * path if we can. This CAN give us invalid 8.3 filenames, but
19325 * there's not a lot of point in guessing what it might be.
19326 */
19327 len = tflen;
19328 if (shortpath_for_invalid_fname(&tfname, &pbuf, &len) == -1)
19329 return -1;
19330 }
19331
19332 /* Count the paths backward to find the beginning of the desired string. */
19333 for (p = tfname + len - 1; p >= tfname; --p)
Bram Moolenaar1cd871b2004-12-19 22:46:22 +000019334 {
19335#ifdef FEAT_MBYTE
19336 if (has_mbyte)
19337 p -= mb_head_off(tfname, p);
19338#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000019339 if (vim_ispathsep(*p))
19340 {
19341 if (sepcount == 0 || (hasTilde && sepcount == 1))
19342 break;
19343 else
19344 sepcount --;
19345 }
Bram Moolenaar1cd871b2004-12-19 22:46:22 +000019346 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000019347 if (hasTilde)
19348 {
19349 --p;
19350 if (p >= tfname)
19351 *p = '~';
19352 else
19353 return -1;
19354 }
19355 else
19356 ++p;
19357
19358 /* Copy in the string - p indexes into tfname - allocated at pbuf */
19359 vim_free(*bufp);
19360 *fnamelen = (int)STRLEN(p);
19361 *bufp = pbuf;
19362 *fnamep = p;
19363
19364 return 0;
19365}
19366#endif /* WIN3264 */
19367
19368/*
19369 * Adjust a filename, according to a string of modifiers.
19370 * *fnamep must be NUL terminated when called. When returning, the length is
19371 * determined by *fnamelen.
19372 * Returns valid flags.
19373 * When there is an error, *fnamep is set to NULL.
19374 */
19375 int
19376modify_fname(src, usedlen, fnamep, bufp, fnamelen)
19377 char_u *src; /* string with modifiers */
19378 int *usedlen; /* characters after src that are used */
19379 char_u **fnamep; /* file name so far */
19380 char_u **bufp; /* buffer for allocated file name or NULL */
19381 int *fnamelen; /* length of fnamep */
19382{
19383 int valid = 0;
19384 char_u *tail;
19385 char_u *s, *p, *pbuf;
19386 char_u dirname[MAXPATHL];
19387 int c;
19388 int has_fullname = 0;
19389#ifdef WIN3264
19390 int has_shortname = 0;
19391#endif
19392
19393repeat:
19394 /* ":p" - full path/file_name */
19395 if (src[*usedlen] == ':' && src[*usedlen + 1] == 'p')
19396 {
19397 has_fullname = 1;
19398
19399 valid |= VALID_PATH;
19400 *usedlen += 2;
19401
19402 /* Expand "~/path" for all systems and "~user/path" for Unix and VMS */
19403 if ((*fnamep)[0] == '~'
19404#if !defined(UNIX) && !(defined(VMS) && defined(USER_HOME))
19405 && ((*fnamep)[1] == '/'
19406# ifdef BACKSLASH_IN_FILENAME
19407 || (*fnamep)[1] == '\\'
19408# endif
19409 || (*fnamep)[1] == NUL)
19410
19411#endif
19412 )
19413 {
19414 *fnamep = expand_env_save(*fnamep);
19415 vim_free(*bufp); /* free any allocated file name */
19416 *bufp = *fnamep;
19417 if (*fnamep == NULL)
19418 return -1;
19419 }
19420
19421 /* When "/." or "/.." is used: force expansion to get rid of it. */
Bram Moolenaar1cd871b2004-12-19 22:46:22 +000019422 for (p = *fnamep; *p != NUL; mb_ptr_adv(p))
Bram Moolenaar071d4272004-06-13 20:20:40 +000019423 {
19424 if (vim_ispathsep(*p)
19425 && p[1] == '.'
19426 && (p[2] == NUL
19427 || vim_ispathsep(p[2])
19428 || (p[2] == '.'
19429 && (p[3] == NUL || vim_ispathsep(p[3])))))
19430 break;
19431 }
19432
19433 /* FullName_save() is slow, don't use it when not needed. */
19434 if (*p != NUL || !vim_isAbsName(*fnamep))
19435 {
19436 *fnamep = FullName_save(*fnamep, *p != NUL);
19437 vim_free(*bufp); /* free any allocated file name */
19438 *bufp = *fnamep;
19439 if (*fnamep == NULL)
19440 return -1;
19441 }
19442
19443 /* Append a path separator to a directory. */
19444 if (mch_isdir(*fnamep))
19445 {
19446 /* Make room for one or two extra characters. */
19447 *fnamep = vim_strnsave(*fnamep, (int)STRLEN(*fnamep) + 2);
19448 vim_free(*bufp); /* free any allocated file name */
19449 *bufp = *fnamep;
19450 if (*fnamep == NULL)
19451 return -1;
19452 add_pathsep(*fnamep);
19453 }
19454 }
19455
19456 /* ":." - path relative to the current directory */
19457 /* ":~" - path relative to the home directory */
19458 /* ":8" - shortname path - postponed till after */
19459 while (src[*usedlen] == ':'
19460 && ((c = src[*usedlen + 1]) == '.' || c == '~' || c == '8'))
19461 {
19462 *usedlen += 2;
19463 if (c == '8')
19464 {
19465#ifdef WIN3264
19466 has_shortname = 1; /* Postpone this. */
19467#endif
19468 continue;
19469 }
19470 pbuf = NULL;
19471 /* Need full path first (use expand_env() to remove a "~/") */
19472 if (!has_fullname)
19473 {
19474 if (c == '.' && **fnamep == '~')
19475 p = pbuf = expand_env_save(*fnamep);
19476 else
19477 p = pbuf = FullName_save(*fnamep, FALSE);
19478 }
19479 else
19480 p = *fnamep;
19481
19482 has_fullname = 0;
19483
19484 if (p != NULL)
19485 {
19486 if (c == '.')
19487 {
19488 mch_dirname(dirname, MAXPATHL);
19489 s = shorten_fname(p, dirname);
19490 if (s != NULL)
19491 {
19492 *fnamep = s;
19493 if (pbuf != NULL)
19494 {
19495 vim_free(*bufp); /* free any allocated file name */
19496 *bufp = pbuf;
19497 pbuf = NULL;
19498 }
19499 }
19500 }
19501 else
19502 {
19503 home_replace(NULL, p, dirname, MAXPATHL, TRUE);
19504 /* Only replace it when it starts with '~' */
19505 if (*dirname == '~')
19506 {
19507 s = vim_strsave(dirname);
19508 if (s != NULL)
19509 {
19510 *fnamep = s;
19511 vim_free(*bufp);
19512 *bufp = s;
19513 }
19514 }
19515 }
19516 vim_free(pbuf);
19517 }
19518 }
19519
19520 tail = gettail(*fnamep);
19521 *fnamelen = (int)STRLEN(*fnamep);
19522
19523 /* ":h" - head, remove "/file_name", can be repeated */
19524 /* Don't remove the first "/" or "c:\" */
19525 while (src[*usedlen] == ':' && src[*usedlen + 1] == 'h')
19526 {
19527 valid |= VALID_HEAD;
19528 *usedlen += 2;
19529 s = get_past_head(*fnamep);
Bram Moolenaar1cd871b2004-12-19 22:46:22 +000019530 while (tail > s && after_pathsep(s, tail))
Bram Moolenaar071d4272004-06-13 20:20:40 +000019531 --tail;
19532 *fnamelen = (int)(tail - *fnamep);
19533#ifdef VMS
19534 if (*fnamelen > 0)
19535 *fnamelen += 1; /* the path separator is part of the path */
19536#endif
Bram Moolenaar1cd871b2004-12-19 22:46:22 +000019537 while (tail > s && !after_pathsep(s, tail))
19538 mb_ptr_back(*fnamep, tail);
Bram Moolenaar071d4272004-06-13 20:20:40 +000019539 }
19540
19541 /* ":8" - shortname */
19542 if (src[*usedlen] == ':' && src[*usedlen + 1] == '8')
19543 {
19544 *usedlen += 2;
19545#ifdef WIN3264
19546 has_shortname = 1;
19547#endif
19548 }
19549
19550#ifdef WIN3264
19551 /* Check shortname after we have done 'heads' and before we do 'tails'
19552 */
19553 if (has_shortname)
19554 {
19555 pbuf = NULL;
19556 /* Copy the string if it is shortened by :h */
19557 if (*fnamelen < (int)STRLEN(*fnamep))
19558 {
19559 p = vim_strnsave(*fnamep, *fnamelen);
19560 if (p == 0)
19561 return -1;
19562 vim_free(*bufp);
19563 *bufp = *fnamep = p;
19564 }
19565
19566 /* Split into two implementations - makes it easier. First is where
19567 * there isn't a full name already, second is where there is.
19568 */
19569 if (!has_fullname && !vim_isAbsName(*fnamep))
19570 {
19571 if (shortpath_for_partial(fnamep, bufp, fnamelen) == -1)
19572 return -1;
19573 }
19574 else
19575 {
19576 int l;
19577
19578 /* Simple case, already have the full-name
19579 * Nearly always shorter, so try first time. */
19580 l = *fnamelen;
19581 if (!get_short_pathname(fnamep, bufp, &l))
19582 return -1;
19583
19584 if (l == 0)
19585 {
19586 /* Couldn't find the filename.. search the paths.
19587 */
19588 l = *fnamelen;
19589 if (shortpath_for_invalid_fname(fnamep, bufp, &l ) == -1)
19590 return -1;
19591 }
19592 *fnamelen = l;
19593 }
19594 }
19595#endif /* WIN3264 */
19596
19597 /* ":t" - tail, just the basename */
19598 if (src[*usedlen] == ':' && src[*usedlen + 1] == 't')
19599 {
19600 *usedlen += 2;
19601 *fnamelen -= (int)(tail - *fnamep);
19602 *fnamep = tail;
19603 }
19604
19605 /* ":e" - extension, can be repeated */
19606 /* ":r" - root, without extension, can be repeated */
19607 while (src[*usedlen] == ':'
19608 && (src[*usedlen + 1] == 'e' || src[*usedlen + 1] == 'r'))
19609 {
19610 /* find a '.' in the tail:
19611 * - for second :e: before the current fname
19612 * - otherwise: The last '.'
19613 */
19614 if (src[*usedlen + 1] == 'e' && *fnamep > tail)
19615 s = *fnamep - 2;
19616 else
19617 s = *fnamep + *fnamelen - 1;
19618 for ( ; s > tail; --s)
19619 if (s[0] == '.')
19620 break;
19621 if (src[*usedlen + 1] == 'e') /* :e */
19622 {
19623 if (s > tail)
19624 {
19625 *fnamelen += (int)(*fnamep - (s + 1));
19626 *fnamep = s + 1;
19627#ifdef VMS
19628 /* cut version from the extension */
19629 s = *fnamep + *fnamelen - 1;
19630 for ( ; s > *fnamep; --s)
19631 if (s[0] == ';')
19632 break;
19633 if (s > *fnamep)
19634 *fnamelen = s - *fnamep;
19635#endif
19636 }
19637 else if (*fnamep <= tail)
19638 *fnamelen = 0;
19639 }
19640 else /* :r */
19641 {
19642 if (s > tail) /* remove one extension */
19643 *fnamelen = (int)(s - *fnamep);
19644 }
19645 *usedlen += 2;
19646 }
19647
19648 /* ":s?pat?foo?" - substitute */
19649 /* ":gs?pat?foo?" - global substitute */
19650 if (src[*usedlen] == ':'
19651 && (src[*usedlen + 1] == 's'
19652 || (src[*usedlen + 1] == 'g' && src[*usedlen + 2] == 's')))
19653 {
19654 char_u *str;
19655 char_u *pat;
19656 char_u *sub;
19657 int sep;
19658 char_u *flags;
19659 int didit = FALSE;
19660
19661 flags = (char_u *)"";
19662 s = src + *usedlen + 2;
19663 if (src[*usedlen + 1] == 'g')
19664 {
19665 flags = (char_u *)"g";
19666 ++s;
19667 }
19668
19669 sep = *s++;
19670 if (sep)
19671 {
19672 /* find end of pattern */
19673 p = vim_strchr(s, sep);
19674 if (p != NULL)
19675 {
19676 pat = vim_strnsave(s, (int)(p - s));
19677 if (pat != NULL)
19678 {
19679 s = p + 1;
19680 /* find end of substitution */
19681 p = vim_strchr(s, sep);
19682 if (p != NULL)
19683 {
19684 sub = vim_strnsave(s, (int)(p - s));
19685 str = vim_strnsave(*fnamep, *fnamelen);
19686 if (sub != NULL && str != NULL)
19687 {
19688 *usedlen = (int)(p + 1 - src);
19689 s = do_string_sub(str, pat, sub, flags);
19690 if (s != NULL)
19691 {
19692 *fnamep = s;
19693 *fnamelen = (int)STRLEN(s);
19694 vim_free(*bufp);
19695 *bufp = s;
19696 didit = TRUE;
19697 }
19698 }
19699 vim_free(sub);
19700 vim_free(str);
19701 }
19702 vim_free(pat);
19703 }
19704 }
19705 /* after using ":s", repeat all the modifiers */
19706 if (didit)
19707 goto repeat;
19708 }
19709 }
19710
19711 return valid;
19712}
19713
19714/*
19715 * Perform a substitution on "str" with pattern "pat" and substitute "sub".
19716 * "flags" can be "g" to do a global substitute.
19717 * Returns an allocated string, NULL for error.
19718 */
19719 char_u *
19720do_string_sub(str, pat, sub, flags)
19721 char_u *str;
19722 char_u *pat;
19723 char_u *sub;
19724 char_u *flags;
19725{
19726 int sublen;
19727 regmatch_T regmatch;
19728 int i;
19729 int do_all;
19730 char_u *tail;
19731 garray_T ga;
19732 char_u *ret;
19733 char_u *save_cpo;
19734
19735 /* Make 'cpoptions' empty, so that the 'l' flag doesn't work here */
19736 save_cpo = p_cpo;
19737 p_cpo = (char_u *)"";
19738
19739 ga_init2(&ga, 1, 200);
19740
19741 do_all = (flags[0] == 'g');
19742
19743 regmatch.rm_ic = p_ic;
19744 regmatch.regprog = vim_regcomp(pat, RE_MAGIC + RE_STRING);
19745 if (regmatch.regprog != NULL)
19746 {
19747 tail = str;
19748 while (vim_regexec_nl(&regmatch, str, (colnr_T)(tail - str)))
19749 {
19750 /*
19751 * Get some space for a temporary buffer to do the substitution
19752 * into. It will contain:
19753 * - The text up to where the match is.
19754 * - The substituted text.
19755 * - The text after the match.
19756 */
19757 sublen = vim_regsub(&regmatch, sub, tail, FALSE, TRUE, FALSE);
19758 if (ga_grow(&ga, (int)(STRLEN(tail) + sublen -
19759 (regmatch.endp[0] - regmatch.startp[0]))) == FAIL)
19760 {
19761 ga_clear(&ga);
19762 break;
19763 }
19764
19765 /* copy the text up to where the match is */
19766 i = (int)(regmatch.startp[0] - tail);
19767 mch_memmove((char_u *)ga.ga_data + ga.ga_len, tail, (size_t)i);
19768 /* add the substituted text */
19769 (void)vim_regsub(&regmatch, sub, (char_u *)ga.ga_data
19770 + ga.ga_len + i, TRUE, TRUE, FALSE);
19771 ga.ga_len += i + sublen - 1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000019772 /* avoid getting stuck on a match with an empty string */
19773 if (tail == regmatch.endp[0])
19774 {
19775 if (*tail == NUL)
19776 break;
19777 *((char_u *)ga.ga_data + ga.ga_len) = *tail++;
19778 ++ga.ga_len;
Bram Moolenaar071d4272004-06-13 20:20:40 +000019779 }
19780 else
19781 {
19782 tail = regmatch.endp[0];
19783 if (*tail == NUL)
19784 break;
19785 }
19786 if (!do_all)
19787 break;
19788 }
19789
19790 if (ga.ga_data != NULL)
19791 STRCPY((char *)ga.ga_data + ga.ga_len, tail);
19792
19793 vim_free(regmatch.regprog);
19794 }
19795
19796 ret = vim_strsave(ga.ga_data == NULL ? str : (char_u *)ga.ga_data);
19797 ga_clear(&ga);
19798 p_cpo = save_cpo;
19799
19800 return ret;
19801}
19802
19803#endif /* defined(FEAT_MODIFY_FNAME) || defined(FEAT_EVAL) */