xref: /vim-8.2.3635/src/eval.c (revision c0197e28)
1 /* 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 
33 #if SIZEOF_INT <= 3		/* use long if int is smaller than 32 bits */
34 typedef long	varnumber_T;
35 #else
36 typedef int	varnumber_T;
37 #endif
38 
39 /*
40  * Structure to hold an internal variable.
41  */
42 typedef struct
43 {
44     char_u	*var_name;	/* name of variable */
45     char	var_type;	/* VAR_NUMBER or VAR_STRING */
46     union
47     {
48 	varnumber_T	var_number;   /* number value */
49 	char_u		*var_string;  /* string value (Careful: can be NULL!) */
50     } var_val;
51 } var;
52 
53 #define VAR_UNKNOWN 0
54 #define VAR_NUMBER  1
55 #define VAR_STRING  2
56 
57 typedef var *	VAR;
58 
59 /*
60  * All user-defined global variables are stored in "variables".
61  */
62 garray_T	variables = {0, 0, sizeof(var), 4, NULL};
63 
64 /*
65  * Array to hold an array with variables local to each sourced script.
66  */
67 static garray_T	    ga_scripts = {0, 0, sizeof(garray_T), 4, NULL};
68 #define SCRIPT_VARS(id) (((garray_T *)ga_scripts.ga_data)[(id) - 1])
69 
70 
71 #define VAR_ENTRY(idx)	(((VAR)(variables.ga_data))[idx])
72 #define VAR_GAP_ENTRY(idx, gap)	(((VAR)(gap->ga_data))[idx])
73 #define BVAR_ENTRY(idx)	(((VAR)(curbuf->b_vars.ga_data))[idx])
74 #define WVAR_ENTRY(idx)	(((VAR)(curwin->w_vars.ga_data))[idx])
75 
76 static int echo_attr = 0;   /* attributes used for ":echo" */
77 
78 /*
79  * Structure to hold info for a user function.
80  */
81 typedef struct ufunc ufunc_T;
82 
83 struct ufunc
84 {
85     ufunc_T	*next;		/* next function in list */
86     char_u	*name;		/* name of function; can start with <SNR>123_
87 				   (<SNR> is K_SPECIAL KS_EXTRA KE_SNR) */
88     int		varargs;	/* variable nr of arguments */
89     int		flags;
90     int		calls;		/* nr of active calls */
91     garray_T	args;		/* arguments */
92     garray_T	lines;		/* function lines */
93     scid_T	script_ID;	/* ID of script where function was defined,
94 				   used for s: variables */
95 };
96 
97 /* function flags */
98 #define FC_ABORT    1		/* abort function on error */
99 #define FC_RANGE    2		/* function accepts range */
100 
101 /*
102  * All user-defined functions are found in the forward-linked function list.
103  * The first function is pointed at by firstfunc.
104  */
105 ufunc_T		*firstfunc = NULL;
106 
107 #define FUNCARG(fp, j)	((char_u **)(fp->args.ga_data))[j]
108 #define FUNCLINE(fp, j)	((char_u **)(fp->lines.ga_data))[j]
109 
110 /* structure to hold info for a function that is currently being executed. */
111 struct funccall
112 {
113     ufunc_T	*func;		/* function being called */
114     int		linenr;		/* next line to be executed */
115     int		returned;	/* ":return" used */
116     int		argcount;	/* nr of arguments */
117     VAR		argvars;	/* arguments */
118     var		a0_var;		/* "a:0" variable */
119     var		firstline;	/* "a:firstline" variable */
120     var		lastline;	/* "a:lastline" variable */
121     garray_T	l_vars;		/* local function variables */
122     VAR		retvar;		/* return value variable */
123     linenr_T	breakpoint;	/* next line with breakpoint or zero */
124     int		dbg_tick;	/* debug_tick when breakpoint was set */
125     int		level;		/* top nesting level of executed function */
126 };
127 
128 /*
129  * Return the name of the executed function.
130  */
131     char_u *
132 func_name(cookie)
133     void *cookie;
134 {
135     return ((struct funccall *)cookie)->func->name;
136 }
137 
138 /*
139  * Return the address holding the next breakpoint line for a funccall cookie.
140  */
141     linenr_T *
142 func_breakpoint(cookie)
143     void *cookie;
144 {
145     return &((struct funccall *)cookie)->breakpoint;
146 }
147 
148 /*
149  * Return the address holding the debug tick for a funccall cookie.
150  */
151     int *
152 func_dbg_tick(cookie)
153     void *cookie;
154 {
155     return &((struct funccall *)cookie)->dbg_tick;
156 }
157 
158 /*
159  * Return the nesting level for a funccall cookie.
160  */
161     int
162 func_level(cookie)
163     void *cookie;
164 {
165     return ((struct funccall *)cookie)->level;
166 }
167 
168 /* pointer to funccal for currently active function */
169 struct funccall *current_funccal = NULL;
170 
171 /*
172  * Return TRUE when a function was ended by a ":return" command.
173  */
174     int
175 current_func_returned()
176 {
177     return current_funccal->returned;
178 }
179 
180 
181 /*
182  * Array to hold the value of v: variables.
183  */
184 #include "version.h"
185 
186 /* values for flags: */
187 #define VV_COMPAT   1	    /* compatible, also used without "v:" */
188 #define VV_RO	    2	    /* read-only */
189 
190 struct vimvar
191 {
192     char	*name;		/* name of variable, without v: */
193     int		len;		/* length of name */
194     char_u	*val;		/* current value (can also be a number!) */
195     char	type;		/* VAR_NUMBER or VAR_STRING */
196     char	flags;		/* VV_COMPAT and VV_RO */
197 } vimvars[VV_LEN] =
198 {   /* The order here must match the VV_ defines in vim.h! */
199     {"count", sizeof("count") - 1, NULL, VAR_NUMBER, VV_COMPAT+VV_RO},
200     {"count1", sizeof("count1") - 1, NULL, VAR_NUMBER, VV_RO},
201     {"prevcount", sizeof("prevcount") - 1, NULL, VAR_NUMBER, VV_RO},
202     {"errmsg", sizeof("errmsg") - 1, NULL, VAR_STRING, VV_COMPAT},
203     {"warningmsg", sizeof("warningmsg") - 1, NULL, VAR_STRING, 0},
204     {"statusmsg", sizeof("statusmsg") - 1, NULL, VAR_STRING, 0},
205     {"shell_error", sizeof("shell_error") - 1, NULL, VAR_NUMBER,
206 							     VV_COMPAT+VV_RO},
207     {"this_session", sizeof("this_session") - 1, NULL, VAR_STRING, VV_COMPAT},
208     {"version", sizeof("version") - 1, (char_u *)VIM_VERSION_100,
209 						 VAR_NUMBER, VV_COMPAT+VV_RO},
210     {"lnum", sizeof("lnum") - 1, NULL, VAR_NUMBER, VV_RO},
211     {"termresponse", sizeof("termresponse") - 1, NULL, VAR_STRING, VV_RO},
212     {"fname", sizeof("fname") - 1, NULL, VAR_STRING, VV_RO},
213     {"lang", sizeof("lang") - 1, NULL, VAR_STRING, VV_RO},
214     {"lc_time", sizeof("lc_time") - 1, NULL, VAR_STRING, VV_RO},
215     {"ctype", sizeof("ctype") - 1, NULL, VAR_STRING, VV_RO},
216     {"charconvert_from", sizeof("charconvert_from") - 1, NULL, VAR_STRING, VV_RO},
217     {"charconvert_to", sizeof("charconvert_to") - 1, NULL, VAR_STRING, VV_RO},
218     {"fname_in", sizeof("fname_in") - 1, NULL, VAR_STRING, VV_RO},
219     {"fname_out", sizeof("fname_out") - 1, NULL, VAR_STRING, VV_RO},
220     {"fname_new", sizeof("fname_new") - 1, NULL, VAR_STRING, VV_RO},
221     {"fname_diff", sizeof("fname_diff") - 1, NULL, VAR_STRING, VV_RO},
222     {"cmdarg", sizeof("cmdarg") - 1, NULL, VAR_STRING, VV_RO},
223     {"foldstart", sizeof("foldstart") - 1, NULL, VAR_NUMBER, VV_RO},
224     {"foldend", sizeof("foldend") - 1, NULL, VAR_NUMBER, VV_RO},
225     {"folddashes", sizeof("folddashes") - 1, NULL, VAR_STRING, VV_RO},
226     {"foldlevel", sizeof("foldlevel") - 1, NULL, VAR_NUMBER, VV_RO},
227     {"progname", sizeof("progname") - 1, NULL, VAR_STRING, VV_RO},
228     {"servername", sizeof("servername") - 1, NULL, VAR_STRING, VV_RO},
229     {"dying", sizeof("dying") - 1, NULL, VAR_NUMBER, VV_RO},
230     {"exception", sizeof("exception") - 1, NULL, VAR_STRING, VV_RO},
231     {"throwpoint", sizeof("throwpoint") - 1, NULL, VAR_STRING, VV_RO},
232     {"register", sizeof("register") - 1, NULL, VAR_STRING, VV_RO},
233     {"cmdbang", sizeof("cmdbang") - 1, NULL, VAR_NUMBER, VV_RO},
234     {"insertmode", sizeof("insertmode") - 1, NULL, VAR_STRING, VV_RO},
235 };
236 
237 static int eval0 __ARGS((char_u *arg,  VAR retvar, char_u **nextcmd, int evaluate));
238 static int eval1 __ARGS((char_u **arg, VAR retvar, int evaluate));
239 static int eval2 __ARGS((char_u **arg, VAR retvar, int evaluate));
240 static int eval3 __ARGS((char_u **arg, VAR retvar, int evaluate));
241 static int eval4 __ARGS((char_u **arg, VAR retvar, int evaluate));
242 static int eval5 __ARGS((char_u **arg, VAR retvar, int evaluate));
243 static int eval6 __ARGS((char_u **arg, VAR retvar, int evaluate));
244 static int eval7 __ARGS((char_u **arg, VAR retvar, int evaluate));
245 static int get_option_var __ARGS((char_u **arg, VAR retvar, int evaluate));
246 static int get_string_var __ARGS((char_u **arg, VAR retvar, int evaluate));
247 static int get_lit_string_var __ARGS((char_u **arg, VAR retvar, int evaluate));
248 static int get_env_var __ARGS((char_u **arg, VAR retvar, int evaluate));
249 static int find_internal_func __ARGS((char_u *name));
250 static int get_func_var __ARGS((char_u *name, int len, VAR retvar, char_u **arg, linenr_T firstline, linenr_T lastline, int *doesrange, int evaluate));
251 static int call_func __ARGS((char_u *name, int len, VAR retvar, int argcount, VAR argvars, linenr_T firstline, linenr_T lastline, int *doesrange, int evaluate));
252 static void f_append __ARGS((VAR argvars, VAR retvar));
253 static void f_argc __ARGS((VAR argvars, VAR retvar));
254 static void f_argidx __ARGS((VAR argvars, VAR retvar));
255 static void f_argv __ARGS((VAR argvars, VAR retvar));
256 static void f_browse __ARGS((VAR argvars, VAR retvar));
257 static buf_T *find_buffer __ARGS((VAR avar));
258 static void f_bufexists __ARGS((VAR argvars, VAR retvar));
259 static void f_buflisted __ARGS((VAR argvars, VAR retvar));
260 static void f_bufloaded __ARGS((VAR argvars, VAR retvar));
261 static buf_T *get_buf_var __ARGS((VAR avar));
262 static void f_bufname __ARGS((VAR argvars, VAR retvar));
263 static void f_bufnr __ARGS((VAR argvars, VAR retvar));
264 static void f_bufwinnr __ARGS((VAR argvars, VAR retvar));
265 static void f_byte2line __ARGS((VAR argvars, VAR retvar));
266 static void f_byteidx __ARGS((VAR argvars, VAR retvar));
267 static void f_char2nr __ARGS((VAR argvars, VAR retvar));
268 static void f_cindent __ARGS((VAR argvars, VAR retvar));
269 static void f_col __ARGS((VAR argvars, VAR retvar));
270 static void f_confirm __ARGS((VAR argvars, VAR retvar));
271 static void f_cscope_connection __ARGS((VAR argvars, VAR retvar));
272 static void f_cursor __ARGS((VAR argsvars, VAR retvar));
273 static void f_delete __ARGS((VAR argvars, VAR retvar));
274 static void f_did_filetype __ARGS((VAR argvars, VAR retvar));
275 static void f_escape __ARGS((VAR argvars, VAR retvar));
276 static void f_eventhandler __ARGS((VAR argvars, VAR retvar));
277 static void f_executable __ARGS((VAR argvars, VAR retvar));
278 static void f_exists __ARGS((VAR argvars, VAR retvar));
279 static void f_expand __ARGS((VAR argvars, VAR retvar));
280 static void f_filereadable __ARGS((VAR argvars, VAR retvar));
281 static void f_filewritable __ARGS((VAR argvars, VAR retvar));
282 static void f_finddir __ARGS((VAR argvars, VAR retvar));
283 static void f_findfile __ARGS((VAR argvars, VAR retvar));
284 static void f_findfilendir __ARGS((VAR argvars, VAR retvar, int dir));
285 static void f_fnamemodify __ARGS((VAR argvars, VAR retvar));
286 static void f_foldclosed __ARGS((VAR argvars, VAR retvar));
287 static void f_foldclosedend __ARGS((VAR argvars, VAR retvar));
288 static void foldclosed_both __ARGS((VAR argvars, VAR retvar, int end));
289 static void f_foldlevel __ARGS((VAR argvars, VAR retvar));
290 static void f_foldtext __ARGS((VAR argvars, VAR retvar));
291 static void f_foreground __ARGS((VAR argvars, VAR retvar));
292 static void f_getbufvar __ARGS((VAR argvars, VAR retvar));
293 static void f_getchar __ARGS((VAR argvars, VAR retvar));
294 static void f_getcharmod __ARGS((VAR argvars, VAR retvar));
295 static void f_getcmdline __ARGS((VAR argvars, VAR retvar));
296 static void f_getcmdpos __ARGS((VAR argvars, VAR retvar));
297 static void f_getcwd __ARGS((VAR argvars, VAR retvar));
298 static void f_getfperm __ARGS((VAR argvars, VAR retvar));
299 static void f_getfsize __ARGS((VAR argvars, VAR retvar));
300 static void f_getftime __ARGS((VAR argvars, VAR retvar));
301 static void f_getftype __ARGS((VAR argvars, VAR retvar));
302 static void f_getline __ARGS((VAR argvars, VAR retvar));
303 static void f_getreg __ARGS((VAR argvars, VAR retvar));
304 static void f_getregtype __ARGS((VAR argvars, VAR retvar));
305 static void f_getwinposx __ARGS((VAR argvars, VAR retvar));
306 static void f_getwinposy __ARGS((VAR argvars, VAR retvar));
307 static void f_getwinvar __ARGS((VAR argvars, VAR retvar));
308 static void f_glob __ARGS((VAR argvars, VAR retvar));
309 static void f_globpath __ARGS((VAR argvars, VAR retvar));
310 static void f_has __ARGS((VAR argvars, VAR retvar));
311 static void f_hasmapto __ARGS((VAR argvars, VAR retvar));
312 static void f_histadd __ARGS((VAR argvars, VAR retvar));
313 static void f_histdel __ARGS((VAR argvars, VAR retvar));
314 static void f_histget __ARGS((VAR argvars, VAR retvar));
315 static void f_histnr __ARGS((VAR argvars, VAR retvar));
316 static void f_hlexists __ARGS((VAR argvars, VAR retvar));
317 static void f_hlID __ARGS((VAR argvars, VAR retvar));
318 static void f_hostname __ARGS((VAR argvars, VAR retvar));
319 static void f_iconv __ARGS((VAR argvars, VAR retvar));
320 static void f_indent __ARGS((VAR argvars, VAR retvar));
321 static void f_isdirectory __ARGS((VAR argvars, VAR retvar));
322 static void f_input __ARGS((VAR argvars, VAR retvar));
323 static void f_inputdialog __ARGS((VAR argvars, VAR retvar));
324 static void f_inputrestore __ARGS((VAR argvars, VAR retvar));
325 static void f_inputsave __ARGS((VAR argvars, VAR retvar));
326 static void f_inputsecret __ARGS((VAR argvars, VAR retvar));
327 static void f_last_buffer_nr __ARGS((VAR argvars, VAR retvar));
328 static void f_libcall __ARGS((VAR argvars, VAR retvar));
329 static void f_libcallnr __ARGS((VAR argvars, VAR retvar));
330 static void libcall_common __ARGS((VAR argvars, VAR retvar, int type));
331 static void f_line __ARGS((VAR argvars, VAR retvar));
332 static void f_line2byte __ARGS((VAR argvars, VAR retvar));
333 static void f_lispindent __ARGS((VAR argvars, VAR retvar));
334 static void f_localtime __ARGS((VAR argvars, VAR retvar));
335 static void f_maparg __ARGS((VAR argvars, VAR retvar));
336 static void f_mapcheck __ARGS((VAR argvars, VAR retvar));
337 static void get_maparg __ARGS((VAR argvars, VAR retvar, int exact));
338 static void f_match __ARGS((VAR argvars, VAR retvar));
339 static void f_matchend __ARGS((VAR argvars, VAR retvar));
340 static void f_matchstr __ARGS((VAR argvars, VAR retvar));
341 static void f_mode __ARGS((VAR argvars, VAR retvar));
342 static void f_nextnonblank __ARGS((VAR argvars, VAR retvar));
343 static void f_nr2char __ARGS((VAR argvars, VAR retvar));
344 static void f_prevnonblank __ARGS((VAR argvars, VAR retvar));
345 static void f_setbufvar __ARGS((VAR argvars, VAR retvar));
346 static void f_setcmdpos __ARGS((VAR argvars, VAR retvar));
347 static void f_setwinvar __ARGS((VAR argvars, VAR retvar));
348 static void f_rename __ARGS((VAR argvars, VAR retvar));
349 static void f_resolve __ARGS((VAR argvars, VAR retvar));
350 static void f_search __ARGS((VAR argvars, VAR retvar));
351 static void f_searchpair __ARGS((VAR argvars, VAR retvar));
352 static int get_search_arg __ARGS((VAR varp, int *flagsp));
353 static void f_remote_expr __ARGS((VAR argvars, VAR retvar));
354 static void f_remote_foreground __ARGS((VAR argvars, VAR retvar));
355 static void f_remote_peek __ARGS((VAR argvars, VAR retvar));
356 static void f_remote_read __ARGS((VAR argvars, VAR retvar));
357 static void f_remote_send __ARGS((VAR argvars, VAR retvar));
358 static void f_repeat __ARGS((VAR argvars, VAR retvar));
359 static void f_server2client __ARGS((VAR argvars, VAR retvar));
360 static void f_serverlist __ARGS((VAR argvars, VAR retvar));
361 static void f_setline __ARGS((VAR argvars, VAR retvar));
362 static void f_setreg __ARGS((VAR argvars, VAR retvar));
363 static void f_simplify __ARGS((VAR argvars, VAR retvar));
364 static void find_some_match __ARGS((VAR argvars, VAR retvar, int start));
365 static void f_strftime __ARGS((VAR argvars, VAR retvar));
366 static void f_stridx __ARGS((VAR argvars, VAR retvar));
367 static void f_strlen __ARGS((VAR argvars, VAR retvar));
368 static void f_strpart __ARGS((VAR argvars, VAR retvar));
369 static void f_strridx __ARGS((VAR argvars, VAR retvar));
370 static void f_strtrans __ARGS((VAR argvars, VAR retvar));
371 static void f_synID __ARGS((VAR argvars, VAR retvar));
372 static void f_synIDattr __ARGS((VAR argvars, VAR retvar));
373 static void f_synIDtrans __ARGS((VAR argvars, VAR retvar));
374 static void f_system __ARGS((VAR argvars, VAR retvar));
375 static void f_submatch __ARGS((VAR argvars, VAR retvar));
376 static void f_substitute __ARGS((VAR argvars, VAR retvar));
377 static void f_tempname __ARGS((VAR argvars, VAR retvar));
378 static void f_tolower __ARGS((VAR argvars, VAR retvar));
379 static void f_toupper __ARGS((VAR argvars, VAR retvar));
380 static void f_tr __ARGS((VAR argvars, VAR retvar));
381 static void f_type __ARGS((VAR argvars, VAR retvar));
382 static void f_virtcol __ARGS((VAR argvars, VAR retvar));
383 static void f_visualmode __ARGS((VAR argvars, VAR retvar));
384 static void f_winbufnr __ARGS((VAR argvars, VAR retvar));
385 static void f_wincol __ARGS((VAR argvars, VAR retvar));
386 static void f_winheight __ARGS((VAR argvars, VAR retvar));
387 static void f_winline __ARGS((VAR argvars, VAR retvar));
388 static void f_winnr __ARGS((VAR argvars, VAR retvar));
389 static void f_winrestcmd __ARGS((VAR argvars, VAR retvar));
390 static void f_winwidth __ARGS((VAR argvars, VAR retvar));
391 static win_T *find_win_by_nr __ARGS((VAR vp));
392 static pos_T *var2fpos __ARGS((VAR varp, int lnum));
393 static int get_env_len __ARGS((char_u **arg));
394 static int get_id_len __ARGS((char_u **arg));
395 static int get_func_len __ARGS((char_u **arg, char_u **alias, int evaluate));
396 static char_u *find_name_end __ARGS((char_u *arg, char_u **expr_start, char_u **expr_end));
397 static int eval_isnamec __ARGS((int c));
398 static int find_vim_var __ARGS((char_u *name, int len));
399 static int get_var_var __ARGS((char_u *name, int len, VAR retvar));
400 static VAR alloc_var __ARGS((void));
401 static VAR alloc_string_var __ARGS((char_u *string));
402 static void free_var __ARGS((VAR varp));
403 static void clear_var __ARGS((VAR varp));
404 static long get_var_number __ARGS((VAR varp));
405 static linenr_T get_var_lnum __ARGS((VAR argvars));
406 static char_u *get_var_string __ARGS((VAR varp));
407 static char_u *get_var_string_buf __ARGS((VAR varp, char_u *buf));
408 static VAR find_var __ARGS((char_u *name, int writing));
409 static VAR find_var_in_ga __ARGS((garray_T *gap, char_u *varname));
410 static garray_T *find_var_ga __ARGS((char_u *name, char_u **varname));
411 static void var_free_one __ARGS((VAR v));
412 static void list_one_var __ARGS((VAR v, char_u *prefix));
413 static void list_vim_var __ARGS((int i));
414 static void list_one_var_a __ARGS((char_u *prefix, char_u *name, int type, char_u *string));
415 static void set_var __ARGS((char_u *name, VAR varp));
416 static void copy_var __ARGS((VAR from, VAR to));
417 static char_u *find_option_end __ARGS((char_u **arg, int *opt_flags));
418 static char_u *trans_function_name __ARGS((char_u **pp, int skip, int internal));
419 static int eval_fname_script __ARGS((char_u *p));
420 static int eval_fname_sid __ARGS((char_u *p));
421 static void list_func_head __ARGS((ufunc_T *fp, int indent));
422 static void cat_func_name __ARGS((char_u *buf, ufunc_T *fp));
423 static ufunc_T *find_func __ARGS((char_u *name));
424 static void call_user_func __ARGS((ufunc_T *fp, int argcount, VAR argvars, VAR retvar, linenr_T firstline, linenr_T lastline));
425 
426 /* Magic braces are always enabled, otherwise Vim scripts would not be
427  * portable. */
428 #define FEAT_MAGIC_BRACES
429 
430 #ifdef FEAT_MAGIC_BRACES
431 static char_u * make_expanded_name __ARGS((char_u *in_start,  char_u *expr_start,  char_u *expr_end,  char_u *in_end));
432 #endif
433 
434 /*
435  * Set an internal variable to a string value. Creates the variable if it does
436  * not already exist.
437  */
438     void
439 set_internal_string_var(name, value)
440     char_u	*name;
441     char_u	*value;
442 {
443     char_u  *val;
444     VAR	    varp;
445 
446     val = vim_strsave(value);
447     if (val != NULL)
448     {
449 	varp = alloc_string_var(val);
450 	if (varp != NULL)
451 	{
452 	    set_var(name, varp);
453 	    free_var(varp);
454 	}
455     }
456 }
457 
458 # if defined(FEAT_MBYTE) || defined(PROTO)
459     int
460 eval_charconvert(enc_from, enc_to, fname_from, fname_to)
461     char_u	*enc_from;
462     char_u	*enc_to;
463     char_u	*fname_from;
464     char_u	*fname_to;
465 {
466     int		err = FALSE;
467 
468     set_vim_var_string(VV_CC_FROM, enc_from, -1);
469     set_vim_var_string(VV_CC_TO, enc_to, -1);
470     set_vim_var_string(VV_FNAME_IN, fname_from, -1);
471     set_vim_var_string(VV_FNAME_OUT, fname_to, -1);
472     if (eval_to_bool(p_ccv, &err, NULL, FALSE))
473 	err = TRUE;
474     set_vim_var_string(VV_CC_FROM, NULL, -1);
475     set_vim_var_string(VV_CC_TO, NULL, -1);
476     set_vim_var_string(VV_FNAME_IN, NULL, -1);
477     set_vim_var_string(VV_FNAME_OUT, NULL, -1);
478 
479     if (err)
480 	return FAIL;
481     return OK;
482 }
483 # endif
484 
485 # if defined(FEAT_POSTSCRIPT) || defined(PROTO)
486     int
487 eval_printexpr(fname, args)
488     char_u	*fname;
489     char_u	*args;
490 {
491     int		err = FALSE;
492 
493     set_vim_var_string(VV_FNAME_IN, fname, -1);
494     set_vim_var_string(VV_CMDARG, args, -1);
495     if (eval_to_bool(p_pexpr, &err, NULL, FALSE))
496 	err = TRUE;
497     set_vim_var_string(VV_FNAME_IN, NULL, -1);
498     set_vim_var_string(VV_CMDARG, NULL, -1);
499 
500     if (err)
501     {
502 	mch_remove(fname);
503 	return FAIL;
504     }
505     return OK;
506 }
507 # endif
508 
509 # if defined(FEAT_DIFF) || defined(PROTO)
510     void
511 eval_diff(origfile, newfile, outfile)
512     char_u	*origfile;
513     char_u	*newfile;
514     char_u	*outfile;
515 {
516     int		err = FALSE;
517 
518     set_vim_var_string(VV_FNAME_IN, origfile, -1);
519     set_vim_var_string(VV_FNAME_NEW, newfile, -1);
520     set_vim_var_string(VV_FNAME_OUT, outfile, -1);
521     (void)eval_to_bool(p_dex, &err, NULL, FALSE);
522     set_vim_var_string(VV_FNAME_IN, NULL, -1);
523     set_vim_var_string(VV_FNAME_NEW, NULL, -1);
524     set_vim_var_string(VV_FNAME_OUT, NULL, -1);
525 }
526 
527     void
528 eval_patch(origfile, difffile, outfile)
529     char_u	*origfile;
530     char_u	*difffile;
531     char_u	*outfile;
532 {
533     int		err;
534 
535     set_vim_var_string(VV_FNAME_IN, origfile, -1);
536     set_vim_var_string(VV_FNAME_DIFF, difffile, -1);
537     set_vim_var_string(VV_FNAME_OUT, outfile, -1);
538     (void)eval_to_bool(p_pex, &err, NULL, FALSE);
539     set_vim_var_string(VV_FNAME_IN, NULL, -1);
540     set_vim_var_string(VV_FNAME_DIFF, NULL, -1);
541     set_vim_var_string(VV_FNAME_OUT, NULL, -1);
542 }
543 # endif
544 
545 /*
546  * Top level evaluation function, returning a boolean.
547  * Sets "error" to TRUE if there was an error.
548  * Return TRUE or FALSE.
549  */
550     int
551 eval_to_bool(arg, error, nextcmd, skip)
552     char_u	*arg;
553     int		*error;
554     char_u	**nextcmd;
555     int		skip;	    /* only parse, don't execute */
556 {
557     var		retvar;
558     int		retval = FALSE;
559 
560     if (skip)
561 	++emsg_skip;
562     if (eval0(arg, &retvar, nextcmd, !skip) == FAIL)
563     {
564 	*error = TRUE;
565     }
566     else
567     {
568 	*error = FALSE;
569 	if (!skip)
570 	{
571 	    retval = (get_var_number(&retvar) != 0);
572 	    clear_var(&retvar);
573 	}
574     }
575     if (skip)
576 	--emsg_skip;
577 
578     return retval;
579 }
580 
581 /*
582  * Top level evaluation function, returning a string.  If "skip" is TRUE,
583  * only parsing to "nextcmd" is done, without reporting errors.  Return
584  * pointer to allocated memory, or NULL for failure or when "skip" is TRUE.
585  */
586     char_u *
587 eval_to_string_skip(arg, nextcmd, skip)
588     char_u	*arg;
589     char_u	**nextcmd;
590     int		skip;	    /* only parse, don't execute */
591 {
592     var		retvar;
593     char_u	*retval;
594 
595     if (skip)
596 	++emsg_skip;
597     if (eval0(arg, &retvar, nextcmd, !skip) == FAIL || skip)
598 	retval = NULL;
599     else
600     {
601 	retval = vim_strsave(get_var_string(&retvar));
602 	clear_var(&retvar);
603     }
604     if (skip)
605 	--emsg_skip;
606 
607     return retval;
608 }
609 
610 /*
611  * Skip over an expression at "*pp".
612  * Return FAIL for an error, OK otherwise.
613  */
614     int
615 skip_expr(pp)
616     char_u	**pp;
617 {
618     var		retvar;
619 
620     *pp = skipwhite(*pp);
621     return eval1(pp, &retvar, FALSE);
622 }
623 
624 /*
625  * Top level evaluation function, returning a string.
626  * Return pointer to allocated memory, or NULL for failure.
627  */
628     char_u *
629 eval_to_string(arg, nextcmd)
630     char_u	*arg;
631     char_u	**nextcmd;
632 {
633     var		retvar;
634     char_u	*retval;
635 
636     if (eval0(arg, &retvar, nextcmd, TRUE) == FAIL)
637 	retval = NULL;
638     else
639     {
640 	retval = vim_strsave(get_var_string(&retvar));
641 	clear_var(&retvar);
642     }
643 
644     return retval;
645 }
646 
647 /*
648  * Call eval_to_string() with "sandbox" set and not using local variables.
649  */
650     char_u *
651 eval_to_string_safe(arg, nextcmd)
652     char_u	*arg;
653     char_u	**nextcmd;
654 {
655     char_u	*retval;
656     void	*save_funccalp;
657 
658     save_funccalp = save_funccal();
659     ++sandbox;
660     retval = eval_to_string(arg, nextcmd);
661     --sandbox;
662     restore_funccal(save_funccalp);
663     return retval;
664 }
665 
666 #if 0 /* not used */
667 /*
668  * Top level evaluation function, returning a string.
669  * Advances "arg" to the first non-blank after the evaluated expression.
670  * Return pointer to allocated memory, or NULL for failure.
671  * Doesn't give error messages.
672  */
673     char_u *
674 eval_arg_to_string(arg)
675     char_u	**arg;
676 {
677     var		retvar;
678     char_u	*retval;
679     int		ret;
680 
681     ++emsg_off;
682 
683     ret = eval1(arg, &retvar, TRUE);
684     if (ret == FAIL)
685 	retval = NULL;
686     else
687     {
688 	retval = vim_strsave(get_var_string(&retvar));
689 	clear_var(&retvar);
690     }
691 
692     --emsg_off;
693 
694     return retval;
695 }
696 #endif
697 
698 /*
699  * Top level evaluation function, returning a number.
700  * Evaluates "expr" silently.
701  * Returns -1 for an error.
702  */
703     int
704 eval_to_number(expr)
705     char_u	*expr;
706 {
707     var		retvar;
708     int		retval;
709     char_u	*p = expr;
710 
711     ++emsg_off;
712 
713     if (eval1(&p, &retvar, TRUE) == FAIL)
714 	retval = -1;
715     else
716     {
717 	retval = get_var_number(&retvar);
718 	clear_var(&retvar);
719     }
720     --emsg_off;
721 
722     return retval;
723 }
724 
725 #if (defined(FEAT_USR_CMDS) && defined(FEAT_CMDL_COMPL)) || defined(PROTO)
726 /*
727  * Call some vimL function and return the result as a string
728  * Uses argv[argc] for the function arguments.
729  */
730     char_u *
731 call_vim_function(func, argc, argv, safe)
732     char_u      *func;
733     int		argc;
734     char_u      **argv;
735     int		safe;		/* use the sandbox */
736 {
737     char_u	*retval = NULL;
738     var		retvar;
739     VAR		argvars;
740     long	n;
741     int		len;
742     int		i;
743     int		doesrange;
744     void	*save_funccalp = NULL;
745 
746     argvars = (VAR)alloc((unsigned)(argc * sizeof(var)));
747     if (argvars == NULL)
748 	return NULL;
749 
750     for (i = 0; i < argc; i++)
751     {
752 	/* Pass a NULL or empty argument as an empty string */
753 	if (argv[i] == NULL || *argv[i] == NUL)
754 	{
755 	    argvars[i].var_type = VAR_STRING;
756 	    argvars[i].var_val.var_string = (char_u *)"";
757 	    continue;
758 	}
759 
760 	/* Recognize a number argument, the others must be strings. */
761 	vim_str2nr(argv[i], NULL, &len, TRUE, TRUE, &n, NULL);
762 	if (len != 0 && len == (int)STRLEN(argv[i]))
763 	{
764 	    argvars[i].var_type = VAR_NUMBER;
765 	    argvars[i].var_val.var_number = n;
766 	}
767 	else
768 	{
769 	    argvars[i].var_type = VAR_STRING;
770 	    argvars[i].var_val.var_string = argv[i];
771 	}
772     }
773 
774     if (safe)
775     {
776 	save_funccalp = save_funccal();
777 	++sandbox;
778     }
779 
780     retvar.var_type = VAR_UNKNOWN;	/* clear_var() uses this */
781     if (call_func(func, (int)STRLEN(func), &retvar, argc, argvars,
782 		    curwin->w_cursor.lnum, curwin->w_cursor.lnum,
783 		    &doesrange, TRUE) == OK)
784 	retval = vim_strsave(get_var_string(&retvar));
785 
786     clear_var(&retvar);
787     vim_free(argvars);
788 
789     if (safe)
790     {
791 	--sandbox;
792 	restore_funccal(save_funccalp);
793     }
794     return retval;
795 }
796 #endif
797 
798 /*
799  * Save the current function call pointer, and set it to NULL.
800  * Used when executing autocommands and for ":source".
801  */
802     void *
803 save_funccal()
804 {
805     struct funccall *fc;
806 
807     fc = current_funccal;
808     current_funccal = NULL;
809     return (void *)fc;
810 }
811 
812     void
813 restore_funccal(fc)
814     void *fc;
815 {
816     current_funccal = (struct funccall *)fc;
817 }
818 
819 #ifdef FEAT_FOLDING
820 /*
821  * Evaluate 'foldexpr'.  Returns the foldlevel, and any character preceding
822  * it in "*cp".  Doesn't give error messages.
823  */
824     int
825 eval_foldexpr(arg, cp)
826     char_u	*arg;
827     int		*cp;
828 {
829     var		retvar;
830     int		retval;
831     char_u	*s;
832 
833     ++emsg_off;
834     ++sandbox;
835     *cp = NUL;
836     if (eval0(arg, &retvar, NULL, TRUE) == FAIL)
837 	retval = 0;
838     else
839     {
840 	/* If the result is a number, just return the number. */
841 	if (retvar.var_type == VAR_NUMBER)
842 	    retval = retvar.var_val.var_number;
843 	else if (retvar.var_type == VAR_UNKNOWN
844 		|| retvar.var_val.var_string == NULL)
845 	    retval = 0;
846 	else
847 	{
848 	    /* If the result is a string, check if there is a non-digit before
849 	     * the number. */
850 	    s = retvar.var_val.var_string;
851 	    if (!VIM_ISDIGIT(*s) && *s != '-')
852 		*cp = *s++;
853 	    retval = atol((char *)s);
854 	}
855 	clear_var(&retvar);
856     }
857     --emsg_off;
858     --sandbox;
859 
860     return retval;
861 }
862 #endif
863 
864 #ifdef FEAT_MAGIC_BRACES
865 /*
866  * Expands out the 'magic' {}'s in a variable/function name.
867  * Note that this can call itself recursively, to deal with
868  * constructs like foo{bar}{baz}{bam}
869  * The four pointer arguments point to "foo{expre}ss{ion}bar"
870  *			"in_start"      ^
871  *			"expr_start"	   ^
872  *			"expr_end"		 ^
873  *			"in_end"			    ^
874  *
875  * Returns a new allocated string, which the caller must free.
876  * Returns NULL for failure.
877  */
878     static char_u *
879 make_expanded_name(in_start, expr_start, expr_end, in_end)
880     char_u	*in_start;
881     char_u	*expr_start;
882     char_u	*expr_end;
883     char_u	*in_end;
884 {
885     char_u	c1;
886     char_u	*retval = NULL;
887     char_u	*temp_result;
888     char_u	*nextcmd = NULL;
889 
890     if (expr_end == NULL || in_end == NULL)
891 	return NULL;
892     *expr_start	= NUL;
893     *expr_end = NUL;
894     c1 = *in_end;
895     *in_end = NUL;
896 
897     temp_result = eval_to_string(expr_start + 1, &nextcmd);
898     if (temp_result != NULL && nextcmd == NULL)
899     {
900 	retval = alloc((unsigned)(STRLEN(temp_result) + (expr_start - in_start)
901 						   + (in_end - expr_end) + 1));
902 
903 	if (retval != NULL)
904 	{
905 	    STRCPY(retval, in_start);
906 	    STRCAT(retval, temp_result);
907 	    STRCAT(retval, expr_end + 1);
908 	}
909     }
910     vim_free(temp_result);
911 
912     *in_end = c1;		/* put char back for error messages */
913     *expr_start = '{';
914     *expr_end = '}';
915 
916     if (retval != NULL)
917     {
918 	temp_result = find_name_end(retval, &expr_start, &expr_end);
919 	if (expr_start != NULL)
920 	{
921 	    /* Further expansion! */
922 	    temp_result = make_expanded_name(retval, expr_start,
923 						       expr_end, temp_result);
924 	    vim_free(retval);
925 	    retval = temp_result;
926 	}
927     }
928 
929     return retval;
930 
931 }
932 #endif /* FEAT_MAGIC_BRACES */
933 
934 /*
935  * ":let var = expr"	assignment command.
936  * ":let var"		list one variable value
937  * ":let"		list all variable values
938  */
939     void
940 ex_let(eap)
941     exarg_T	*eap;
942 {
943     char_u	*arg = eap->arg;
944     char_u	*expr;
945     char_u	*name;
946     VAR		varp;
947     var		retvar;
948     char_u	*p;
949     int		c1 = 0, c2;
950     int		i;
951     char_u	*expr_start;
952     char_u	*expr_end;
953     char_u	*name_end;
954 
955     name_end = find_name_end(arg, &expr_start, &expr_end);
956     expr = vim_strchr(name_end, '=');
957     if (expr == NULL)
958     {
959 	if (ends_excmd(*arg))
960 	{
961 	    if (!eap->skip)
962 	    {
963 		/*
964 		 * List all variables.
965 		 */
966 		for (i = 0; i < variables.ga_len && !got_int; ++i)
967 		    if (VAR_ENTRY(i).var_name != NULL)
968 			list_one_var(&VAR_ENTRY(i), (char_u *)"");
969 		for (i = 0; i < curbuf->b_vars.ga_len && !got_int; ++i)
970 		    if (BVAR_ENTRY(i).var_name != NULL)
971 			list_one_var(&BVAR_ENTRY(i), (char_u *)"b:");
972 		for (i = 0; i < curwin->w_vars.ga_len && !got_int; ++i)
973 		    if (WVAR_ENTRY(i).var_name != NULL)
974 			list_one_var(&WVAR_ENTRY(i), (char_u *)"w:");
975 		for (i = 0; i < VV_LEN && !got_int; ++i)
976 		    if (vimvars[i].type == VAR_NUMBER || vimvars[i].val != NULL)
977 			list_vim_var(i);
978 	    }
979 	}
980 	else
981 	{
982 	    int		error = FALSE;
983 
984 	    /*
985 	     * List variables.
986 	     */
987 	    while (!ends_excmd(*arg) && !got_int)
988 	    {
989 		char_u	*temp_string = NULL;
990 		int	arg_len;
991 
992 		/* Find the end of the name. */
993 		name_end = find_name_end(arg, &expr_start, &expr_end);
994 
995 		if (!vim_iswhite(*name_end) && !ends_excmd(*name_end))
996 		{
997 		    emsg_severe = TRUE;
998 		    EMSG(_(e_trailing));
999 		    break;
1000 		}
1001 		if (!error && !eap->skip)
1002 		{
1003 #ifdef FEAT_MAGIC_BRACES
1004 		    if (expr_start != NULL)
1005 		    {
1006 			temp_string = make_expanded_name(arg, expr_start,
1007 							 expr_end, name_end);
1008 			if (temp_string == NULL)
1009 			{
1010 			    /*
1011 			     * Report an invalid expression in braces, unless
1012 			     * the expression evaluation has been cancelled due
1013 			     * to an aborting error, an interrupt, or an
1014 			     * exception.
1015 			     */
1016 			    if (!aborting())
1017 			    {
1018 				emsg_severe = TRUE;
1019 				EMSG2(_(e_invarg2), arg);
1020 				break;
1021 			    }
1022 			    error = TRUE;
1023 			    arg = skipwhite(name_end);
1024 			    continue;
1025 			}
1026 			arg = temp_string;
1027 			arg_len = STRLEN(temp_string);
1028 		    }
1029 		    else
1030 #endif
1031 		    {
1032 			c1 = *name_end;
1033 			*name_end = NUL;
1034 			arg_len = (int)(name_end - arg);
1035 		    }
1036 		    i = find_vim_var(arg, arg_len);
1037 		    if (i >= 0)
1038 			list_vim_var(i);
1039 		    else if (STRCMP("b:changedtick", arg) == 0)
1040 		    {
1041 			char_u	numbuf[NUMBUFLEN];
1042 
1043 			sprintf((char *)numbuf, "%ld",
1044 						 (long)curbuf->b_changedtick);
1045 			list_one_var_a((char_u *)"b:", (char_u *)"changedtick",
1046 							  VAR_NUMBER, numbuf);
1047 		    }
1048 		    else
1049 		    {
1050 			varp = find_var(arg, FALSE);
1051 			if (varp == NULL)
1052 			{
1053 			    /* Skip further arguments but do continue to
1054 			     * search for a trailing command. */
1055 			    EMSG2(_("E106: Unknown variable: \"%s\""), arg);
1056 			    error = TRUE;
1057 			}
1058 			else
1059 			{
1060 			    name = vim_strchr(arg, ':');
1061 			    if (name != NULL)
1062 			    {
1063 				/* "a:" vars have no name stored, use whole
1064 				 * arg */
1065 				if (arg[0] == 'a' && arg[1] == ':')
1066 				    c2 = NUL;
1067 				else
1068 				{
1069 				    c2 = *++name;
1070 				    *name = NUL;
1071 				}
1072 				list_one_var(varp, arg);
1073 				if (c2 != NUL)
1074 				    *name = c2;
1075 			    }
1076 			    else
1077 				list_one_var(varp, (char_u *)"");
1078 			}
1079 		    }
1080 #ifdef FEAT_MAGIC_BRACES
1081 		    if (expr_start != NULL)
1082 			vim_free(temp_string);
1083 		    else
1084 #endif
1085 			*name_end = c1;
1086 		}
1087 		arg = skipwhite(name_end);
1088 	    }
1089 	}
1090 	eap->nextcmd = check_nextcmd(arg);
1091     }
1092     else
1093     {
1094 	if (eap->skip)
1095 	    ++emsg_skip;
1096 	i = eval0(expr + 1, &retvar, &eap->nextcmd, !eap->skip);
1097 	if (eap->skip)
1098 	{
1099 	    if (i != FAIL)
1100 		clear_var(&retvar);
1101 	    --emsg_skip;
1102 	}
1103 	else if (i != FAIL)
1104 	{
1105 	    /*
1106 	     * ":let $VAR = expr": Set environment variable.
1107 	     */
1108 	    if (*arg == '$')
1109 	    {
1110 		int	len;
1111 		int	cc;
1112 
1113 		/* Find the end of the name. */
1114 		++arg;
1115 		name = arg;
1116 		len = get_env_len(&arg);
1117 		if (len == 0)
1118 		    EMSG2(_(e_invarg2), name - 1);
1119 		else
1120 		{
1121 		    if (*skipwhite(arg) != '=')
1122 			EMSG(_(e_letunexp));
1123 		    else
1124 		    {
1125 			cc = name[len];
1126 			name[len] = NUL;
1127 			p = get_var_string(&retvar);
1128 			vim_setenv(name, p);
1129 			if (STRICMP(name, "HOME") == 0)
1130 			    init_homedir();
1131 			else if (didset_vim && STRICMP(name, "VIM") == 0)
1132 			    didset_vim = FALSE;
1133 			else if (didset_vimruntime
1134 					  && STRICMP(name, "VIMRUNTIME") == 0)
1135 			    didset_vimruntime = FALSE;
1136 			name[len] = cc;
1137 		    }
1138 		}
1139 	    }
1140 
1141 	    /*
1142 	     * ":let &option = expr": Set option value.
1143 	     * ":let &l:option = expr": Set local option value.
1144 	     * ":let &g:option = expr": Set global option value.
1145 	     */
1146 	    else if (*arg == '&')
1147 	    {
1148 		int opt_flags;
1149 
1150 		/*
1151 		 * Find the end of the name;
1152 		 */
1153 		p = find_option_end(&arg, &opt_flags);
1154 		if (p == NULL || *skipwhite(p) != '=')
1155 		    EMSG(_(e_letunexp));
1156 		else
1157 		{
1158 		    c1 = *p;
1159 		    *p = NUL;
1160 		    set_option_value(arg, get_var_number(&retvar),
1161 					  get_var_string(&retvar), opt_flags);
1162 		    *p = c1;		    /* put back for error messages */
1163 		}
1164 	    }
1165 
1166 	    /*
1167 	     * ":let @r = expr": Set register contents.
1168 	     */
1169 	    else if (*arg == '@')
1170 	    {
1171 		++arg;
1172 		if (*skipwhite(arg + 1) != '=')
1173 		    EMSG(_(e_letunexp));
1174 		else
1175 		    write_reg_contents(*arg == '@' ? '"' : *arg,
1176 					  get_var_string(&retvar), -1, FALSE);
1177 	    }
1178 
1179 	    /*
1180 	     * ":let var = expr": Set internal variable.
1181 	     */
1182 	    else if (eval_isnamec(*arg) && !VIM_ISDIGIT(*arg))
1183 	    {
1184 		/* Find the end of the name. */
1185 		p = find_name_end(arg, &expr_start, &expr_end);
1186 
1187 		if (*skipwhite(p) != '=')
1188 		    EMSG(_(e_letunexp));
1189 		else if (p - arg == 13
1190 				    && STRNCMP(arg, "b:changedtick", 13) == 0)
1191 		    EMSG2(_(e_readonlyvar), arg);
1192 #ifdef FEAT_MAGIC_BRACES
1193 		else if (expr_start != NULL)
1194 		{
1195 		    char_u  *temp_string;
1196 
1197 		    temp_string = make_expanded_name(arg, expr_start,
1198 								 expr_end, p);
1199 		    if (temp_string == NULL)
1200 		    {
1201 			/*
1202 			 * Report an invalid expression in braces, unless the
1203 			 * expression evaluation has been cancelled due to an
1204 			 * aborting error, an interrupt, or an exception.
1205 			 */
1206 			if (!aborting())
1207 			    EMSG2(_(e_invarg2), arg);
1208 		    }
1209 		    else
1210 		    {
1211 			set_var(temp_string, &retvar);
1212 			vim_free(temp_string);
1213 		    }
1214 		}
1215 #endif
1216 		else
1217 		{
1218 		    c1 = *p;
1219 		    *p = NUL;
1220 		    set_var(arg, &retvar);
1221 		    *p = c1;		/* put char back for error messages */
1222 		}
1223 	    }
1224 
1225 	    else
1226 	    {
1227 		EMSG2(_(e_invarg2), arg);
1228 	    }
1229 
1230 	    clear_var(&retvar);
1231 	}
1232     }
1233 }
1234 
1235 #if defined(FEAT_CMDL_COMPL) || defined(PROTO)
1236 
1237     void
1238 set_context_for_expression(xp, arg, cmdidx)
1239     expand_T	*xp;
1240     char_u	*arg;
1241     cmdidx_T	cmdidx;
1242 {
1243     int		got_eq = FALSE;
1244     int		c;
1245 
1246     xp->xp_context = cmdidx == CMD_let ? EXPAND_USER_VARS
1247 				       : cmdidx == CMD_call ? EXPAND_FUNCTIONS
1248 				       : EXPAND_EXPRESSION;
1249     while ((xp->xp_pattern = vim_strpbrk(arg,
1250 				  (char_u *)"\"'+-*/%.=!?~|&$([<>,#")) != NULL)
1251     {
1252 	c = *xp->xp_pattern;
1253 	if (c == '&')
1254 	{
1255 	    c = xp->xp_pattern[1];
1256 	    if (c == '&')
1257 	    {
1258 		++xp->xp_pattern;
1259 		xp->xp_context = cmdidx != CMD_let || got_eq
1260 					 ? EXPAND_EXPRESSION : EXPAND_NOTHING;
1261 	    }
1262 	    else if (c != ' ')
1263 		xp->xp_context = EXPAND_SETTINGS;
1264 	}
1265 	else if (c == '$')
1266 	{
1267 	    /* environment variable */
1268 	    xp->xp_context = EXPAND_ENV_VARS;
1269 	}
1270 	else if (c == '=')
1271 	{
1272 	    got_eq = TRUE;
1273 	    xp->xp_context = EXPAND_EXPRESSION;
1274 	}
1275 	else if (c == '<'
1276 		&& xp->xp_context == EXPAND_FUNCTIONS
1277 		&& vim_strchr(xp->xp_pattern, '(') == NULL)
1278 	{
1279 	    /* Function name can start with "<SNR>" */
1280 	    break;
1281 	}
1282 	else if (cmdidx != CMD_let || got_eq)
1283 	{
1284 	    if (c == '"')	    /* string */
1285 	    {
1286 		while ((c = *++xp->xp_pattern) != NUL && c != '"')
1287 		    if (c == '\\' && xp->xp_pattern[1] != NUL)
1288 			++xp->xp_pattern;
1289 		xp->xp_context = EXPAND_NOTHING;
1290 	    }
1291 	    else if (c == '\'')	    /* literal string */
1292 	    {
1293 		while ((c = *++xp->xp_pattern) != NUL && c != '\'')
1294 		    /* skip */ ;
1295 		xp->xp_context = EXPAND_NOTHING;
1296 	    }
1297 	    else if (c == '|')
1298 	    {
1299 		if (xp->xp_pattern[1] == '|')
1300 		{
1301 		    ++xp->xp_pattern;
1302 		    xp->xp_context = EXPAND_EXPRESSION;
1303 		}
1304 		else
1305 		    xp->xp_context = EXPAND_COMMANDS;
1306 	    }
1307 	    else
1308 		xp->xp_context = EXPAND_EXPRESSION;
1309 	}
1310 	else
1311 	    xp->xp_context = EXPAND_NOTHING;
1312 	arg = xp->xp_pattern;
1313 	if (*arg != NUL)
1314 	    while ((c = *++arg) != NUL && (c == ' ' || c == '\t'))
1315 		/* skip */ ;
1316     }
1317     xp->xp_pattern = arg;
1318 }
1319 
1320 #endif /* FEAT_CMDL_COMPL */
1321 
1322 /*
1323  * ":1,25call func(arg1, arg2)"	function call.
1324  */
1325     void
1326 ex_call(eap)
1327     exarg_T	*eap;
1328 {
1329     char_u	*arg = eap->arg;
1330     char_u	*startarg;
1331     char_u	*alias;
1332     char_u	*name;
1333     var		retvar;
1334     int		len;
1335     linenr_T	lnum;
1336     int		doesrange;
1337     int		failed = FALSE;
1338 
1339     name = arg;
1340     len = get_func_len(&arg, &alias, !eap->skip);
1341     if (len == 0)
1342 	goto end;
1343     if (alias != NULL)
1344 	name = alias;
1345 
1346     startarg = arg;
1347     retvar.var_type = VAR_UNKNOWN;	/* clear_var() uses this */
1348 
1349     if (*startarg != '(')
1350     {
1351 	EMSG2(_("E107: Missing braces: %s"), name);
1352 	goto end;
1353     }
1354 
1355     /*
1356      * When skipping, evaluate the function once, to find the end of the
1357      * arguments.
1358      * When the function takes a range, this is discovered after the first
1359      * call, and the loop is broken.
1360      */
1361     if (eap->skip)
1362     {
1363 	++emsg_skip;
1364 	lnum = eap->line2;	/* do it once, also with an invalid range */
1365     }
1366     else
1367 	lnum = eap->line1;
1368     for ( ; lnum <= eap->line2; ++lnum)
1369     {
1370 	if (!eap->skip && eap->addr_count > 0)
1371 	{
1372 	    curwin->w_cursor.lnum = lnum;
1373 	    curwin->w_cursor.col = 0;
1374 	}
1375 	arg = startarg;
1376 	if (get_func_var(name, len, &retvar, &arg,
1377 		      eap->line1, eap->line2, &doesrange, !eap->skip) == FAIL)
1378 	{
1379 	    failed = TRUE;
1380 	    break;
1381 	}
1382 	clear_var(&retvar);
1383 	if (doesrange || eap->skip)
1384 	    break;
1385 	/* Stop when immediately aborting on error, or when an interrupt
1386 	 * occurred or an exception was thrown but not caught.  get_func_var()
1387 	 * returned OK, so that the check for trailing characters below is
1388 	 * executed. */
1389 	if (aborting())
1390 	    break;
1391     }
1392     if (eap->skip)
1393 	--emsg_skip;
1394 
1395     if (!failed)
1396     {
1397 	/* Check for trailing illegal characters and a following command. */
1398 	if (!ends_excmd(*arg))
1399 	{
1400 	    emsg_severe = TRUE;
1401 	    EMSG(_(e_trailing));
1402 	}
1403 	else
1404 	    eap->nextcmd = check_nextcmd(arg);
1405     }
1406 
1407 end:
1408     if (alias != NULL)
1409 	vim_free(alias);
1410 }
1411 
1412 /*
1413  * ":unlet[!] var1 ... " command.
1414  */
1415     void
1416 ex_unlet(eap)
1417     exarg_T	*eap;
1418 {
1419     char_u	*arg = eap->arg;
1420     char_u	*name_end;
1421     char_u	cc;
1422     char_u	*expr_start;
1423     char_u	*expr_end;
1424     int		error = FALSE;
1425 
1426     do
1427     {
1428 	/* Find the end of the name. */
1429 	name_end = find_name_end(arg, &expr_start, &expr_end);
1430 
1431 	if (!vim_iswhite(*name_end) && !ends_excmd(*name_end))
1432 	{
1433 	    emsg_severe = TRUE;
1434 	    EMSG(_(e_trailing));
1435 	    break;
1436 	}
1437 
1438 	if (!error && !eap->skip)
1439 	{
1440 #ifdef FEAT_MAGIC_BRACES
1441 	    if (expr_start != NULL)
1442 	    {
1443 		char_u  *temp_string;
1444 
1445 		temp_string = make_expanded_name(arg, expr_start,
1446 							 expr_end, name_end);
1447 		if (temp_string == NULL)
1448 		{
1449 		    /*
1450 		     * Report an invalid expression in braces, unless the
1451 		     * expression evaluation has been cancelled due to an
1452 		     * aborting error, an interrupt, or an exception.
1453 		     */
1454 		    if (!aborting())
1455 		    {
1456 			emsg_severe = TRUE;
1457 			EMSG2(_(e_invarg2), arg);
1458 			break;
1459 		    }
1460 		    error = TRUE;
1461 		}
1462 		else
1463 		{
1464 		    if (do_unlet(temp_string) == FAIL && !eap->forceit)
1465 		    {
1466 			EMSG2(_("E108: No such variable: \"%s\""), temp_string);
1467 			error = TRUE;
1468 		    }
1469 		    vim_free(temp_string);
1470 		}
1471 	    }
1472 	    else
1473 #endif
1474 	    {
1475 		cc = *name_end;
1476 		*name_end = NUL;
1477 
1478 		if (do_unlet(arg) == FAIL && !eap->forceit)
1479 		{
1480 		    EMSG2(_("E108: No such variable: \"%s\""), arg);
1481 		    error = TRUE;
1482 		}
1483 
1484 		*name_end = cc;
1485 	    }
1486 	}
1487 	arg = skipwhite(name_end);
1488     } while (!ends_excmd(*arg));
1489 
1490     eap->nextcmd = check_nextcmd(arg);
1491 }
1492 
1493 /*
1494  * "unlet" a variable.  Return OK if it existed, FAIL if not.
1495  */
1496     int
1497 do_unlet(name)
1498     char_u	*name;
1499 {
1500     VAR		v;
1501 
1502     v = find_var(name, TRUE);
1503     if (v != NULL)
1504     {
1505 	var_free_one(v);
1506 	return OK;
1507     }
1508     return FAIL;
1509 }
1510 
1511 #if (defined(FEAT_MENU) && defined(FEAT_MULTI_LANG)) || defined(PROTO)
1512 /*
1513  * Delete all "menutrans_" variables.
1514  */
1515     void
1516 del_menutrans_vars()
1517 {
1518     int		i;
1519 
1520     for (i = 0; i < variables.ga_len; ++i)
1521 	if (VAR_ENTRY(i).var_name != NULL
1522 		&& STRNCMP(VAR_ENTRY(i).var_name, "menutrans_", 10) == 0)
1523 	    var_free_one(&VAR_ENTRY(i));
1524 }
1525 #endif
1526 
1527 #if defined(FEAT_CMDL_COMPL) || defined(PROTO)
1528 
1529 /*
1530  * Local string buffer for the next two functions to store a variable name
1531  * with its prefix. Allocated in cat_prefix_varname(), freed later in
1532  * get_user_var_name().
1533  */
1534 
1535 static char_u *cat_prefix_varname __ARGS((int prefix, char_u *name));
1536 
1537 static char_u	*varnamebuf = NULL;
1538 static int	varnamebuflen = 0;
1539 
1540 /*
1541  * Function to concatenate a prefix and a variable name.
1542  */
1543     static char_u *
1544 cat_prefix_varname(prefix, name)
1545     int		prefix;
1546     char_u	*name;
1547 {
1548     int		len;
1549 
1550     len = (int)STRLEN(name) + 3;
1551     if (len > varnamebuflen)
1552     {
1553 	vim_free(varnamebuf);
1554 	len += 10;			/* some additional space */
1555 	varnamebuf = alloc(len);
1556 	if (varnamebuf == NULL)
1557 	{
1558 	    varnamebuflen = 0;
1559 	    return NULL;
1560 	}
1561 	varnamebuflen = len;
1562     }
1563     *varnamebuf = prefix;
1564     varnamebuf[1] = ':';
1565     STRCPY(varnamebuf + 2, name);
1566     return varnamebuf;
1567 }
1568 
1569 /*
1570  * Function given to ExpandGeneric() to obtain the list of user defined
1571  * (global/buffer/window/built-in) variable names.
1572  */
1573 /*ARGSUSED*/
1574     char_u *
1575 get_user_var_name(xp, idx)
1576     expand_T	*xp;
1577     int		idx;
1578 {
1579     static int	gidx;
1580     static int	bidx;
1581     static int	widx;
1582     static int	vidx;
1583     char_u	*name;
1584 
1585     if (idx == 0)
1586 	gidx = bidx = widx = vidx = 0;
1587     if (gidx < variables.ga_len)			/* Global variables */
1588     {
1589 	while ((name = VAR_ENTRY(gidx++).var_name) == NULL
1590 		&& gidx < variables.ga_len)
1591 	    /* skip */;
1592 	if (name != NULL)
1593 	{
1594 	    if (STRNCMP("g:", xp->xp_pattern, 2) == 0)
1595 		return cat_prefix_varname('g', name);
1596 	    else
1597 		return name;
1598 	}
1599     }
1600     if (bidx < curbuf->b_vars.ga_len)		/* Current buffer variables */
1601     {
1602 	while ((name = BVAR_ENTRY(bidx++).var_name) == NULL
1603 		&& bidx < curbuf->b_vars.ga_len)
1604 	    /* skip */;
1605 	if (name != NULL)
1606 	    return cat_prefix_varname('b', name);
1607     }
1608     if (bidx == curbuf->b_vars.ga_len)
1609     {
1610 	++bidx;
1611 	return (char_u *)"b:changedtick";
1612     }
1613     if (widx < curwin->w_vars.ga_len)		/* Current window variables */
1614     {
1615 	while ((name = WVAR_ENTRY(widx++).var_name) == NULL
1616 		&& widx < curwin->w_vars.ga_len)
1617 	    /* skip */;
1618 	if (name != NULL)
1619 	    return cat_prefix_varname('w', name);
1620     }
1621     if (vidx < VV_LEN)				      /* Built-in variables */
1622 	return cat_prefix_varname('v', (char_u *)vimvars[vidx++].name);
1623 
1624     vim_free(varnamebuf);
1625     varnamebuf = NULL;
1626     varnamebuflen = 0;
1627     return NULL;
1628 }
1629 
1630 #endif /* FEAT_CMDL_COMPL */
1631 
1632 /*
1633  * types for expressions.
1634  */
1635 typedef enum
1636 {
1637     TYPE_UNKNOWN = 0
1638     , TYPE_EQUAL	/* == */
1639     , TYPE_NEQUAL	/* != */
1640     , TYPE_GREATER	/* >  */
1641     , TYPE_GEQUAL	/* >= */
1642     , TYPE_SMALLER	/* <  */
1643     , TYPE_SEQUAL	/* <= */
1644     , TYPE_MATCH	/* =~ */
1645     , TYPE_NOMATCH	/* !~ */
1646 } exptype_T;
1647 
1648 /*
1649  * The "evaluate" argument: When FALSE, the argument is only parsed but not
1650  * executed.  The function may return OK, but the retvar will be of type
1651  * VAR_UNKNOWN.  The function still returns FAIL for a syntax error.
1652  */
1653 
1654 /*
1655  * Handle zero level expression.
1656  * This calls eval1() and handles error message and nextcmd.
1657  * Return OK or FAIL.
1658  */
1659     static int
1660 eval0(arg, retvar, nextcmd, evaluate)
1661     char_u	*arg;
1662     VAR		retvar;
1663     char_u	**nextcmd;
1664     int		evaluate;
1665 {
1666     int		ret;
1667     char_u	*p;
1668 
1669     p = skipwhite(arg);
1670     ret = eval1(&p, retvar, evaluate);
1671     if (ret == FAIL || !ends_excmd(*p))
1672     {
1673 	if (ret != FAIL)
1674 	    clear_var(retvar);
1675 	/*
1676 	 * Report the invalid expression unless the expression evaluation has
1677 	 * been cancelled due to an aborting error, an interrupt, or an
1678 	 * exception.
1679 	 */
1680 	if (!aborting())
1681 	    EMSG2(_(e_invexpr2), arg);
1682 	ret = FAIL;
1683     }
1684     if (nextcmd != NULL)
1685 	*nextcmd = check_nextcmd(p);
1686 
1687     return ret;
1688 }
1689 
1690 /*
1691  * Handle top level expression:
1692  *	expr1 ? expr0 : expr0
1693  *
1694  * "arg" must point to the first non-white of the expression.
1695  * "arg" is advanced to the next non-white after the recognized expression.
1696  *
1697  * Return OK or FAIL.
1698  */
1699     static int
1700 eval1(arg, retvar, evaluate)
1701     char_u	**arg;
1702     VAR		retvar;
1703     int		evaluate;
1704 {
1705     int		result;
1706     var		var2;
1707 
1708     /*
1709      * Get the first variable.
1710      */
1711     if (eval2(arg, retvar, evaluate) == FAIL)
1712 	return FAIL;
1713 
1714     if ((*arg)[0] == '?')
1715     {
1716 	result = FALSE;
1717 	if (evaluate)
1718 	{
1719 	    if (get_var_number(retvar) != 0)
1720 		result = TRUE;
1721 	    clear_var(retvar);
1722 	}
1723 
1724 	/*
1725 	 * Get the second variable.
1726 	 */
1727 	*arg = skipwhite(*arg + 1);
1728 	if (eval1(arg, retvar, evaluate && result) == FAIL) /* recursive! */
1729 	    return FAIL;
1730 
1731 	/*
1732 	 * Check for the ":".
1733 	 */
1734 	if ((*arg)[0] != ':')
1735 	{
1736 	    EMSG(_("E109: Missing ':' after '?'"));
1737 	    if (evaluate && result)
1738 		clear_var(retvar);
1739 	    return FAIL;
1740 	}
1741 
1742 	/*
1743 	 * Get the third variable.
1744 	 */
1745 	*arg = skipwhite(*arg + 1);
1746 	if (eval1(arg, &var2, evaluate && !result) == FAIL) /* recursive! */
1747 	{
1748 	    if (evaluate && result)
1749 		clear_var(retvar);
1750 	    return FAIL;
1751 	}
1752 	if (evaluate && !result)
1753 	    *retvar = var2;
1754     }
1755 
1756     return OK;
1757 }
1758 
1759 /*
1760  * Handle first level expression:
1761  *	expr2 || expr2 || expr2	    logical OR
1762  *
1763  * "arg" must point to the first non-white of the expression.
1764  * "arg" is advanced to the next non-white after the recognized expression.
1765  *
1766  * Return OK or FAIL.
1767  */
1768     static int
1769 eval2(arg, retvar, evaluate)
1770     char_u	**arg;
1771     VAR		retvar;
1772     int		evaluate;
1773 {
1774     var		var2;
1775     long	result;
1776     int		first;
1777 
1778     /*
1779      * Get the first variable.
1780      */
1781     if (eval3(arg, retvar, evaluate) == FAIL)
1782 	return FAIL;
1783 
1784     /*
1785      * Repeat until there is no following "||".
1786      */
1787     first = TRUE;
1788     result = FALSE;
1789     while ((*arg)[0] == '|' && (*arg)[1] == '|')
1790     {
1791 	if (evaluate && first)
1792 	{
1793 	    if (get_var_number(retvar) != 0)
1794 		result = TRUE;
1795 	    clear_var(retvar);
1796 	    first = FALSE;
1797 	}
1798 
1799 	/*
1800 	 * Get the second variable.
1801 	 */
1802 	*arg = skipwhite(*arg + 2);
1803 	if (eval3(arg, &var2, evaluate && !result) == FAIL)
1804 	    return FAIL;
1805 
1806 	/*
1807 	 * Compute the result.
1808 	 */
1809 	if (evaluate && !result)
1810 	{
1811 	    if (get_var_number(&var2) != 0)
1812 		result = TRUE;
1813 	    clear_var(&var2);
1814 	}
1815 	if (evaluate)
1816 	{
1817 	    retvar->var_type = VAR_NUMBER;
1818 	    retvar->var_val.var_number = result;
1819 	}
1820     }
1821 
1822     return OK;
1823 }
1824 
1825 /*
1826  * Handle second level expression:
1827  *	expr3 && expr3 && expr3	    logical AND
1828  *
1829  * "arg" must point to the first non-white of the expression.
1830  * "arg" is advanced to the next non-white after the recognized expression.
1831  *
1832  * Return OK or FAIL.
1833  */
1834     static int
1835 eval3(arg, retvar, evaluate)
1836     char_u	**arg;
1837     VAR		retvar;
1838     int		evaluate;
1839 {
1840     var		var2;
1841     long	result;
1842     int		first;
1843 
1844     /*
1845      * Get the first variable.
1846      */
1847     if (eval4(arg, retvar, evaluate) == FAIL)
1848 	return FAIL;
1849 
1850     /*
1851      * Repeat until there is no following "&&".
1852      */
1853     first = TRUE;
1854     result = TRUE;
1855     while ((*arg)[0] == '&' && (*arg)[1] == '&')
1856     {
1857 	if (evaluate && first)
1858 	{
1859 	    if (get_var_number(retvar) == 0)
1860 		result = FALSE;
1861 	    clear_var(retvar);
1862 	    first = FALSE;
1863 	}
1864 
1865 	/*
1866 	 * Get the second variable.
1867 	 */
1868 	*arg = skipwhite(*arg + 2);
1869 	if (eval4(arg, &var2, evaluate && result) == FAIL)
1870 	    return FAIL;
1871 
1872 	/*
1873 	 * Compute the result.
1874 	 */
1875 	if (evaluate && result)
1876 	{
1877 	    if (get_var_number(&var2) == 0)
1878 		result = FALSE;
1879 	    clear_var(&var2);
1880 	}
1881 	if (evaluate)
1882 	{
1883 	    retvar->var_type = VAR_NUMBER;
1884 	    retvar->var_val.var_number = result;
1885 	}
1886     }
1887 
1888     return OK;
1889 }
1890 
1891 /*
1892  * Handle third level expression:
1893  *	var1 == var2
1894  *	var1 =~ var2
1895  *	var1 != var2
1896  *	var1 !~ var2
1897  *	var1 > var2
1898  *	var1 >= var2
1899  *	var1 < var2
1900  *	var1 <= var2
1901  *
1902  * "arg" must point to the first non-white of the expression.
1903  * "arg" is advanced to the next non-white after the recognized expression.
1904  *
1905  * Return OK or FAIL.
1906  */
1907     static int
1908 eval4(arg, retvar, evaluate)
1909     char_u	**arg;
1910     VAR		retvar;
1911     int		evaluate;
1912 {
1913     var		var2;
1914     char_u	*p;
1915     int		i;
1916     exptype_T	type = TYPE_UNKNOWN;
1917     int		len = 2;
1918     long	n1, n2;
1919     char_u	*s1, *s2;
1920     char_u	buf1[NUMBUFLEN], buf2[NUMBUFLEN];
1921     regmatch_T	regmatch;
1922     int		ic;
1923     char_u	*save_cpo;
1924 
1925     /*
1926      * Get the first variable.
1927      */
1928     if (eval5(arg, retvar, evaluate) == FAIL)
1929 	return FAIL;
1930 
1931     p = *arg;
1932     switch (p[0])
1933     {
1934 	case '=':   if (p[1] == '=')
1935 			type = TYPE_EQUAL;
1936 		    else if (p[1] == '~')
1937 			type = TYPE_MATCH;
1938 		    break;
1939 	case '!':   if (p[1] == '=')
1940 			type = TYPE_NEQUAL;
1941 		    else if (p[1] == '~')
1942 			type = TYPE_NOMATCH;
1943 		    break;
1944 	case '>':   if (p[1] != '=')
1945 		    {
1946 			type = TYPE_GREATER;
1947 			len = 1;
1948 		    }
1949 		    else
1950 			type = TYPE_GEQUAL;
1951 		    break;
1952 	case '<':   if (p[1] != '=')
1953 		    {
1954 			type = TYPE_SMALLER;
1955 			len = 1;
1956 		    }
1957 		    else
1958 			type = TYPE_SEQUAL;
1959 		    break;
1960     }
1961 
1962     /*
1963      * If there is a comparitive operator, use it.
1964      */
1965     if (type != TYPE_UNKNOWN)
1966     {
1967 	/* extra question mark appended: ignore case */
1968 	if (p[len] == '?')
1969 	{
1970 	    ic = TRUE;
1971 	    ++len;
1972 	}
1973 	/* extra '#' appended: match case */
1974 	else if (p[len] == '#')
1975 	{
1976 	    ic = FALSE;
1977 	    ++len;
1978 	}
1979 	/* nothing appened: use 'ignorecase' */
1980 	else
1981 	    ic = p_ic;
1982 
1983 	/*
1984 	 * Get the second variable.
1985 	 */
1986 	*arg = skipwhite(p + len);
1987 	if (eval5(arg, &var2, evaluate) == FAIL)
1988 	{
1989 	    clear_var(retvar);
1990 	    return FAIL;
1991 	}
1992 
1993 	if (evaluate)
1994 	{
1995 	    /*
1996 	     * If one of the two variables is a number, compare as a number.
1997 	     * When using "=~" or "!~", always compare as string.
1998 	     */
1999 	    if ((retvar->var_type == VAR_NUMBER || var2.var_type == VAR_NUMBER)
2000 		    && type != TYPE_MATCH && type != TYPE_NOMATCH)
2001 	    {
2002 		n1 = get_var_number(retvar);
2003 		n2 = get_var_number(&var2);
2004 		switch (type)
2005 		{
2006 		    case TYPE_EQUAL:    n1 = (n1 == n2); break;
2007 		    case TYPE_NEQUAL:   n1 = (n1 != n2); break;
2008 		    case TYPE_GREATER:  n1 = (n1 > n2); break;
2009 		    case TYPE_GEQUAL:   n1 = (n1 >= n2); break;
2010 		    case TYPE_SMALLER:  n1 = (n1 < n2); break;
2011 		    case TYPE_SEQUAL:   n1 = (n1 <= n2); break;
2012 		    case TYPE_UNKNOWN:
2013 		    case TYPE_MATCH:
2014 		    case TYPE_NOMATCH:  break;  /* avoid gcc warning */
2015 		}
2016 	    }
2017 	    else
2018 	    {
2019 		s1 = get_var_string_buf(retvar, buf1);
2020 		s2 = get_var_string_buf(&var2, buf2);
2021 		if (type != TYPE_MATCH && type != TYPE_NOMATCH)
2022 		    i = ic ? MB_STRICMP(s1, s2) : STRCMP(s1, s2);
2023 		else
2024 		    i = 0;
2025 		n1 = FALSE;
2026 		switch (type)
2027 		{
2028 		    case TYPE_EQUAL:    n1 = (i == 0); break;
2029 		    case TYPE_NEQUAL:   n1 = (i != 0); break;
2030 		    case TYPE_GREATER:  n1 = (i > 0); break;
2031 		    case TYPE_GEQUAL:   n1 = (i >= 0); break;
2032 		    case TYPE_SMALLER:  n1 = (i < 0); break;
2033 		    case TYPE_SEQUAL:   n1 = (i <= 0); break;
2034 
2035 		    case TYPE_MATCH:
2036 		    case TYPE_NOMATCH:
2037 			    /* avoid 'l' flag in 'cpoptions' */
2038 			    save_cpo = p_cpo;
2039 			    p_cpo = (char_u *)"";
2040 			    regmatch.regprog = vim_regcomp(s2,
2041 							RE_MAGIC + RE_STRING);
2042 			    regmatch.rm_ic = ic;
2043 			    if (regmatch.regprog != NULL)
2044 			    {
2045 				n1 = vim_regexec_nl(&regmatch, s1, (colnr_T)0);
2046 				vim_free(regmatch.regprog);
2047 				if (type == TYPE_NOMATCH)
2048 				    n1 = !n1;
2049 			    }
2050 			    p_cpo = save_cpo;
2051 			    break;
2052 
2053 		    case TYPE_UNKNOWN:  break;  /* avoid gcc warning */
2054 		}
2055 	    }
2056 	    clear_var(retvar);
2057 	    clear_var(&var2);
2058 	    retvar->var_type = VAR_NUMBER;
2059 	    retvar->var_val.var_number = n1;
2060 	}
2061     }
2062 
2063     return OK;
2064 }
2065 
2066 /*
2067  * Handle fourth level expression:
2068  *	+	number addition
2069  *	-	number subtraction
2070  *	.	string concatenation
2071  *
2072  * "arg" must point to the first non-white of the expression.
2073  * "arg" is advanced to the next non-white after the recognized expression.
2074  *
2075  * Return OK or FAIL.
2076  */
2077     static int
2078 eval5(arg, retvar, evaluate)
2079     char_u	**arg;
2080     VAR		retvar;
2081     int		evaluate;
2082 {
2083     var		var2;
2084     int		op;
2085     long	n1, n2;
2086     char_u	*s1, *s2;
2087     char_u	buf1[NUMBUFLEN], buf2[NUMBUFLEN];
2088     char_u	*p;
2089 
2090     /*
2091      * Get the first variable.
2092      */
2093     if (eval6(arg, retvar, evaluate) == FAIL)
2094 	return FAIL;
2095 
2096     /*
2097      * Repeat computing, until no '+', '-' or '.' is following.
2098      */
2099     for (;;)
2100     {
2101 	op = **arg;
2102 	if (op != '+' && op != '-' && op != '.')
2103 	    break;
2104 
2105 	/*
2106 	 * Get the second variable.
2107 	 */
2108 	*arg = skipwhite(*arg + 1);
2109 	if (eval6(arg, &var2, evaluate) == FAIL)
2110 	{
2111 	    clear_var(retvar);
2112 	    return FAIL;
2113 	}
2114 
2115 	if (evaluate)
2116 	{
2117 	    /*
2118 	     * Compute the result.
2119 	     */
2120 	    if (op == '.')
2121 	    {
2122 		s1 = get_var_string_buf(retvar, buf1);
2123 		s2 = get_var_string_buf(&var2, buf2);
2124 		op = (int)STRLEN(s1);
2125 		p = alloc((unsigned)(op + STRLEN(s2) + 1));
2126 		if (p != NULL)
2127 		{
2128 		    STRCPY(p, s1);
2129 		    STRCPY(p + op, s2);
2130 		}
2131 		clear_var(retvar);
2132 		retvar->var_type = VAR_STRING;
2133 		retvar->var_val.var_string = p;
2134 	    }
2135 	    else
2136 	    {
2137 		n1 = get_var_number(retvar);
2138 		n2 = get_var_number(&var2);
2139 		clear_var(retvar);
2140 		if (op == '+')
2141 		    n1 = n1 + n2;
2142 		else
2143 		    n1 = n1 - n2;
2144 		retvar->var_type = VAR_NUMBER;
2145 		retvar->var_val.var_number = n1;
2146 	    }
2147 	    clear_var(&var2);
2148 	}
2149     }
2150     return OK;
2151 }
2152 
2153 /*
2154  * Handle fifth level expression:
2155  *	*	number multiplication
2156  *	/	number division
2157  *	%	number modulo
2158  *
2159  * "arg" must point to the first non-white of the expression.
2160  * "arg" is advanced to the next non-white after the recognized expression.
2161  *
2162  * Return OK or FAIL.
2163  */
2164     static int
2165 eval6(arg, retvar, evaluate)
2166     char_u	**arg;
2167     VAR		retvar;
2168     int		evaluate;
2169 {
2170     var		var2;
2171     int		op;
2172     long	n1, n2;
2173 
2174     /*
2175      * Get the first variable.
2176      */
2177     if (eval7(arg, retvar, evaluate) == FAIL)
2178 	return FAIL;
2179 
2180     /*
2181      * Repeat computing, until no '*', '/' or '%' is following.
2182      */
2183     for (;;)
2184     {
2185 	op = **arg;
2186 	if (op != '*' && op != '/' && op != '%')
2187 	    break;
2188 
2189 	if (evaluate)
2190 	{
2191 	    n1 = get_var_number(retvar);
2192 	    clear_var(retvar);
2193 	}
2194 	else
2195 	    n1 = 0;
2196 
2197 	/*
2198 	 * Get the second variable.
2199 	 */
2200 	*arg = skipwhite(*arg + 1);
2201 	if (eval7(arg, &var2, evaluate) == FAIL)
2202 	    return FAIL;
2203 
2204 	if (evaluate)
2205 	{
2206 	    n2 = get_var_number(&var2);
2207 	    clear_var(&var2);
2208 
2209 	    /*
2210 	     * Compute the result.
2211 	     */
2212 	    if (op == '*')
2213 		n1 = n1 * n2;
2214 	    else if (op == '/')
2215 	    {
2216 		if (n2 == 0)	/* give an error message? */
2217 		    n1 = 0x7fffffffL;
2218 		else
2219 		    n1 = n1 / n2;
2220 	    }
2221 	    else
2222 	    {
2223 		if (n2 == 0)	/* give an error message? */
2224 		    n1 = 0;
2225 		else
2226 		    n1 = n1 % n2;
2227 	    }
2228 	    retvar->var_type = VAR_NUMBER;
2229 	    retvar->var_val.var_number = n1;
2230 	}
2231     }
2232 
2233     return OK;
2234 }
2235 
2236 /*
2237  * Handle sixth level expression:
2238  *  number		number constant
2239  *  "string"		string contstant
2240  *  'string'		literal string contstant
2241  *  &option-name	option value
2242  *  @r			register contents
2243  *  identifier		variable value
2244  *  function()		function call
2245  *  $VAR		environment variable
2246  *  (expression)	nested expression
2247  *
2248  *  Also handle:
2249  *  ! in front		logical NOT
2250  *  - in front		unary minus
2251  *  + in front		unary plus (ignored)
2252  *  trailing []		subscript in String
2253  *
2254  * "arg" must point to the first non-white of the expression.
2255  * "arg" is advanced to the next non-white after the recognized expression.
2256  *
2257  * Return OK or FAIL.
2258  */
2259     static int
2260 eval7(arg, retvar, evaluate)
2261     char_u	**arg;
2262     VAR		retvar;
2263     int		evaluate;
2264 {
2265     var		var2;
2266     long	n;
2267     int		len;
2268     char_u	*s;
2269     int		val;
2270     char_u	*start_leader, *end_leader;
2271     int		ret = OK;
2272     char_u	*alias;
2273 
2274     /*
2275      * Initialise variable so that clear_var() can't mistake this for a string
2276      * and free a string that isn't there.
2277      */
2278     retvar->var_type = VAR_UNKNOWN;
2279 
2280     /*
2281      * Skip '!' and '-' characters.  They are handled later.
2282      */
2283     start_leader = *arg;
2284     while (**arg == '!' || **arg == '-' || **arg == '+')
2285 	*arg = skipwhite(*arg + 1);
2286     end_leader = *arg;
2287 
2288     switch (**arg)
2289     {
2290     /*
2291      * Number constant.
2292      */
2293     case '0':
2294     case '1':
2295     case '2':
2296     case '3':
2297     case '4':
2298     case '5':
2299     case '6':
2300     case '7':
2301     case '8':
2302     case '9':
2303 		vim_str2nr(*arg, NULL, &len, TRUE, TRUE, &n, NULL);
2304 		*arg += len;
2305 		if (evaluate)
2306 		{
2307 		    retvar->var_type = VAR_NUMBER;
2308 		    retvar->var_val.var_number = n;
2309 		}
2310 		break;
2311 
2312     /*
2313      * String constant: "string".
2314      */
2315     case '"':	ret = get_string_var(arg, retvar, evaluate);
2316 		break;
2317 
2318     /*
2319      * Literal string constant: 'string'.
2320      */
2321     case '\'':	ret = get_lit_string_var(arg, retvar, evaluate);
2322 		break;
2323 
2324     /*
2325      * Option value: &name
2326      */
2327     case '&':	ret = get_option_var(arg, retvar, evaluate);
2328 		break;
2329 
2330     /*
2331      * Environment variable: $VAR.
2332      */
2333     case '$':	ret = get_env_var(arg, retvar, evaluate);
2334 		break;
2335 
2336     /*
2337      * Register contents: @r.
2338      */
2339     case '@':	++*arg;
2340 		if (evaluate)
2341 		{
2342 		    retvar->var_type = VAR_STRING;
2343 		    retvar->var_val.var_string = get_reg_contents(**arg, FALSE);
2344 		}
2345 		if (**arg != NUL)
2346 		    ++*arg;
2347 		break;
2348 
2349     /*
2350      * nested expression: (expression).
2351      */
2352     case '(':	*arg = skipwhite(*arg + 1);
2353 		ret = eval1(arg, retvar, evaluate);	/* recursive! */
2354 		if (**arg == ')')
2355 		    ++*arg;
2356 		else if (ret == OK)
2357 		{
2358 		    EMSG(_("E110: Missing ')'"));
2359 		    clear_var(retvar);
2360 		    ret = FAIL;
2361 		}
2362 		break;
2363 
2364     /*
2365      * Must be a variable or function name then.
2366      */
2367     default:	s = *arg;
2368 		len = get_func_len(arg, &alias, evaluate);
2369 		if (alias != NULL)
2370 		    s = alias;
2371 
2372 		if (len == 0)
2373 		    ret = FAIL;
2374 		else
2375 		{
2376 		    if (**arg == '(')		/* recursive! */
2377 		    {
2378 			ret = get_func_var(s, len, retvar, arg,
2379 				  curwin->w_cursor.lnum, curwin->w_cursor.lnum,
2380 				  &len, evaluate);
2381 			/* Stop the expression evaluation when immediately
2382 			 * aborting on error, or when an interrupt occurred or
2383 			 * an exception was thrown but not caught. */
2384 			if (aborting())
2385 			{
2386 			    if (ret == OK)
2387 				clear_var(retvar);
2388 			    ret = FAIL;
2389 			}
2390 		    }
2391 		    else if (evaluate)
2392 			ret = get_var_var(s, len, retvar);
2393 		}
2394 
2395 		if (alias != NULL)
2396 		    vim_free(alias);
2397 
2398 		break;
2399     }
2400     *arg = skipwhite(*arg);
2401 
2402     /*
2403      * Handle expr[expr] subscript.
2404      */
2405     if (**arg == '[' && ret == OK)
2406     {
2407 	/*
2408 	 * Get the variable from inside the [].
2409 	 */
2410 	*arg = skipwhite(*arg + 1);
2411 	if (eval1(arg, &var2, evaluate) == FAIL)	/* recursive! */
2412 	{
2413 	    clear_var(retvar);
2414 	    return FAIL;
2415 	}
2416 
2417 	/* Check for the ']'. */
2418 	if (**arg != ']')
2419 	{
2420 	    EMSG(_("E111: Missing ']'"));
2421 	    clear_var(retvar);
2422 	    clear_var(&var2);
2423 	    return FAIL;
2424 	}
2425 
2426 	if (evaluate)
2427 	{
2428 	    n = get_var_number(&var2);
2429 	    clear_var(&var2);
2430 
2431 	    /*
2432 	     * The resulting variable is a string of a single character.
2433 	     * If the index is too big or negative, the result is empty.
2434 	     */
2435 	    s = get_var_string(retvar);
2436 	    if (n >= (long)STRLEN(s) || n < 0)
2437 		s = NULL;
2438 	    else
2439 		s = vim_strnsave(s + n, 1);
2440 	    clear_var(retvar);
2441 	    retvar->var_type = VAR_STRING;
2442 	    retvar->var_val.var_string = s;
2443 	}
2444 	*arg = skipwhite(*arg + 1);	/* skip the ']' */
2445     }
2446 
2447     /*
2448      * Apply logical NOT and unary '-', from right to left, ignore '+'.
2449      */
2450     if (ret == OK && evaluate && end_leader > start_leader)
2451     {
2452 	val = get_var_number(retvar);
2453 	while (end_leader > start_leader)
2454 	{
2455 	    --end_leader;
2456 	    if (*end_leader == '!')
2457 		val = !val;
2458 	    else if (*end_leader == '-')
2459 		val = -val;
2460 	}
2461 	clear_var(retvar);
2462 	retvar->var_type = VAR_NUMBER;
2463 	retvar->var_val.var_number = val;
2464     }
2465 
2466     return ret;
2467 }
2468 
2469 /*
2470  * Get an option value.
2471  * "arg" points to the '&' or '+' before the option name.
2472  * "arg" is advanced to character after the option name.
2473  * Return OK or FAIL.
2474  */
2475     static int
2476 get_option_var(arg, retvar, evaluate)
2477     char_u	**arg;
2478     VAR		retvar;		/* when NULL, only check if option exists */
2479     int		evaluate;
2480 {
2481     char_u	*option_end;
2482     long	numval;
2483     char_u	*stringval;
2484     int		opt_type;
2485     int		c;
2486     int		working = (**arg == '+');    /* has("+option") */
2487     int		ret = OK;
2488     int		opt_flags;
2489 
2490     /*
2491      * Isolate the option name and find its value.
2492      */
2493     option_end = find_option_end(arg, &opt_flags);
2494     if (option_end == NULL)
2495     {
2496 	if (retvar != NULL)
2497 	    EMSG2(_("E112: Option name missing: %s"), *arg);
2498 	return FAIL;
2499     }
2500 
2501     if (!evaluate)
2502     {
2503 	*arg = option_end;
2504 	return OK;
2505     }
2506 
2507     c = *option_end;
2508     *option_end = NUL;
2509     opt_type = get_option_value(*arg, &numval,
2510 			       retvar == NULL ? NULL : &stringval, opt_flags);
2511 
2512     if (opt_type == -3)			/* invalid name */
2513     {
2514 	if (retvar != NULL)
2515 	    EMSG2(_("E113: Unknown option: %s"), *arg);
2516 	ret = FAIL;
2517     }
2518     else if (retvar != NULL)
2519     {
2520 	if (opt_type == -2)		/* hidden string option */
2521 	{
2522 	    retvar->var_type = VAR_STRING;
2523 	    retvar->var_val.var_string = NULL;
2524 	}
2525 	else if (opt_type == -1)	/* hidden number option */
2526 	{
2527 	    retvar->var_type = VAR_NUMBER;
2528 	    retvar->var_val.var_number = 0;
2529 	}
2530 	else if (opt_type == 1)		/* number option */
2531 	{
2532 	    retvar->var_type = VAR_NUMBER;
2533 	    retvar->var_val.var_number = numval;
2534 	}
2535 	else				/* string option */
2536 	{
2537 	    retvar->var_type = VAR_STRING;
2538 	    retvar->var_val.var_string = stringval;
2539 	}
2540     }
2541     else if (working && (opt_type == -2 || opt_type == -1))
2542 	ret = FAIL;
2543 
2544     *option_end = c;		    /* put back for error messages */
2545     *arg = option_end;
2546 
2547     return ret;
2548 }
2549 
2550 /*
2551  * Allocate a variable for a string constant.
2552  * Return OK or FAIL.
2553  */
2554     static int
2555 get_string_var(arg, retvar, evaluate)
2556     char_u	**arg;
2557     VAR		retvar;
2558     int		evaluate;
2559 {
2560     char_u	*p;
2561     char_u	*name;
2562     int		i;
2563     int		extra = 0;
2564 
2565     /*
2566      * Find the end of the string, skipping backslashed characters.
2567      */
2568     for (p = *arg + 1; *p && *p != '"'; ++p)
2569     {
2570 	if (*p == '\\' && p[1] != NUL)
2571 	{
2572 	    ++p;
2573 	    /* A "\<x>" form occupies at least 4 characters, and produces up
2574 	     * to 6 characters: reserve space for 2 extra */
2575 	    if (*p == '<')
2576 		extra += 2;
2577 	}
2578 #ifdef FEAT_MBYTE
2579 	if (has_mbyte)
2580 	    p += (*mb_ptr2len_check)(p) - 1;
2581 #endif
2582     }
2583 
2584     if (*p != '"')
2585     {
2586 	EMSG2(_("E114: Missing quote: %s"), *arg);
2587 	return FAIL;
2588     }
2589 
2590     /* If only parsing, set *arg and return here */
2591     if (!evaluate)
2592     {
2593 	*arg = p + 1;
2594 	return OK;
2595     }
2596 
2597     /*
2598      * Copy the string into allocated memory, handling backslashed
2599      * characters.
2600      */
2601     name = alloc((unsigned)(p - *arg + extra));
2602     if (name == NULL)
2603 	return FAIL;
2604 
2605     i = 0;
2606     for (p = *arg + 1; *p && *p != '"'; ++p)
2607     {
2608 	if (*p == '\\')
2609 	{
2610 	    switch (*++p)
2611 	    {
2612 		case 'b': name[i++] = BS; break;
2613 		case 'e': name[i++] = ESC; break;
2614 		case 'f': name[i++] = FF; break;
2615 		case 'n': name[i++] = NL; break;
2616 		case 'r': name[i++] = CAR; break;
2617 		case 't': name[i++] = TAB; break;
2618 
2619 		case 'X': /* hex: "\x1", "\x12" */
2620 		case 'x':
2621 		case 'u': /* Unicode: "\u0023" */
2622 		case 'U':
2623 			  if (vim_isxdigit(p[1]))
2624 			  {
2625 			      int	n, nr;
2626 			      int	c = toupper(*p);
2627 
2628 			      if (c == 'X')
2629 				  n = 2;
2630 			      else
2631 				  n = 4;
2632 			      nr = 0;
2633 			      while (--n >= 0 && vim_isxdigit(p[1]))
2634 			      {
2635 				  ++p;
2636 				  nr = (nr << 4) + hex2nr(*p);
2637 			      }
2638 #ifdef FEAT_MBYTE
2639 			      /* For "\u" store the number according to
2640 			       * 'encoding'. */
2641 			      if (c != 'X')
2642 				  i += (*mb_char2bytes)(nr, name + i);
2643 			      else
2644 #endif
2645 				  name[i++] = nr;
2646 			  }
2647 			  else
2648 			      name[i++] = *p;
2649 			  break;
2650 
2651 			  /* octal: "\1", "\12", "\123" */
2652 		case '0':
2653 		case '1':
2654 		case '2':
2655 		case '3':
2656 		case '4':
2657 		case '5':
2658 		case '6':
2659 		case '7': name[i] = *p - '0';
2660 			  if (p[1] >= '0' && p[1] <= '7')
2661 			  {
2662 			      ++p;
2663 			      name[i] = (name[i] << 3) + *p - '0';
2664 			      if (p[1] >= '0' && p[1] <= '7')
2665 			      {
2666 				  ++p;
2667 				  name[i] = (name[i] << 3) + *p - '0';
2668 			      }
2669 			  }
2670 			  ++i;
2671 			  break;
2672 
2673 			    /* Special key, e.g.: "\<C-W>" */
2674 		case '<': extra = trans_special(&p, name + i, TRUE);
2675 			  if (extra != 0)
2676 			  {
2677 			      i += extra;
2678 			      --p;
2679 			      break;
2680 			  }
2681 			  /* FALLTHROUGH */
2682 
2683 		default:  name[i++] = *p;
2684 			  break;
2685 	    }
2686 	}
2687 	else
2688 	    name[i++] = *p;
2689 
2690 #ifdef FEAT_MBYTE
2691 	/* For a multi-byte character copy the bytes after the first one. */
2692 	if (has_mbyte)
2693 	{
2694 	    int	l = (*mb_ptr2len_check)(p);
2695 
2696 	    while (--l > 0)
2697 		name[i++] = *++p;
2698 	}
2699 #endif
2700     }
2701     name[i] = NUL;
2702     *arg = p + 1;
2703 
2704     retvar->var_type = VAR_STRING;
2705     retvar->var_val.var_string = name;
2706 
2707     return OK;
2708 }
2709 
2710 /*
2711  * Allocate a variable for an backtick-string constant.
2712  * Return OK or FAIL.
2713  */
2714     static int
2715 get_lit_string_var(arg, retvar, evaluate)
2716     char_u	**arg;
2717     VAR		retvar;
2718     int		evaluate;
2719 {
2720     char_u	*p;
2721     char_u	*name;
2722 
2723     /*
2724      * Find the end of the string.
2725      */
2726     p = vim_strchr(*arg + 1, '\'');
2727     if (p == NULL)
2728     {
2729 	EMSG2(_("E115: Missing quote: %s"), *arg);
2730 	return FAIL;
2731     }
2732 
2733     if (evaluate)
2734     {
2735 	/*
2736 	 * Copy the string into allocated memory.
2737 	 */
2738 	name = vim_strnsave(*arg + 1, (int)(p - (*arg + 1)));
2739 	if (name == NULL)
2740 	    return FAIL;
2741 
2742 	retvar->var_type = VAR_STRING;
2743 	retvar->var_val.var_string = name;
2744     }
2745 
2746     *arg = p + 1;
2747 
2748     return OK;
2749 }
2750 
2751 /*
2752  * Get the value of an environment variable.
2753  * "arg" is pointing to the '$'.  It is advanced to after the name.
2754  * If the environment variable was not set, silently assume it is empty.
2755  * Always return OK.
2756  */
2757     static int
2758 get_env_var(arg, retvar, evaluate)
2759     char_u	**arg;
2760     VAR		retvar;
2761     int		evaluate;
2762 {
2763     char_u	*string = NULL;
2764     int		len;
2765     int		cc;
2766     char_u	*name;
2767 
2768     ++*arg;
2769     name = *arg;
2770     len = get_env_len(arg);
2771     if (evaluate)
2772     {
2773 	if (len != 0)
2774 	{
2775 	    cc = name[len];
2776 	    name[len] = NUL;
2777 	    /* first try mch_getenv(), fast for normal environment vars */
2778 	    string = mch_getenv(name);
2779 	    if (string != NULL && *string != NUL)
2780 		string = vim_strsave(string);
2781 	    else
2782 	    {
2783 		/* next try expanding things like $VIM and ${HOME} */
2784 		string = expand_env_save(name - 1);
2785 		if (string != NULL && *string == '$')
2786 		{
2787 		    vim_free(string);
2788 		    string = NULL;
2789 		}
2790 	    }
2791 	    name[len] = cc;
2792 	}
2793 	retvar->var_type = VAR_STRING;
2794 	retvar->var_val.var_string = string;
2795     }
2796 
2797     return OK;
2798 }
2799 
2800 /*
2801  * Array with names and number of arguments of all internal functions
2802  * MUST BE KEPT SORTED IN strcmp() ORDER FOR BINARY SEARCH!
2803  */
2804 static struct fst
2805 {
2806     char	*f_name;	/* function name */
2807     char	f_min_argc;	/* minimal number of arguments */
2808     char	f_max_argc;	/* maximal number of arguments */
2809     void	(*f_func) __ARGS((VAR args, VAR rvar)); /* impl. function */
2810 } functions[] =
2811 {
2812     {"append",		2, 2, f_append},
2813     {"argc",		0, 0, f_argc},
2814     {"argidx",		0, 0, f_argidx},
2815     {"argv",		1, 1, f_argv},
2816     {"browse",		4, 4, f_browse},
2817     {"bufexists",	1, 1, f_bufexists},
2818     {"buffer_exists",	1, 1, f_bufexists},	/* obsolete */
2819     {"buffer_name",	1, 1, f_bufname},	/* obsolete */
2820     {"buffer_number",	1, 1, f_bufnr},		/* obsolete */
2821     {"buflisted",	1, 1, f_buflisted},
2822     {"bufloaded",	1, 1, f_bufloaded},
2823     {"bufname",		1, 1, f_bufname},
2824     {"bufnr",		1, 1, f_bufnr},
2825     {"bufwinnr",	1, 1, f_bufwinnr},
2826     {"byte2line",	1, 1, f_byte2line},
2827     {"byteidx",		2, 2, f_byteidx},
2828     {"char2nr",		1, 1, f_char2nr},
2829     {"cindent",		1, 1, f_cindent},
2830     {"col",		1, 1, f_col},
2831     {"confirm",		1, 4, f_confirm},
2832     {"cscope_connection",0,3, f_cscope_connection},
2833     {"cursor",		2, 2, f_cursor},
2834     {"delete",		1, 1, f_delete},
2835     {"did_filetype",	0, 0, f_did_filetype},
2836     {"escape",		2, 2, f_escape},
2837     {"eventhandler",	0, 0, f_eventhandler},
2838     {"executable",	1, 1, f_executable},
2839     {"exists",		1, 1, f_exists},
2840     {"expand",		1, 2, f_expand},
2841     {"file_readable",	1, 1, f_filereadable},	/* obsolete */
2842     {"filereadable",	1, 1, f_filereadable},
2843     {"filewritable",	1, 1, f_filewritable},
2844     {"finddir",		1, 3, f_finddir},
2845     {"findfile",	1, 3, f_findfile},
2846     {"fnamemodify",	2, 2, f_fnamemodify},
2847     {"foldclosed",	1, 1, f_foldclosed},
2848     {"foldclosedend",	1, 1, f_foldclosedend},
2849     {"foldlevel",	1, 1, f_foldlevel},
2850     {"foldtext",	0, 0, f_foldtext},
2851     {"foreground",	0, 0, f_foreground},
2852     {"getbufvar",	2, 2, f_getbufvar},
2853     {"getchar",		0, 1, f_getchar},
2854     {"getcharmod",	0, 0, f_getcharmod},
2855     {"getcmdline",	0, 0, f_getcmdline},
2856     {"getcmdpos",	0, 0, f_getcmdpos},
2857     {"getcwd",		0, 0, f_getcwd},
2858     {"getfperm",	1, 1, f_getfperm},
2859     {"getfsize",	1, 1, f_getfsize},
2860     {"getftime",	1, 1, f_getftime},
2861     {"getftype",	1, 1, f_getftype},
2862     {"getline",		1, 1, f_getline},
2863     {"getreg",		0, 1, f_getreg},
2864     {"getregtype",	0, 1, f_getregtype},
2865     {"getwinposx",	0, 0, f_getwinposx},
2866     {"getwinposy",	0, 0, f_getwinposy},
2867     {"getwinvar",	2, 2, f_getwinvar},
2868     {"glob",		1, 1, f_glob},
2869     {"globpath",	2, 2, f_globpath},
2870     {"has",		1, 1, f_has},
2871     {"hasmapto",	1, 2, f_hasmapto},
2872     {"highlightID",	1, 1, f_hlID},		/* obsolete */
2873     {"highlight_exists",1, 1, f_hlexists},	/* obsolete */
2874     {"histadd",		2, 2, f_histadd},
2875     {"histdel",		1, 2, f_histdel},
2876     {"histget",		1, 2, f_histget},
2877     {"histnr",		1, 1, f_histnr},
2878     {"hlID",		1, 1, f_hlID},
2879     {"hlexists",	1, 1, f_hlexists},
2880     {"hostname",	0, 0, f_hostname},
2881     {"iconv",		3, 3, f_iconv},
2882     {"indent",		1, 1, f_indent},
2883     {"input",		1, 2, f_input},
2884     {"inputdialog",	1, 3, f_inputdialog},
2885     {"inputrestore",	0, 0, f_inputrestore},
2886     {"inputsave",	0, 0, f_inputsave},
2887     {"inputsecret",	1, 2, f_inputsecret},
2888     {"isdirectory",	1, 1, f_isdirectory},
2889     {"last_buffer_nr",	0, 0, f_last_buffer_nr},/* obsolete */
2890     {"libcall",		3, 3, f_libcall},
2891     {"libcallnr",	3, 3, f_libcallnr},
2892     {"line",		1, 1, f_line},
2893     {"line2byte",	1, 1, f_line2byte},
2894     {"lispindent",	1, 1, f_lispindent},
2895     {"localtime",	0, 0, f_localtime},
2896     {"maparg",		1, 2, f_maparg},
2897     {"mapcheck",	1, 2, f_mapcheck},
2898     {"match",		2, 4, f_match},
2899     {"matchend",	2, 4, f_matchend},
2900     {"matchstr",	2, 4, f_matchstr},
2901     {"mode",		0, 0, f_mode},
2902     {"nextnonblank",	1, 1, f_nextnonblank},
2903     {"nr2char",		1, 1, f_nr2char},
2904     {"prevnonblank",	1, 1, f_prevnonblank},
2905     {"remote_expr",	2, 3, f_remote_expr},
2906     {"remote_foreground", 1, 1, f_remote_foreground},
2907     {"remote_peek",	1, 2, f_remote_peek},
2908     {"remote_read",	1, 1, f_remote_read},
2909     {"remote_send",	2, 3, f_remote_send},
2910     {"rename",		2, 2, f_rename},
2911     {"repeat",		2, 2, f_repeat},
2912     {"resolve",		1, 1, f_resolve},
2913     {"search",		1, 2, f_search},
2914     {"searchpair",	3, 5, f_searchpair},
2915     {"server2client",	2, 2, f_server2client},
2916     {"serverlist",	0, 0, f_serverlist},
2917     {"setbufvar",	3, 3, f_setbufvar},
2918     {"setcmdpos",	1, 1, f_setcmdpos},
2919     {"setline",		2, 2, f_setline},
2920     {"setreg",		2, 3, f_setreg},
2921     {"setwinvar",	3, 3, f_setwinvar},
2922     {"simplify",	1, 1, f_simplify},
2923 #ifdef HAVE_STRFTIME
2924     {"strftime",	1, 2, f_strftime},
2925 #endif
2926     {"stridx",		2, 2, f_stridx},
2927     {"strlen",		1, 1, f_strlen},
2928     {"strpart",		2, 3, f_strpart},
2929     {"strridx",		2, 2, f_strridx},
2930     {"strtrans",	1, 1, f_strtrans},
2931     {"submatch",	1, 1, f_submatch},
2932     {"substitute",	4, 4, f_substitute},
2933     {"synID",		3, 3, f_synID},
2934     {"synIDattr",	2, 3, f_synIDattr},
2935     {"synIDtrans",	1, 1, f_synIDtrans},
2936     {"system",		1, 2, f_system},
2937     {"tempname",	0, 0, f_tempname},
2938     {"tolower",		1, 1, f_tolower},
2939     {"toupper",		1, 1, f_toupper},
2940     {"tr",		3, 3, f_tr},
2941     {"type",		1, 1, f_type},
2942     {"virtcol",		1, 1, f_virtcol},
2943     {"visualmode",	0, 1, f_visualmode},
2944     {"winbufnr",	1, 1, f_winbufnr},
2945     {"wincol",		0, 0, f_wincol},
2946     {"winheight",	1, 1, f_winheight},
2947     {"winline",		0, 0, f_winline},
2948     {"winnr",		0, 1, f_winnr},
2949     {"winrestcmd",	0, 0, f_winrestcmd},
2950     {"winwidth",	1, 1, f_winwidth},
2951 };
2952 
2953 #if defined(FEAT_CMDL_COMPL) || defined(PROTO)
2954 
2955 /*
2956  * Function given to ExpandGeneric() to obtain the list of internal
2957  * or user defined function names.
2958  */
2959     char_u *
2960 get_function_name(xp, idx)
2961     expand_T	*xp;
2962     int		idx;
2963 {
2964     static int	intidx = -1;
2965     char_u	*name;
2966 
2967     if (idx == 0)
2968 	intidx = -1;
2969     if (intidx < 0)
2970     {
2971 	name = get_user_func_name(xp, idx);
2972 	if (name != NULL)
2973 	    return name;
2974     }
2975     if (++intidx < (int)(sizeof(functions) / sizeof(struct fst)))
2976     {
2977 	STRCPY(IObuff, functions[intidx].f_name);
2978 	STRCAT(IObuff, "(");
2979 	if (functions[intidx].f_max_argc == 0)
2980 	    STRCAT(IObuff, ")");
2981 	return IObuff;
2982     }
2983 
2984     return NULL;
2985 }
2986 
2987 /*
2988  * Function given to ExpandGeneric() to obtain the list of internal or
2989  * user defined variable or function names.
2990  */
2991 /*ARGSUSED*/
2992     char_u *
2993 get_expr_name(xp, idx)
2994     expand_T	*xp;
2995     int		idx;
2996 {
2997     static int	intidx = -1;
2998     char_u	*name;
2999 
3000     if (idx == 0)
3001 	intidx = -1;
3002     if (intidx < 0)
3003     {
3004 	name = get_function_name(xp, idx);
3005 	if (name != NULL)
3006 	    return name;
3007     }
3008     return get_user_var_name(xp, ++intidx);
3009 }
3010 
3011 #endif /* FEAT_CMDL_COMPL */
3012 
3013 /*
3014  * Find internal function in table above.
3015  * Return index, or -1 if not found
3016  */
3017     static int
3018 find_internal_func(name)
3019     char_u	*name;		/* name of the function */
3020 {
3021     int		first = 0;
3022     int		last = (int)(sizeof(functions) / sizeof(struct fst)) - 1;
3023     int		cmp;
3024     int		x;
3025 
3026     /*
3027      * Find the function name in the table. Binary search.
3028      */
3029     while (first <= last)
3030     {
3031 	x = first + ((unsigned)(last - first) >> 1);
3032 	cmp = STRCMP(name, functions[x].f_name);
3033 	if (cmp < 0)
3034 	    last = x - 1;
3035 	else if (cmp > 0)
3036 	    first = x + 1;
3037 	else
3038 	    return x;
3039     }
3040     return -1;
3041 }
3042 
3043 /*
3044  * Allocate a variable for the result of a function.
3045  * Return OK or FAIL.
3046  */
3047     static int
3048 get_func_var(name, len, retvar, arg, firstline, lastline, doesrange, evaluate)
3049     char_u	*name;		/* name of the function */
3050     int		len;		/* length of "name" */
3051     VAR		retvar;
3052     char_u	**arg;		/* argument, pointing to the '(' */
3053     linenr_T	firstline;	/* first line of range */
3054     linenr_T	lastline;	/* last line of range */
3055     int		*doesrange;	/* return: function handled range */
3056     int		evaluate;
3057 {
3058     char_u	*argp;
3059     int		ret = OK;
3060 #define MAX_FUNC_ARGS	20
3061     var		argvars[MAX_FUNC_ARGS];	/* vars for arguments */
3062     int		argcount = 0;		/* number of arguments found */
3063 
3064     /*
3065      * Get the arguments.
3066      */
3067     argp = *arg;
3068     while (argcount < MAX_FUNC_ARGS)
3069     {
3070 	argp = skipwhite(argp + 1);	    /* skip the '(' or ',' */
3071 	if (*argp == ')' || *argp == ',' || *argp == NUL)
3072 	    break;
3073 	argvars[argcount].var_name = NULL;  /* the name is not stored */
3074 	if (eval1(&argp, &argvars[argcount], evaluate) == FAIL)
3075 	{
3076 	    ret = FAIL;
3077 	    break;
3078 	}
3079 	++argcount;
3080 	if (*argp != ',')
3081 	    break;
3082     }
3083     if (*argp == ')')
3084 	++argp;
3085     else
3086 	ret = FAIL;
3087 
3088     if (ret == OK)
3089 	ret = call_func(name, len, retvar, argcount, argvars,
3090 				    firstline, lastline, doesrange, evaluate);
3091     else if (!aborting())
3092 	EMSG2(_("E116: Invalid arguments for function %s"), name);
3093 
3094     while (--argcount >= 0)
3095 	clear_var(&argvars[argcount]);
3096 
3097     *arg = skipwhite(argp);
3098     return ret;
3099 }
3100 
3101 
3102 /*
3103  * Call a function with its resolved parameters
3104  * Return OK or FAIL.
3105  */
3106     static int
3107 call_func(name, len, retvar, argcount, argvars, firstline, lastline,
3108 							  doesrange, evaluate)
3109     char_u	*name;		/* name of the function */
3110     int		len;		/* length of "name" */
3111     VAR		retvar;		/* return value goes here */
3112     int		argcount;	/* number of "argvars" */
3113     VAR		argvars;	/* vars for arguments */
3114     linenr_T	firstline;	/* first line of range */
3115     linenr_T	lastline;	/* last line of range */
3116     int		*doesrange;	/* return: function handled range */
3117     int		evaluate;
3118 {
3119     int		ret = FAIL;
3120     static char *errors[] =
3121 		{N_("E117: Unknown function: %s"),
3122 		 N_("E118: Too many arguments for function: %s"),
3123 		 N_("E119: Not enough arguments for function: %s"),
3124 		 N_("E120: Using <SID> not in a script context: %s"),
3125 		};
3126 #define ERROR_UNKNOWN	0
3127 #define ERROR_TOOMANY	1
3128 #define ERROR_TOOFEW	2
3129 #define ERROR_SCRIPT	3
3130 #define ERROR_NONE	4
3131 #define ERROR_OTHER	5
3132     int		error = ERROR_NONE;
3133     int		i;
3134     int		llen;
3135     ufunc_T	*fp;
3136     int		cc;
3137 #define FLEN_FIXED 40
3138     char_u	fname_buf[FLEN_FIXED + 1];
3139     char_u	*fname;
3140 
3141     /*
3142      * In a script change <SID>name() and s:name() to K_SNR 123_name().
3143      * Change <SNR>123_name() to K_SNR 123_name().
3144      * Use fname_buf[] when it fits, otherwise allocate memory (slow).
3145      */
3146     cc = name[len];
3147     name[len] = NUL;
3148     llen = eval_fname_script(name);
3149     if (llen > 0)
3150     {
3151 	fname_buf[0] = K_SPECIAL;
3152 	fname_buf[1] = KS_EXTRA;
3153 	fname_buf[2] = (int)KE_SNR;
3154 	i = 3;
3155 	if (eval_fname_sid(name))	/* "<SID>" or "s:" */
3156 	{
3157 	    if (current_SID <= 0)
3158 		error = ERROR_SCRIPT;
3159 	    else
3160 	    {
3161 		sprintf((char *)fname_buf + 3, "%ld_", (long)current_SID);
3162 		i = (int)STRLEN(fname_buf);
3163 	    }
3164 	}
3165 	if (i + STRLEN(name + llen) < FLEN_FIXED)
3166 	{
3167 	    STRCPY(fname_buf + i, name + llen);
3168 	    fname = fname_buf;
3169 	}
3170 	else
3171 	{
3172 	    fname = alloc((unsigned)(i + STRLEN(name + llen) + 1));
3173 	    if (fname == NULL)
3174 		error = ERROR_OTHER;
3175 	    else
3176 	    {
3177 		mch_memmove(fname, fname_buf, (size_t)i);
3178 		STRCPY(fname + i, name + llen);
3179 	    }
3180 	}
3181     }
3182     else
3183 	fname = name;
3184 
3185     *doesrange = FALSE;
3186 
3187 
3188     /* execute the function if no errors detected and executing */
3189     if (evaluate && error == ERROR_NONE)
3190     {
3191 	retvar->var_type = VAR_NUMBER;	/* default is number retvar */
3192 	error = ERROR_UNKNOWN;
3193 
3194 	if (!ASCII_ISLOWER(fname[0]))
3195 	{
3196 	    /*
3197 	     * User defined function.
3198 	     */
3199 	    fp = find_func(fname);
3200 #ifdef FEAT_AUTOCMD
3201 	    if (fp == NULL && apply_autocmds(EVENT_FUNCUNDEFINED,
3202 						    fname, fname, TRUE, NULL)
3203 #ifdef FEAT_EVAL
3204 		    && !aborting()
3205 #endif
3206 	       )
3207 	    {
3208 		/* executed an autocommand, search for function again */
3209 		fp = find_func(fname);
3210 	    }
3211 #endif
3212 	    if (fp != NULL)
3213 	    {
3214 		if (fp->flags & FC_RANGE)
3215 		    *doesrange = TRUE;
3216 		if (argcount < fp->args.ga_len)
3217 		    error = ERROR_TOOFEW;
3218 		else if (!fp->varargs && argcount > fp->args.ga_len)
3219 		    error = ERROR_TOOMANY;
3220 		else
3221 		{
3222 		    /*
3223 		     * Call the user function.
3224 		     * Save and restore search patterns, script variables and
3225 		     * redo buffer.
3226 		     */
3227 		    save_search_patterns();
3228 		    saveRedobuff();
3229 		    ++fp->calls;
3230 		    call_user_func(fp, argcount, argvars, retvar,
3231 							 firstline, lastline);
3232 		    --fp->calls;
3233 		    restoreRedobuff();
3234 		    restore_search_patterns();
3235 		    error = ERROR_NONE;
3236 		}
3237 	    }
3238 	}
3239 	else
3240 	{
3241 	    /*
3242 	     * Find the function name in the table, call its implementation.
3243 	     */
3244 	    i = find_internal_func(fname);
3245 	    if (i >= 0)
3246 	    {
3247 		if (argcount < functions[i].f_min_argc)
3248 		    error = ERROR_TOOFEW;
3249 		else if (argcount > functions[i].f_max_argc)
3250 		    error = ERROR_TOOMANY;
3251 		else
3252 		{
3253 		    argvars[argcount].var_type = VAR_UNKNOWN;
3254 		    functions[i].f_func(argvars, retvar);
3255 		    error = ERROR_NONE;
3256 		}
3257 	    }
3258 	}
3259 	/*
3260 	 * The function call (or "FuncUndefined" autocommand sequence) might
3261 	 * have been aborted by an error, an interrupt, or an explicitly thrown
3262 	 * exception that has not been caught so far.  This situation can be
3263 	 * tested for by calling aborting().  For an error in an internal
3264 	 * function or for the "E132" error in call_user_func(), however, the
3265 	 * throw point at which the "force_abort" flag (temporarily reset by
3266 	 * emsg()) is normally updated has not been reached yet. We need to
3267 	 * update that flag first to make aborting() reliable.
3268 	 */
3269 	update_force_abort();
3270     }
3271     if (error == ERROR_NONE)
3272 	ret = OK;
3273 
3274     /*
3275      * Report an error unless the argument evaluation or function call has been
3276      * cancelled due to an aborting error, an interrupt, or an exception.
3277      */
3278     if (error < ERROR_NONE && !aborting())
3279 	EMSG2((char_u *)_(errors[error]), name);
3280 
3281     name[len] = cc;
3282     if (fname != name && fname != fname_buf)
3283 	vim_free(fname);
3284 
3285     return ret;
3286 }
3287 
3288 /*********************************************
3289  * Implementation of the built-in functions
3290  */
3291 
3292 /*
3293  * "append(lnum, string)" function
3294  */
3295     static void
3296 f_append(argvars, retvar)
3297     VAR		argvars;
3298     VAR		retvar;
3299 {
3300     long	lnum;
3301 
3302     lnum = get_var_lnum(argvars);
3303     retvar->var_val.var_number = 1; /* Default: Failed */
3304 
3305     if (lnum >= 0
3306 	    && lnum <= curbuf->b_ml.ml_line_count
3307 	    && u_save(lnum, lnum + 1) == OK)
3308     {
3309 	ml_append(lnum, get_var_string(&argvars[1]), (colnr_T)0, FALSE);
3310 	if (curwin->w_cursor.lnum > lnum)
3311 	    ++curwin->w_cursor.lnum;
3312 	appended_lines_mark(lnum, 1L);
3313 	retvar->var_val.var_number = 0;
3314     }
3315 }
3316 
3317 /*
3318  * "argc()" function
3319  */
3320 /* ARGSUSED */
3321     static void
3322 f_argc(argvars, retvar)
3323     VAR		argvars;
3324     VAR		retvar;
3325 {
3326     retvar->var_val.var_number = ARGCOUNT;
3327 }
3328 
3329 /*
3330  * "argidx()" function
3331  */
3332 /* ARGSUSED */
3333     static void
3334 f_argidx(argvars, retvar)
3335     VAR		argvars;
3336     VAR		retvar;
3337 {
3338     retvar->var_val.var_number = curwin->w_arg_idx;
3339 }
3340 
3341 /*
3342  * "argv(nr)" function
3343  */
3344     static void
3345 f_argv(argvars, retvar)
3346     VAR		argvars;
3347     VAR		retvar;
3348 {
3349     int		idx;
3350 
3351     idx = get_var_number(&argvars[0]);
3352     if (idx >= 0 && idx < ARGCOUNT)
3353 	retvar->var_val.var_string = vim_strsave(alist_name(&ARGLIST[idx]));
3354     else
3355 	retvar->var_val.var_string = NULL;
3356     retvar->var_type = VAR_STRING;
3357 }
3358 
3359 /*
3360  * "browse(save, title, initdir, default)" function
3361  */
3362 /* ARGSUSED */
3363     static void
3364 f_browse(argvars, retvar)
3365     VAR		argvars;
3366     VAR		retvar;
3367 {
3368 #ifdef FEAT_BROWSE
3369     int		save;
3370     char_u	*title;
3371     char_u	*initdir;
3372     char_u	*defname;
3373     char_u	buf[NUMBUFLEN];
3374     char_u	buf2[NUMBUFLEN];
3375 
3376     save = get_var_number(&argvars[0]);
3377     title = get_var_string(&argvars[1]);
3378     initdir = get_var_string_buf(&argvars[2], buf);
3379     defname = get_var_string_buf(&argvars[3], buf2);
3380 
3381     retvar->var_val.var_string =
3382 		 do_browse(save, title, defname, NULL, initdir, NULL, curbuf);
3383 #else
3384     retvar->var_val.var_string = NULL;
3385 #endif
3386     retvar->var_type = VAR_STRING;
3387 }
3388 
3389 /*
3390  * Find a buffer by number or exact name.
3391  */
3392     static buf_T *
3393 find_buffer(avar)
3394     VAR		avar;
3395 {
3396     buf_T	*buf = NULL;
3397     char_u	*name;
3398 
3399     if (avar->var_type == VAR_NUMBER)
3400 	buf = buflist_findnr((int)avar->var_val.var_number);
3401     else if (avar->var_val.var_string != NULL)
3402     {
3403 	/* First make the name into a full path name */
3404 	name = FullName_save(avar->var_val.var_string,
3405 #ifdef UNIX
3406 		TRUE	    /* force expansion, get rid of symbolic links */
3407 #else
3408 		FALSE
3409 #endif
3410 		);
3411 	if (name != NULL)
3412 	{
3413 	    buf = buflist_findname(name);
3414 	    vim_free(name);
3415 	}
3416 	if (buf == NULL)
3417 	{
3418 	    /* No full path name match, try a match with a URL or a "nofile"
3419 	     * buffer, these don't use the full path. */
3420 	    for (buf = firstbuf; buf != NULL; buf = buf->b_next)
3421 		if (buf->b_fname != NULL
3422 			&& (path_with_url(buf->b_fname)
3423 #ifdef FEAT_QUICKFIX
3424 			    || bt_nofile(buf)
3425 #endif
3426 			   )
3427 			&& STRCMP(buf->b_fname, avar->var_val.var_string) == 0)
3428 		    break;
3429 	}
3430     }
3431     return buf;
3432 }
3433 
3434 /*
3435  * "bufexists(expr)" function
3436  */
3437     static void
3438 f_bufexists(argvars, retvar)
3439     VAR		argvars;
3440     VAR		retvar;
3441 {
3442     retvar->var_val.var_number = (find_buffer(&argvars[0]) != NULL);
3443 }
3444 
3445 /*
3446  * "buflisted(expr)" function
3447  */
3448     static void
3449 f_buflisted(argvars, retvar)
3450     VAR		argvars;
3451     VAR		retvar;
3452 {
3453     buf_T	*buf;
3454 
3455     buf = find_buffer(&argvars[0]);
3456     retvar->var_val.var_number = (buf != NULL && buf->b_p_bl);
3457 }
3458 
3459 /*
3460  * "bufloaded(expr)" function
3461  */
3462     static void
3463 f_bufloaded(argvars, retvar)
3464     VAR		argvars;
3465     VAR		retvar;
3466 {
3467     buf_T	*buf;
3468 
3469     buf = find_buffer(&argvars[0]);
3470     retvar->var_val.var_number = (buf != NULL && buf->b_ml.ml_mfp != NULL);
3471 }
3472 
3473 /*
3474  * Get buffer by number or pattern.
3475  */
3476     static buf_T *
3477 get_buf_var(avar)
3478     VAR		avar;
3479 {
3480     char_u	*name = avar->var_val.var_string;
3481     int		save_magic;
3482     char_u	*save_cpo;
3483     buf_T	*buf;
3484 
3485     if (avar->var_type == VAR_NUMBER)
3486 	return buflist_findnr((int)avar->var_val.var_number);
3487     if (name == NULL || *name == NUL)
3488 	return curbuf;
3489     if (name[0] == '$' && name[1] == NUL)
3490 	return lastbuf;
3491 
3492     /* Ignore 'magic' and 'cpoptions' here to make scripts portable */
3493     save_magic = p_magic;
3494     p_magic = TRUE;
3495     save_cpo = p_cpo;
3496     p_cpo = (char_u *)"";
3497 
3498     buf = buflist_findnr(buflist_findpat(name, name + STRLEN(name),
3499 								TRUE, FALSE));
3500 
3501     p_magic = save_magic;
3502     p_cpo = save_cpo;
3503 
3504     /* If not found, try expanding the name, like done for bufexists(). */
3505     if (buf == NULL)
3506 	buf = find_buffer(avar);
3507 
3508     return buf;
3509 }
3510 
3511 /*
3512  * "bufname(expr)" function
3513  */
3514     static void
3515 f_bufname(argvars, retvar)
3516     VAR		argvars;
3517     VAR		retvar;
3518 {
3519     buf_T	*buf;
3520 
3521     ++emsg_off;
3522     buf = get_buf_var(&argvars[0]);
3523     retvar->var_type = VAR_STRING;
3524     if (buf != NULL && buf->b_fname != NULL)
3525 	retvar->var_val.var_string = vim_strsave(buf->b_fname);
3526     else
3527 	retvar->var_val.var_string = NULL;
3528     --emsg_off;
3529 }
3530 
3531 /*
3532  * "bufnr(expr)" function
3533  */
3534     static void
3535 f_bufnr(argvars, retvar)
3536     VAR		argvars;
3537     VAR		retvar;
3538 {
3539     buf_T	*buf;
3540 
3541     ++emsg_off;
3542     buf = get_buf_var(&argvars[0]);
3543     if (buf != NULL)
3544 	retvar->var_val.var_number = buf->b_fnum;
3545     else
3546 	retvar->var_val.var_number = -1;
3547     --emsg_off;
3548 }
3549 
3550 /*
3551  * "bufwinnr(nr)" function
3552  */
3553     static void
3554 f_bufwinnr(argvars, retvar)
3555     VAR		argvars;
3556     VAR		retvar;
3557 {
3558 #ifdef FEAT_WINDOWS
3559     win_T	*wp;
3560     int		winnr = 0;
3561 #endif
3562     buf_T	*buf;
3563 
3564     ++emsg_off;
3565     buf = get_buf_var(&argvars[0]);
3566 #ifdef FEAT_WINDOWS
3567     for (wp = firstwin; wp; wp = wp->w_next)
3568     {
3569 	++winnr;
3570 	if (wp->w_buffer == buf)
3571 	    break;
3572     }
3573     retvar->var_val.var_number = (wp != NULL ? winnr : -1);
3574 #else
3575     retvar->var_val.var_number = (curwin->w_buffer == buf ? 1 : -1);
3576 #endif
3577     --emsg_off;
3578 }
3579 
3580 /*
3581  * "byte2line(byte)" function
3582  */
3583 /*ARGSUSED*/
3584     static void
3585 f_byte2line(argvars, retvar)
3586     VAR		argvars;
3587     VAR		retvar;
3588 {
3589 #ifndef FEAT_BYTEOFF
3590     retvar->var_val.var_number = -1;
3591 #else
3592     long	boff = 0;
3593 
3594     boff = get_var_number(&argvars[0]) - 1;
3595     if (boff < 0)
3596 	retvar->var_val.var_number = -1;
3597     else
3598 	retvar->var_val.var_number = ml_find_line_or_offset(curbuf,
3599 							  (linenr_T)0, &boff);
3600 #endif
3601 }
3602 
3603 /*
3604  * "byteidx()" function
3605  */
3606 /*ARGSUSED*/
3607     static void
3608 f_byteidx(argvars, retvar)
3609     VAR		argvars;
3610     VAR		retvar;
3611 {
3612 #ifdef FEAT_MBYTE
3613     char_u	*t;
3614 #endif
3615     char_u	*str;
3616     long	idx;
3617 
3618     str = get_var_string(&argvars[0]);
3619     idx = get_var_number(&argvars[1]);
3620     retvar->var_val.var_number = -1;
3621     if (idx < 0)
3622 	return;
3623 
3624 #ifdef FEAT_MBYTE
3625     t = str;
3626     for ( ; idx > 0; idx--)
3627     {
3628 	if (*t == NUL)		/* EOL reached */
3629 	    return;
3630 	t += mb_ptr2len_check(t);
3631     }
3632     retvar->var_val.var_number = t - str;
3633 #else
3634     if (idx <= STRLEN(str))
3635 	retvar->var_val.var_number = idx;
3636 #endif
3637 }
3638 
3639 /*
3640  * "char2nr(string)" function
3641  */
3642     static void
3643 f_char2nr(argvars, retvar)
3644     VAR		argvars;
3645     VAR		retvar;
3646 {
3647 #ifdef FEAT_MBYTE
3648     if (has_mbyte)
3649 	retvar->var_val.var_number =
3650 				  (*mb_ptr2char)(get_var_string(&argvars[0]));
3651     else
3652 #endif
3653     retvar->var_val.var_number = get_var_string(&argvars[0])[0];
3654 }
3655 
3656 /*
3657  * "cindent(lnum)" function
3658  */
3659     static void
3660 f_cindent(argvars, retvar)
3661     VAR		argvars;
3662     VAR		retvar;
3663 {
3664 #ifdef FEAT_CINDENT
3665     pos_T	pos;
3666     linenr_T	lnum;
3667 
3668     pos = curwin->w_cursor;
3669     lnum = get_var_lnum(argvars);
3670     if (lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count)
3671     {
3672 	curwin->w_cursor.lnum = lnum;
3673 	retvar->var_val.var_number = get_c_indent();
3674 	curwin->w_cursor = pos;
3675     }
3676     else
3677 #endif
3678 	retvar->var_val.var_number = -1;
3679 }
3680 
3681 /*
3682  * "col(string)" function
3683  */
3684     static void
3685 f_col(argvars, retvar)
3686     VAR		argvars;
3687     VAR		retvar;
3688 {
3689     colnr_T	col = 0;
3690     pos_T	*fp;
3691 
3692     fp = var2fpos(&argvars[0], FALSE);
3693     if (fp != NULL)
3694     {
3695 	if (fp->col == MAXCOL)
3696 	{
3697 	    /* '> can be MAXCOL, get the length of the line then */
3698 	    if (fp->lnum <= curbuf->b_ml.ml_line_count)
3699 		col = STRLEN(ml_get(fp->lnum)) + 1;
3700 	    else
3701 		col = MAXCOL;
3702 	}
3703 	else
3704 	{
3705 	    col = fp->col + 1;
3706 #ifdef FEAT_VIRTUALEDIT
3707 	    /* col(".") when the cursor is on the NUL at the end of the line
3708 	     * because of "coladd" can be seen as an extra column. */
3709 	    if (virtual_active() && fp == &curwin->w_cursor)
3710 	    {
3711 		char_u	*p = ml_get_cursor();
3712 
3713 		if (curwin->w_cursor.coladd >= (colnr_T)chartabsize(p,
3714 				 curwin->w_virtcol - curwin->w_cursor.coladd))
3715 		{
3716 # ifdef FEAT_MBYTE
3717 		    int		l;
3718 
3719 		    if (*p != NUL && p[(l = (*mb_ptr2len_check)(p))] == NUL)
3720 			col += l;
3721 # else
3722 		    if (*p != NUL && p[1] == NUL)
3723 			++col;
3724 # endif
3725 		}
3726 	    }
3727 #endif
3728 	}
3729     }
3730     retvar->var_val.var_number = col;
3731 }
3732 
3733 /*
3734  * "confirm(message, buttons[, default [, type]])" function
3735  */
3736 /*ARGSUSED*/
3737     static void
3738 f_confirm(argvars, retvar)
3739     VAR		argvars;
3740     VAR		retvar;
3741 {
3742 #if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
3743     char_u	*message;
3744     char_u	*buttons = NULL;
3745     char_u	buf[NUMBUFLEN];
3746     char_u	buf2[NUMBUFLEN];
3747     int		def = 1;
3748     int		type = VIM_GENERIC;
3749     int		c;
3750 
3751     message = get_var_string(&argvars[0]);
3752     if (argvars[1].var_type != VAR_UNKNOWN)
3753     {
3754 	buttons = get_var_string_buf(&argvars[1], buf);
3755 	if (argvars[2].var_type != VAR_UNKNOWN)
3756 	{
3757 	    def = get_var_number(&argvars[2]);
3758 	    if (argvars[3].var_type != VAR_UNKNOWN)
3759 	    {
3760 		/* avoid that TOUPPER_ASC calls get_var_string_buf() twice */
3761 		c = *get_var_string_buf(&argvars[3], buf2);
3762 		switch (TOUPPER_ASC(c))
3763 		{
3764 		    case 'E': type = VIM_ERROR; break;
3765 		    case 'Q': type = VIM_QUESTION; break;
3766 		    case 'I': type = VIM_INFO; break;
3767 		    case 'W': type = VIM_WARNING; break;
3768 		    case 'G': type = VIM_GENERIC; break;
3769 		}
3770 	    }
3771 	}
3772     }
3773 
3774     if (buttons == NULL || *buttons == NUL)
3775 	buttons = (char_u *)_("&Ok");
3776 
3777     retvar->var_val.var_number = do_dialog(type, NULL, message, buttons,
3778 								   def, NULL);
3779 #else
3780     retvar->var_val.var_number = 0;
3781 #endif
3782 }
3783 
3784 
3785 /*
3786  * "cscope_connection([{num} , {dbpath} [, {prepend}]])" function
3787  *
3788  * Checks the existence of a cscope connection.
3789  */
3790 /*ARGSUSED*/
3791     static void
3792 f_cscope_connection(argvars, retvar)
3793     VAR		argvars;
3794     VAR		retvar;
3795 {
3796 #ifdef FEAT_CSCOPE
3797     int		num = 0;
3798     char_u	*dbpath = NULL;
3799     char_u	*prepend = NULL;
3800     char_u	buf[NUMBUFLEN];
3801 
3802     if (argvars[0].var_type != VAR_UNKNOWN
3803 	    && argvars[1].var_type != VAR_UNKNOWN)
3804     {
3805 	num = (int)get_var_number(&argvars[0]);
3806 	dbpath = get_var_string(&argvars[1]);
3807 	if (argvars[2].var_type != VAR_UNKNOWN)
3808 	    prepend = get_var_string_buf(&argvars[2], buf);
3809     }
3810 
3811     retvar->var_val.var_number = cs_connection(num, dbpath, prepend);
3812 #else
3813     retvar->var_val.var_number = 0;
3814 #endif
3815 }
3816 
3817 /*
3818  * "cursor(lnum, col)" function
3819  *
3820  * Moves the cursor to the specified line and column
3821  */
3822 /*ARGSUSED*/
3823     static void
3824 f_cursor(argvars, retvar)
3825     VAR		argvars;
3826     VAR		retvar;
3827 {
3828     long	line, col;
3829 
3830     line = get_var_lnum(argvars);
3831     if (line > 0)
3832 	curwin->w_cursor.lnum = line;
3833     col = get_var_number(&argvars[1]);
3834     if (col > 0)
3835 	curwin->w_cursor.col = col - 1;
3836 #ifdef FEAT_VIRTUALEDIT
3837     curwin->w_cursor.coladd = 0;
3838 #endif
3839 
3840     /* Make sure the cursor is in a valid position. */
3841     check_cursor();
3842 #ifdef FEAT_MBYTE
3843     /* Correct cursor for multi-byte character. */
3844     if (has_mbyte)
3845 	mb_adjust_cursor();
3846 #endif
3847 
3848     curwin->w_set_curswant = TRUE;
3849 }
3850 
3851 /*
3852  * "libcall()" function
3853  */
3854     static void
3855 f_libcall(argvars, retvar)
3856     VAR		argvars;
3857     VAR		retvar;
3858 {
3859     libcall_common(argvars, retvar, VAR_STRING);
3860 }
3861 
3862 /*
3863  * "libcallnr()" function
3864  */
3865     static void
3866 f_libcallnr(argvars, retvar)
3867     VAR		argvars;
3868     VAR		retvar;
3869 {
3870     libcall_common(argvars, retvar, VAR_NUMBER);
3871 }
3872 
3873     static void
3874 libcall_common(argvars, retvar, type)
3875     VAR		argvars;
3876     VAR		retvar;
3877     int		type;
3878 {
3879 #ifdef FEAT_LIBCALL
3880     char_u		*string_in;
3881     char_u		**string_result;
3882     int			nr_result;
3883 #endif
3884 
3885     retvar->var_type = type;
3886     if (type == VAR_NUMBER)
3887 	retvar->var_val.var_number = 0;
3888     else
3889 	retvar->var_val.var_string = NULL;
3890 
3891     if (check_restricted() || check_secure())
3892 	return;
3893 
3894 #ifdef FEAT_LIBCALL
3895     /* The first two args must be strings, otherwise its meaningless */
3896     if (argvars[0].var_type == VAR_STRING && argvars[1].var_type == VAR_STRING)
3897     {
3898 	if (argvars[2].var_type == VAR_NUMBER)
3899 	    string_in = NULL;
3900 	else
3901 	    string_in = argvars[2].var_val.var_string;
3902 	if (type == VAR_NUMBER)
3903 	    string_result = NULL;
3904 	else
3905 	    string_result = &retvar->var_val.var_string;
3906 	if (mch_libcall(argvars[0].var_val.var_string,
3907 			     argvars[1].var_val.var_string,
3908 			     string_in,
3909 			     argvars[2].var_val.var_number,
3910 			     string_result,
3911 			     &nr_result) == OK
3912 		&& type == VAR_NUMBER)
3913 	    retvar->var_val.var_number = nr_result;
3914     }
3915 #endif
3916 }
3917 
3918 /*
3919  * "delete()" function
3920  */
3921     static void
3922 f_delete(argvars, retvar)
3923     VAR		argvars;
3924     VAR		retvar;
3925 {
3926     if (check_restricted() || check_secure())
3927 	retvar->var_val.var_number = -1;
3928     else
3929 	retvar->var_val.var_number = mch_remove(get_var_string(&argvars[0]));
3930 }
3931 
3932 /*
3933  * "did_filetype()" function
3934  */
3935 /*ARGSUSED*/
3936     static void
3937 f_did_filetype(argvars, retvar)
3938     VAR		argvars;
3939     VAR		retvar;
3940 {
3941 #ifdef FEAT_AUTOCMD
3942     retvar->var_val.var_number = did_filetype;
3943 #else
3944     retvar->var_val.var_number = 0;
3945 #endif
3946 }
3947 
3948 /*
3949  * "escape({string}, {chars})" function
3950  */
3951     static void
3952 f_escape(argvars, retvar)
3953     VAR		argvars;
3954     VAR		retvar;
3955 {
3956     char_u	buf[NUMBUFLEN];
3957 
3958     retvar->var_val.var_string =
3959 	vim_strsave_escaped(get_var_string(&argvars[0]),
3960 		get_var_string_buf(&argvars[1], buf));
3961     retvar->var_type = VAR_STRING;
3962 }
3963 
3964 /*
3965  * "eventhandler()" function
3966  */
3967 /*ARGSUSED*/
3968     static void
3969 f_eventhandler(argvars, retvar)
3970     VAR		argvars;
3971     VAR		retvar;
3972 {
3973     retvar->var_val.var_number = vgetc_busy;
3974 }
3975 
3976 /*
3977  * "executable()" function
3978  */
3979     static void
3980 f_executable(argvars, retvar)
3981     VAR		argvars;
3982     VAR		retvar;
3983 {
3984     retvar->var_val.var_number = mch_can_exe(get_var_string(&argvars[0]));
3985 }
3986 
3987 /*
3988  * "exists()" function
3989  */
3990     static void
3991 f_exists(argvars, retvar)
3992     VAR		argvars;
3993     VAR		retvar;
3994 {
3995     char_u	*p;
3996     char_u	*name;
3997     int		n = FALSE;
3998     int		len = 0;
3999 
4000     p = get_var_string(&argvars[0]);
4001     if (*p == '$')			/* environment variable */
4002     {
4003 	/* first try "normal" environment variables (fast) */
4004 	if (mch_getenv(p + 1) != NULL)
4005 	    n = TRUE;
4006 	else
4007 	{
4008 	    /* try expanding things like $VIM and ${HOME} */
4009 	    p = expand_env_save(p);
4010 	    if (p != NULL && *p != '$')
4011 		n = TRUE;
4012 	    vim_free(p);
4013 	}
4014     }
4015     else if (*p == '&' || *p == '+')			/* option */
4016 	n = (get_option_var(&p, NULL, TRUE) == OK);
4017     else if (*p == '*')			/* internal or user defined function */
4018     {
4019 	++p;
4020 	p = trans_function_name(&p, FALSE, TRUE);
4021 	if (p != NULL)
4022 	{
4023 	    if (ASCII_ISUPPER(*p) || p[0] == K_SPECIAL)
4024 		n = (find_func(p) != NULL);
4025 	    else if (ASCII_ISLOWER(*p))
4026 		n = (find_internal_func(p) >= 0);
4027 	    vim_free(p);
4028 	}
4029     }
4030     else if (*p == ':')
4031     {
4032 	n = cmd_exists(p + 1);
4033     }
4034     else if (*p == '#')
4035     {
4036 #ifdef FEAT_AUTOCMD
4037 	name = p + 1;
4038 	p = vim_strchr(name, '#');
4039 	if (p != NULL)
4040 	    n = au_exists(name, p, p + 1);
4041 	else
4042 	    n = au_exists(name, name + STRLEN(name), NULL);
4043 #endif
4044     }
4045     else				/* internal variable */
4046     {
4047 #ifdef FEAT_MAGIC_BRACES
4048 	char_u	*expr_start;
4049 	char_u	*expr_end;
4050 	char_u  *temp_string = NULL;
4051 	char_u	*s;
4052 #endif
4053 	name = p;
4054 
4055 #ifdef FEAT_MAGIC_BRACES
4056 	/* Find the end of the name. */
4057 	s = find_name_end(name, &expr_start, &expr_end);
4058 	if (expr_start != NULL)
4059 	{
4060 	    temp_string = make_expanded_name(name, expr_start, expr_end, s);
4061 	    if (temp_string != NULL)
4062 	    {
4063 		len = STRLEN(temp_string);
4064 		name = temp_string;
4065 	    }
4066 	}
4067 #endif
4068 	if (len == 0)
4069 	    len = get_id_len(&p);
4070 	if (len != 0)
4071 	    n = (get_var_var(name, len, NULL) == OK);
4072 
4073 #ifdef FEAT_MAGIC_BRACES
4074 	vim_free(temp_string);
4075 #endif
4076     }
4077 
4078     retvar->var_val.var_number = n;
4079 }
4080 
4081 /*
4082  * "expand()" function
4083  */
4084     static void
4085 f_expand(argvars, retvar)
4086     VAR		argvars;
4087     VAR		retvar;
4088 {
4089     char_u	*s;
4090     int		len;
4091     char_u	*errormsg;
4092     int		flags = WILD_SILENT|WILD_USE_NL|WILD_LIST_NOTFOUND;
4093     expand_T	xpc;
4094 
4095     retvar->var_type = VAR_STRING;
4096     s = get_var_string(&argvars[0]);
4097     if (*s == '%' || *s == '#' || *s == '<')
4098     {
4099 	++emsg_off;
4100 	retvar->var_val.var_string = eval_vars(s, &len, NULL, &errormsg, s);
4101 	--emsg_off;
4102     }
4103     else
4104     {
4105 	/* When the optional second argument is non-zero, don't remove matches
4106 	 * for 'suffixes' and 'wildignore' */
4107 	if (argvars[1].var_type != VAR_UNKNOWN && get_var_number(&argvars[1]))
4108 	    flags |= WILD_KEEP_ALL;
4109 	ExpandInit(&xpc);
4110 	xpc.xp_context = EXPAND_FILES;
4111 	retvar->var_val.var_string = ExpandOne(&xpc, s, NULL, flags, WILD_ALL);
4112 	ExpandCleanup(&xpc);
4113     }
4114 }
4115 
4116 /*
4117  * "filereadable()" function
4118  */
4119     static void
4120 f_filereadable(argvars, retvar)
4121     VAR		argvars;
4122     VAR		retvar;
4123 {
4124     FILE	*fd;
4125     char_u	*p;
4126     int		n;
4127 
4128     p = get_var_string(&argvars[0]);
4129     if (*p && !mch_isdir(p) && (fd = mch_fopen((char *)p, "r")) != NULL)
4130     {
4131 	n = TRUE;
4132 	fclose(fd);
4133     }
4134     else
4135 	n = FALSE;
4136 
4137     retvar->var_val.var_number = n;
4138 }
4139 
4140 /*
4141  * return 0 for not writable, 1 for writable file, 2 for a dir which we have
4142  * rights to write into.
4143  */
4144     static void
4145 f_filewritable(argvars, retvar)
4146     VAR		argvars;
4147     VAR		retvar;
4148 {
4149     char_u	*p;
4150     int		retval = 0;
4151 #if defined(UNIX) || defined(VMS)
4152     int		perm = 0;
4153 #endif
4154 
4155     p = get_var_string(&argvars[0]);
4156 #if defined(UNIX) || defined(VMS)
4157     perm = mch_getperm(p);
4158 #endif
4159 #ifndef MACOS_CLASSIC /* TODO: get either mch_writable or mch_access */
4160     if (
4161 # ifdef WIN3264
4162 	    mch_writable(p) &&
4163 # else
4164 # if defined(UNIX) || defined(VMS)
4165 	    (perm & 0222) &&
4166 #  endif
4167 # endif
4168 	    mch_access((char *)p, W_OK) == 0
4169        )
4170 #endif
4171     {
4172 	++retval;
4173 	if (mch_isdir(p))
4174 	    ++retval;
4175     }
4176     retvar->var_val.var_number = retval;
4177 }
4178 
4179 /*
4180  * "finddir({fname}[, {path}[, {count}]])" function
4181  */
4182     static void
4183 f_finddir(argvars, retvar)
4184     VAR		argvars;
4185     VAR		retvar;
4186 {
4187     f_findfilendir(argvars, retvar, TRUE);
4188 }
4189 
4190 /*
4191  * "findfile({fname}[, {path}[, {count}]])" function
4192  */
4193     static void
4194 f_findfile(argvars, retvar)
4195     VAR		argvars;
4196     VAR		retvar;
4197 {
4198     f_findfilendir(argvars, retvar, FALSE);
4199 }
4200 
4201     static void
4202 f_findfilendir(argvars, retvar, dir)
4203     VAR		argvars;
4204     VAR		retvar;
4205     int		dir;
4206 {
4207 #ifdef FEAT_SEARCHPATH
4208     char_u	*fname;
4209     char_u	*fresult = NULL;
4210     char_u	*path = *curbuf->b_p_path == NUL ? p_path : curbuf->b_p_path;
4211     char_u	*p;
4212     char_u	pathbuf[NUMBUFLEN];
4213     int		count = 1;
4214     int		first = TRUE;
4215 
4216     fname = get_var_string(&argvars[0]);
4217 
4218     if (argvars[1].var_type != VAR_UNKNOWN)
4219     {
4220 	p = get_var_string_buf(&argvars[1], pathbuf);
4221 	if (*p != NUL)
4222 	    path = p;
4223 
4224 	if (argvars[2].var_type != VAR_UNKNOWN)
4225 	    count = get_var_number(&argvars[2]);
4226     }
4227 
4228     do
4229     {
4230 	vim_free(fresult);
4231 	fresult = find_file_in_path_option(first ? fname : NULL,
4232 					    first ? (int)STRLEN(fname) : 0,
4233 					    0, first, path, dir, NULL);
4234 	first = FALSE;
4235     } while (--count > 0 && fresult != NULL);
4236 
4237     retvar->var_val.var_string = fresult;
4238 #else
4239     retvar->var_val.var_string = NULL;
4240 #endif
4241     retvar->var_type = VAR_STRING;
4242 }
4243 
4244 /*
4245  * "fnamemodify({fname}, {mods})" function
4246  */
4247     static void
4248 f_fnamemodify(argvars, retvar)
4249     VAR		argvars;
4250     VAR		retvar;
4251 {
4252     char_u	*fname;
4253     char_u	*mods;
4254     int		usedlen = 0;
4255     int		len;
4256     char_u	*fbuf = NULL;
4257     char_u	buf[NUMBUFLEN];
4258 
4259     fname = get_var_string(&argvars[0]);
4260     mods = get_var_string_buf(&argvars[1], buf);
4261     len = (int)STRLEN(fname);
4262 
4263     (void)modify_fname(mods, &usedlen, &fname, &fbuf, &len);
4264 
4265     retvar->var_type = VAR_STRING;
4266     if (fname == NULL)
4267 	retvar->var_val.var_string = NULL;
4268     else
4269 	retvar->var_val.var_string = vim_strnsave(fname, len);
4270     vim_free(fbuf);
4271 }
4272 
4273 /*
4274  * "foldclosed()" function
4275  */
4276     static void
4277 f_foldclosed(argvars, retvar)
4278     VAR		argvars;
4279     VAR		retvar;
4280 {
4281     foldclosed_both(argvars, retvar, FALSE);
4282 }
4283 
4284 /*
4285  * "foldclosedend()" function
4286  */
4287     static void
4288 f_foldclosedend(argvars, retvar)
4289     VAR		argvars;
4290     VAR		retvar;
4291 {
4292     foldclosed_both(argvars, retvar, TRUE);
4293 }
4294 
4295 /*
4296  * "foldclosed()" function
4297  */
4298     static void
4299 foldclosed_both(argvars, retvar, end)
4300     VAR		argvars;
4301     VAR		retvar;
4302     int		end;
4303 {
4304 #ifdef FEAT_FOLDING
4305     linenr_T	lnum;
4306     linenr_T	first, last;
4307 
4308     lnum = get_var_lnum(argvars);
4309     if (lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count)
4310     {
4311 	if (hasFoldingWin(curwin, lnum, &first, &last, FALSE, NULL))
4312 	{
4313 	    if (end)
4314 		retvar->var_val.var_number = (varnumber_T)last;
4315 	    else
4316 		retvar->var_val.var_number = (varnumber_T)first;
4317 	    return;
4318 	}
4319     }
4320 #endif
4321     retvar->var_val.var_number = -1;
4322 }
4323 
4324 /*
4325  * "foldlevel()" function
4326  */
4327     static void
4328 f_foldlevel(argvars, retvar)
4329     VAR		argvars;
4330     VAR		retvar;
4331 {
4332 #ifdef FEAT_FOLDING
4333     linenr_T	lnum;
4334 
4335     lnum = get_var_lnum(argvars);
4336     if (lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count)
4337 	retvar->var_val.var_number = foldLevel(lnum);
4338     else
4339 #endif
4340 	retvar->var_val.var_number = 0;
4341 }
4342 
4343 /*
4344  * "foldtext()" function
4345  */
4346 /*ARGSUSED*/
4347     static void
4348 f_foldtext(argvars, retvar)
4349     VAR		argvars;
4350     VAR		retvar;
4351 {
4352 #ifdef FEAT_FOLDING
4353     linenr_T	lnum;
4354     char_u	*s;
4355     char_u	*r;
4356     int		len;
4357     char	*txt;
4358 #endif
4359 
4360     retvar->var_type = VAR_STRING;
4361     retvar->var_val.var_string = NULL;
4362 #ifdef FEAT_FOLDING
4363     if ((linenr_T)vimvars[VV_FOLDSTART].val > 0
4364 	    && (linenr_T)vimvars[VV_FOLDEND].val <= curbuf->b_ml.ml_line_count
4365 	    && vimvars[VV_FOLDDASHES].val != NULL)
4366     {
4367 	/* Find first non-empty line in the fold. */
4368 	lnum = (linenr_T)vimvars[VV_FOLDSTART].val;
4369 	while (lnum < (linenr_T)vimvars[VV_FOLDEND].val)
4370 	{
4371 	    if (!linewhite(lnum))
4372 		break;
4373 	    ++lnum;
4374 	}
4375 
4376 	/* Find interesting text in this line. */
4377 	s = skipwhite(ml_get(lnum));
4378 	/* skip C comment-start */
4379 	if (s[0] == '/' && (s[1] == '*' || s[1] == '/'))
4380 	    s = skipwhite(s + 2);
4381 	txt = _("+-%s%3ld lines: ");
4382 	r = alloc((unsigned)(STRLEN(txt)
4383 		    + STRLEN(vimvars[VV_FOLDDASHES].val)    /* for %s */
4384 		    + 20				    /* for %3ld */
4385 		    + STRLEN(s)));			    /* concatenated */
4386 	if (r != NULL)
4387 	{
4388 	    sprintf((char *)r, txt, vimvars[VV_FOLDDASHES].val,
4389 		    (long)((linenr_T)vimvars[VV_FOLDEND].val
4390 				   - (linenr_T)vimvars[VV_FOLDSTART].val + 1));
4391 	    len = (int)STRLEN(r);
4392 	    STRCAT(r, s);
4393 	    /* remove 'foldmarker' and 'commentstring' */
4394 	    foldtext_cleanup(r + len);
4395 	    retvar->var_val.var_string = r;
4396 	}
4397     }
4398 #endif
4399 }
4400 
4401 /*
4402  * "foreground()" function
4403  */
4404 /*ARGSUSED*/
4405     static void
4406 f_foreground(argvars, retvar)
4407     VAR		argvars;
4408     VAR		retvar;
4409 {
4410     retvar->var_val.var_number = 0;
4411 #ifdef FEAT_GUI
4412     if (gui.in_use)
4413 	gui_mch_set_foreground();
4414 #else
4415 # ifdef WIN32
4416     win32_set_foreground();
4417 # endif
4418 #endif
4419 }
4420 
4421 /*
4422  * "getchar()" function
4423  */
4424     static void
4425 f_getchar(argvars, retvar)
4426     VAR		argvars;
4427     VAR		retvar;
4428 {
4429     varnumber_T		n;
4430 
4431     ++no_mapping;
4432     ++allow_keys;
4433     if (argvars[0].var_type == VAR_UNKNOWN)
4434 	/* getchar(): blocking wait. */
4435 	n = safe_vgetc();
4436     else if (get_var_number(&argvars[0]) == 1)
4437 	/* getchar(1): only check if char avail */
4438 	n = vpeekc();
4439     else if (vpeekc() == NUL)
4440 	/* getchar(0) and no char avail: return zero */
4441 	n = 0;
4442     else
4443 	/* getchar(0) and char avail: return char */
4444 	n = safe_vgetc();
4445     --no_mapping;
4446     --allow_keys;
4447 
4448     retvar->var_val.var_number = n;
4449     if (IS_SPECIAL(n) || mod_mask != 0)
4450     {
4451 	char_u		temp[10];   /* modifier: 3, mbyte-char: 6, NUL: 1 */
4452 	int		i = 0;
4453 
4454 	/* Turn a special key into three bytes, plus modifier. */
4455 	if (mod_mask != 0)
4456 	{
4457 	    temp[i++] = K_SPECIAL;
4458 	    temp[i++] = KS_MODIFIER;
4459 	    temp[i++] = mod_mask;
4460 	}
4461 	if (IS_SPECIAL(n))
4462 	{
4463 	    temp[i++] = K_SPECIAL;
4464 	    temp[i++] = K_SECOND(n);
4465 	    temp[i++] = K_THIRD(n);
4466 	}
4467 #ifdef FEAT_MBYTE
4468 	else if (has_mbyte)
4469 	    i += (*mb_char2bytes)(n, temp + i);
4470 #endif
4471 	else
4472 	    temp[i++] = n;
4473 	temp[i++] = NUL;
4474 	retvar->var_type = VAR_STRING;
4475 	retvar->var_val.var_string = vim_strsave(temp);
4476     }
4477 }
4478 
4479 /*
4480  * "getcharmod()" function
4481  */
4482 /*ARGSUSED*/
4483     static void
4484 f_getcharmod(argvars, retvar)
4485     VAR		argvars;
4486     VAR		retvar;
4487 {
4488     retvar->var_val.var_number = mod_mask;
4489 }
4490 
4491 /*
4492  * "getcmdline()" function
4493  */
4494 /*ARGSUSED*/
4495     static void
4496 f_getcmdline(argvars, retvar)
4497     VAR		argvars;
4498     VAR		retvar;
4499 {
4500     retvar->var_type = VAR_STRING;
4501     retvar->var_val.var_string = get_cmdline_str();
4502 }
4503 
4504 /*
4505  * "getcmdpos()" function
4506  */
4507 /*ARGSUSED*/
4508     static void
4509 f_getcmdpos(argvars, retvar)
4510     VAR		argvars;
4511     VAR		retvar;
4512 {
4513     retvar->var_val.var_number = get_cmdline_pos() + 1;
4514 }
4515 
4516 /*
4517  * "getbufvar()" function
4518  */
4519     static void
4520 f_getbufvar(argvars, retvar)
4521     VAR		argvars;
4522     VAR		retvar;
4523 {
4524     buf_T	*buf;
4525     buf_T	*save_curbuf;
4526     char_u	*varname;
4527     VAR		v;
4528 
4529     ++emsg_off;
4530     buf = get_buf_var(&argvars[0]);
4531     varname = get_var_string(&argvars[1]);
4532 
4533     retvar->var_type = VAR_STRING;
4534     retvar->var_val.var_string = NULL;
4535 
4536     if (buf != NULL && varname != NULL)
4537     {
4538 	if (*varname == '&')	/* buffer-local-option */
4539 	{
4540 	    /* set curbuf to be our buf, temporarily */
4541 	    save_curbuf = curbuf;
4542 	    curbuf = buf;
4543 
4544 	    get_option_var(&varname, retvar, TRUE);
4545 
4546 	    /* restore previous notion of curbuf */
4547 	    curbuf = save_curbuf;
4548 	}
4549 	else
4550 	{
4551 	    /* look up the variable */
4552 	    v = find_var_in_ga(&buf->b_vars, varname);
4553 	    if (v != NULL)
4554 		copy_var(v, retvar);
4555 	}
4556     }
4557 
4558     --emsg_off;
4559 }
4560 
4561 /*
4562  * "getcwd()" function
4563  */
4564 /*ARGSUSED*/
4565     static void
4566 f_getcwd(argvars, retvar)
4567     VAR		argvars;
4568     VAR		retvar;
4569 {
4570     char_u	cwd[MAXPATHL];
4571 
4572     retvar->var_type = VAR_STRING;
4573     if (mch_dirname(cwd, MAXPATHL) == FAIL)
4574 	retvar->var_val.var_string = NULL;
4575     else
4576     {
4577 	retvar->var_val.var_string = vim_strsave(cwd);
4578 #ifdef BACKSLASH_IN_FILENAME
4579 	slash_adjust(retvar->var_val.var_string);
4580 #endif
4581     }
4582 }
4583 
4584 /*
4585  * "getfperm({fname})" function
4586  */
4587     static void
4588 f_getfperm(argvars, retvar)
4589     VAR		argvars;
4590     VAR		retvar;
4591 {
4592     char_u	*fname;
4593     struct stat st;
4594     char_u	*perm = NULL;
4595     char_u	flags[] = "rwx";
4596     int		i;
4597 
4598     fname = get_var_string(&argvars[0]);
4599 
4600     retvar->var_type = VAR_STRING;
4601     if (mch_stat((char *)fname, &st) >= 0)
4602     {
4603 	perm = vim_strsave((char_u *)"---------");
4604 	if (perm != NULL)
4605 	{
4606 	    for (i = 0; i < 9; i++)
4607 	    {
4608 		if (st.st_mode & (1 << (8 - i)))
4609 		    perm[i] = flags[i % 3];
4610 	    }
4611 	}
4612     }
4613     retvar->var_val.var_string = perm;
4614 }
4615 
4616 /*
4617  * "getfsize({fname})" function
4618  */
4619     static void
4620 f_getfsize(argvars, retvar)
4621     VAR		argvars;
4622     VAR		retvar;
4623 {
4624     char_u	*fname;
4625     struct stat	st;
4626 
4627     fname = get_var_string(&argvars[0]);
4628 
4629     retvar->var_type = VAR_NUMBER;
4630 
4631     if (mch_stat((char *)fname, &st) >= 0)
4632     {
4633 	if (mch_isdir(fname))
4634 	    retvar->var_val.var_number = 0;
4635 	else
4636 	    retvar->var_val.var_number = (varnumber_T)st.st_size;
4637     }
4638     else
4639 	  retvar->var_val.var_number = -1;
4640 }
4641 
4642 /*
4643  * "getftime({fname})" function
4644  */
4645     static void
4646 f_getftime(argvars, retvar)
4647     VAR		argvars;
4648     VAR		retvar;
4649 {
4650     char_u	*fname;
4651     struct stat	st;
4652 
4653     fname = get_var_string(&argvars[0]);
4654 
4655     if (mch_stat((char *)fname, &st) >= 0)
4656 	retvar->var_val.var_number = (varnumber_T)st.st_mtime;
4657     else
4658 	retvar->var_val.var_number = -1;
4659 }
4660 
4661 /*
4662  * "getftype({fname})" function
4663  */
4664     static void
4665 f_getftype(argvars, retvar)
4666     VAR		argvars;
4667     VAR		retvar;
4668 {
4669     char_u	*fname;
4670     struct stat st;
4671     char_u	*type = NULL;
4672     char	*t;
4673 
4674     fname = get_var_string(&argvars[0]);
4675 
4676     retvar->var_type = VAR_STRING;
4677     if (mch_lstat((char *)fname, &st) >= 0)
4678     {
4679 #ifdef S_ISREG
4680 	if (S_ISREG(st.st_mode))
4681 	    t = "file";
4682 	else if (S_ISDIR(st.st_mode))
4683 	    t = "dir";
4684 # ifdef S_ISLNK
4685 	else if (S_ISLNK(st.st_mode))
4686 	    t = "link";
4687 # endif
4688 # ifdef S_ISBLK
4689 	else if (S_ISBLK(st.st_mode))
4690 	    t = "bdev";
4691 # endif
4692 # ifdef S_ISCHR
4693 	else if (S_ISCHR(st.st_mode))
4694 	    t = "cdev";
4695 # endif
4696 # ifdef S_ISFIFO
4697 	else if (S_ISFIFO(st.st_mode))
4698 	    t = "fifo";
4699 # endif
4700 # ifdef S_ISSOCK
4701 	else if (S_ISSOCK(st.st_mode))
4702 	    t = "fifo";
4703 # endif
4704 	else
4705 	    t = "other";
4706 #else
4707 # ifdef S_IFMT
4708 	switch (st.st_mode & S_IFMT)
4709 	{
4710 	    case S_IFREG: t = "file"; break;
4711 	    case S_IFDIR: t = "dir"; break;
4712 #  ifdef S_IFLNK
4713 	    case S_IFLNK: t = "link"; break;
4714 #  endif
4715 #  ifdef S_IFBLK
4716 	    case S_IFBLK: t = "bdev"; break;
4717 #  endif
4718 #  ifdef S_IFCHR
4719 	    case S_IFCHR: t = "cdev"; break;
4720 #  endif
4721 #  ifdef S_IFIFO
4722 	    case S_IFIFO: t = "fifo"; break;
4723 #  endif
4724 #  ifdef S_IFSOCK
4725 	    case S_IFSOCK: t = "socket"; break;
4726 #  endif
4727 	    default: t = "other";
4728 	}
4729 # else
4730 	if (mch_isdir(fname))
4731 	    t = "dir";
4732 	else
4733 	    t = "file";
4734 # endif
4735 #endif
4736 	type = vim_strsave((char_u *)t);
4737     }
4738     retvar->var_val.var_string = type;
4739 }
4740 
4741 /*
4742  * "getreg()" function
4743  */
4744     static void
4745 f_getreg(argvars, retvar)
4746     VAR		argvars;
4747     VAR		retvar;
4748 {
4749     char_u	*strregname;
4750     int		regname;
4751 
4752     if (argvars[0].var_type != VAR_UNKNOWN)
4753 	strregname = get_var_string(&argvars[0]);
4754     else
4755 	strregname = vimvars[VV_REG].val;
4756     regname = (strregname == NULL ? '"' : *strregname);
4757     if (regname == 0)
4758 	regname = '"';
4759 
4760     retvar->var_type = VAR_STRING;
4761     retvar->var_val.var_string = get_reg_contents(regname, TRUE);
4762 }
4763 
4764 /*
4765  * "getregtype()" function
4766  */
4767     static void
4768 f_getregtype(argvars, retvar)
4769     VAR		argvars;
4770     VAR		retvar;
4771 {
4772     char_u	*strregname;
4773     int		regname;
4774     char_u	buf[NUMBUFLEN + 2];
4775     long	reglen = 0;
4776 
4777     if (argvars[0].var_type != VAR_UNKNOWN)
4778 	strregname = get_var_string(&argvars[0]);
4779     else
4780 	/* Default to v:register */
4781 	strregname = vimvars[VV_REG].val;
4782 
4783     regname = (strregname == NULL ? '"' : *strregname);
4784     if (regname == 0)
4785 	regname = '"';
4786 
4787     buf[0] = NUL;
4788     buf[1] = NUL;
4789     switch (get_reg_type(regname, &reglen))
4790     {
4791 	case MLINE: buf[0] = 'V'; break;
4792 	case MCHAR: buf[0] = 'v'; break;
4793 #ifdef FEAT_VISUAL
4794 	case MBLOCK:
4795 		buf[0] = Ctrl_V;
4796 		sprintf((char *)buf + 1, "%ld", reglen + 1);
4797 		break;
4798 #endif
4799     }
4800     retvar->var_type = VAR_STRING;
4801     retvar->var_val.var_string = vim_strsave(buf);
4802 }
4803 
4804 /*
4805  * "getline(lnum)" function
4806  */
4807     static void
4808 f_getline(argvars, retvar)
4809     VAR		argvars;
4810     VAR		retvar;
4811 {
4812     linenr_T	lnum;
4813     char_u	*p;
4814 
4815     lnum = get_var_lnum(argvars);
4816 
4817     if (lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count)
4818 	p = ml_get(lnum);
4819     else
4820 	p = (char_u *)"";
4821 
4822     retvar->var_type = VAR_STRING;
4823     retvar->var_val.var_string = vim_strsave(p);
4824 }
4825 
4826 /*
4827  * "getwinposx()" function
4828  */
4829 /*ARGSUSED*/
4830     static void
4831 f_getwinposx(argvars, retvar)
4832     VAR		argvars;
4833     VAR		retvar;
4834 {
4835     retvar->var_val.var_number = -1;
4836 #ifdef FEAT_GUI
4837     if (gui.in_use)
4838     {
4839 	int	    x, y;
4840 
4841 	if (gui_mch_get_winpos(&x, &y) == OK)
4842 	    retvar->var_val.var_number = x;
4843     }
4844 #endif
4845 }
4846 
4847 /*
4848  * "getwinposy()" function
4849  */
4850 /*ARGSUSED*/
4851     static void
4852 f_getwinposy(argvars, retvar)
4853     VAR		argvars;
4854     VAR		retvar;
4855 {
4856     retvar->var_val.var_number = -1;
4857 #ifdef FEAT_GUI
4858     if (gui.in_use)
4859     {
4860 	int	    x, y;
4861 
4862 	if (gui_mch_get_winpos(&x, &y) == OK)
4863 	    retvar->var_val.var_number = y;
4864     }
4865 #endif
4866 }
4867 
4868 /*
4869  * "getwinvar()" function
4870  */
4871     static void
4872 f_getwinvar(argvars, retvar)
4873     VAR		argvars;
4874     VAR		retvar;
4875 {
4876     win_T	*win, *oldcurwin;
4877     char_u	*varname;
4878     VAR		v;
4879 
4880     ++emsg_off;
4881     win = find_win_by_nr(&argvars[0]);
4882     varname = get_var_string(&argvars[1]);
4883 
4884     retvar->var_type = VAR_STRING;
4885     retvar->var_val.var_string = NULL;
4886 
4887     if (win != NULL && varname != NULL)
4888     {
4889 	if (*varname == '&')	/* window-local-option */
4890 	{
4891 	    /* set curwin to be our win, temporarily */
4892 	    oldcurwin = curwin;
4893 	    curwin = win;
4894 
4895 	    get_option_var(&varname, retvar , 1);
4896 
4897 	    /* restore previous notion of curwin */
4898 	    curwin = oldcurwin;
4899 	}
4900 	else
4901 	{
4902 	    /* look up the variable */
4903 	    v = find_var_in_ga(&win->w_vars, varname);
4904 	    if (v != NULL)
4905 		copy_var(v, retvar);
4906 	}
4907     }
4908 
4909     --emsg_off;
4910 }
4911 
4912 /*
4913  * "glob()" function
4914  */
4915     static void
4916 f_glob(argvars, retvar)
4917     VAR		argvars;
4918     VAR		retvar;
4919 {
4920     expand_T	xpc;
4921 
4922     ExpandInit(&xpc);
4923     xpc.xp_context = EXPAND_FILES;
4924     retvar->var_type = VAR_STRING;
4925     retvar->var_val.var_string = ExpandOne(&xpc, get_var_string(&argvars[0]),
4926 				     NULL, WILD_USE_NL|WILD_SILENT, WILD_ALL);
4927     ExpandCleanup(&xpc);
4928 }
4929 
4930 /*
4931  * "globpath()" function
4932  */
4933     static void
4934 f_globpath(argvars, retvar)
4935     VAR		argvars;
4936     VAR		retvar;
4937 {
4938     char_u	buf1[NUMBUFLEN];
4939 
4940     retvar->var_type = VAR_STRING;
4941     retvar->var_val.var_string = globpath(get_var_string(&argvars[0]),
4942 				       get_var_string_buf(&argvars[1], buf1));
4943 }
4944 
4945 /*
4946  * "has()" function
4947  */
4948     static void
4949 f_has(argvars, retvar)
4950     VAR		argvars;
4951     VAR		retvar;
4952 {
4953     int		i;
4954     char_u	*name;
4955     int		n = FALSE;
4956     static char	*(has_list[]) =
4957     {
4958 #ifdef AMIGA
4959 	"amiga",
4960 # ifdef FEAT_ARP
4961 	"arp",
4962 # endif
4963 #endif
4964 #ifdef __BEOS__
4965 	"beos",
4966 #endif
4967 #ifdef MSDOS
4968 # ifdef DJGPP
4969 	"dos32",
4970 # else
4971 	"dos16",
4972 # endif
4973 #endif
4974 #ifdef MACOS /* TODO: Should we add MACOS_CLASSIC, MACOS_X? (Dany) */
4975 	"mac",
4976 #endif
4977 #if defined(MACOS_X_UNIX)
4978 	"macunix",
4979 #endif
4980 #ifdef OS2
4981 	"os2",
4982 #endif
4983 #ifdef __QNX__
4984 	"qnx",
4985 #endif
4986 #ifdef RISCOS
4987 	"riscos",
4988 #endif
4989 #ifdef UNIX
4990 	"unix",
4991 #endif
4992 #ifdef VMS
4993 	"vms",
4994 #endif
4995 #ifdef WIN16
4996 	"win16",
4997 #endif
4998 #ifdef WIN32
4999 	"win32",
5000 #endif
5001 #if defined(UNIX) && (defined(__CYGWIN32__) || defined(__CYGWIN__))
5002 	"win32unix",
5003 #endif
5004 #ifdef WIN64
5005 	"win64",
5006 #endif
5007 #ifdef EBCDIC
5008 	"ebcdic",
5009 #endif
5010 #ifndef CASE_INSENSITIVE_FILENAME
5011 	"fname_case",
5012 #endif
5013 #ifdef FEAT_ARABIC
5014 	"arabic",
5015 #endif
5016 #ifdef FEAT_AUTOCMD
5017 	"autocmd",
5018 #endif
5019 #ifdef FEAT_BEVAL
5020 	"balloon_eval",
5021 #endif
5022 #if defined(SOME_BUILTIN_TCAPS) || defined(ALL_BUILTIN_TCAPS)
5023 	"builtin_terms",
5024 # ifdef ALL_BUILTIN_TCAPS
5025 	"all_builtin_terms",
5026 # endif
5027 #endif
5028 #ifdef FEAT_BYTEOFF
5029 	"byte_offset",
5030 #endif
5031 #ifdef FEAT_CINDENT
5032 	"cindent",
5033 #endif
5034 #ifdef FEAT_CLIENTSERVER
5035 	"clientserver",
5036 #endif
5037 #ifdef FEAT_CLIPBOARD
5038 	"clipboard",
5039 #endif
5040 #ifdef FEAT_CMDL_COMPL
5041 	"cmdline_compl",
5042 #endif
5043 #ifdef FEAT_CMDHIST
5044 	"cmdline_hist",
5045 #endif
5046 #ifdef FEAT_COMMENTS
5047 	"comments",
5048 #endif
5049 #ifdef FEAT_CRYPT
5050 	"cryptv",
5051 #endif
5052 #ifdef FEAT_CSCOPE
5053 	"cscope",
5054 #endif
5055 #ifdef DEBUG
5056 	"debug",
5057 #endif
5058 #ifdef FEAT_CON_DIALOG
5059 	"dialog_con",
5060 #endif
5061 #ifdef FEAT_GUI_DIALOG
5062 	"dialog_gui",
5063 #endif
5064 #ifdef FEAT_DIFF
5065 	"diff",
5066 #endif
5067 #ifdef FEAT_DIGRAPHS
5068 	"digraphs",
5069 #endif
5070 #ifdef FEAT_DND
5071 	"dnd",
5072 #endif
5073 #ifdef FEAT_EMACS_TAGS
5074 	"emacs_tags",
5075 #endif
5076 	"eval",	    /* always present, of course! */
5077 #ifdef FEAT_EX_EXTRA
5078 	"ex_extra",
5079 #endif
5080 #ifdef FEAT_SEARCH_EXTRA
5081 	"extra_search",
5082 #endif
5083 #ifdef FEAT_FKMAP
5084 	"farsi",
5085 #endif
5086 #ifdef FEAT_SEARCHPATH
5087 	"file_in_path",
5088 #endif
5089 #ifdef FEAT_FIND_ID
5090 	"find_in_path",
5091 #endif
5092 #ifdef FEAT_FOLDING
5093 	"folding",
5094 #endif
5095 #ifdef FEAT_FOOTER
5096 	"footer",
5097 #endif
5098 #if !defined(USE_SYSTEM) && defined(UNIX)
5099 	"fork",
5100 #endif
5101 #ifdef FEAT_GETTEXT
5102 	"gettext",
5103 #endif
5104 #ifdef FEAT_GUI
5105 	"gui",
5106 #endif
5107 #ifdef FEAT_GUI_ATHENA
5108 # ifdef FEAT_GUI_NEXTAW
5109 	"gui_neXtaw",
5110 # else
5111 	"gui_athena",
5112 # endif
5113 #endif
5114 #ifdef FEAT_GUI_BEOS
5115 	"gui_beos",
5116 #endif
5117 #ifdef FEAT_GUI_KDE
5118 	"gui_kde",
5119 #endif
5120 #ifdef FEAT_GUI_GTK
5121 	"gui_gtk",
5122 # ifdef HAVE_GTK2
5123 	"gui_gtk2",
5124 # endif
5125 #endif
5126 #ifdef FEAT_GUI_MAC
5127 	"gui_mac",
5128 #endif
5129 #ifdef FEAT_GUI_MOTIF
5130 	"gui_motif",
5131 #endif
5132 #ifdef FEAT_GUI_PHOTON
5133 	"gui_photon",
5134 #endif
5135 #ifdef FEAT_GUI_W16
5136 	"gui_win16",
5137 #endif
5138 #ifdef FEAT_GUI_W32
5139 	"gui_win32",
5140 #endif
5141 #ifdef FEAT_HANGULIN
5142 	"hangul_input",
5143 #endif
5144 #if defined(HAVE_ICONV_H) && defined(USE_ICONV)
5145 	"iconv",
5146 #endif
5147 #ifdef FEAT_INS_EXPAND
5148 	"insert_expand",
5149 #endif
5150 #ifdef FEAT_JUMPLIST
5151 	"jumplist",
5152 #endif
5153 #ifdef FEAT_KEYMAP
5154 	"keymap",
5155 #endif
5156 #ifdef FEAT_LANGMAP
5157 	"langmap",
5158 #endif
5159 #ifdef FEAT_LIBCALL
5160 	"libcall",
5161 #endif
5162 #ifdef FEAT_LINEBREAK
5163 	"linebreak",
5164 #endif
5165 #ifdef FEAT_LISP
5166 	"lispindent",
5167 #endif
5168 #ifdef FEAT_LISTCMDS
5169 	"listcmds",
5170 #endif
5171 #ifdef FEAT_LOCALMAP
5172 	"localmap",
5173 #endif
5174 #ifdef FEAT_MENU
5175 	"menu",
5176 #endif
5177 #ifdef FEAT_SESSION
5178 	"mksession",
5179 #endif
5180 #ifdef FEAT_MODIFY_FNAME
5181 	"modify_fname",
5182 #endif
5183 #ifdef FEAT_MOUSE
5184 	"mouse",
5185 #endif
5186 #ifdef FEAT_MOUSESHAPE
5187 	"mouseshape",
5188 #endif
5189 #if defined(UNIX) || defined(VMS)
5190 # ifdef FEAT_MOUSE_DEC
5191 	"mouse_dec",
5192 # endif
5193 # ifdef FEAT_MOUSE_GPM
5194 	"mouse_gpm",
5195 # endif
5196 # ifdef FEAT_MOUSE_JSB
5197 	"mouse_jsbterm",
5198 # endif
5199 # ifdef FEAT_MOUSE_NET
5200 	"mouse_netterm",
5201 # endif
5202 # ifdef FEAT_MOUSE_PTERM
5203 	"mouse_pterm",
5204 # endif
5205 # ifdef FEAT_MOUSE_XTERM
5206 	"mouse_xterm",
5207 # endif
5208 #endif
5209 #ifdef FEAT_MBYTE
5210 	"multi_byte",
5211 #endif
5212 #ifdef FEAT_MBYTE_IME
5213 	"multi_byte_ime",
5214 #endif
5215 #ifdef FEAT_MULTI_LANG
5216 	"multi_lang",
5217 #endif
5218 #ifdef FEAT_MZSCHEME
5219 	"mzscheme",
5220 #endif
5221 #ifdef FEAT_OLE
5222 	"ole",
5223 #endif
5224 #ifdef FEAT_OSFILETYPE
5225 	"osfiletype",
5226 #endif
5227 #ifdef FEAT_PATH_EXTRA
5228 	"path_extra",
5229 #endif
5230 #ifdef FEAT_PERL
5231 #ifndef DYNAMIC_PERL
5232 	"perl",
5233 #endif
5234 #endif
5235 #ifdef FEAT_PYTHON
5236 #ifndef DYNAMIC_PYTHON
5237 	"python",
5238 #endif
5239 #endif
5240 #ifdef FEAT_POSTSCRIPT
5241 	"postscript",
5242 #endif
5243 #ifdef FEAT_PRINTER
5244 	"printer",
5245 #endif
5246 #ifdef FEAT_QUICKFIX
5247 	"quickfix",
5248 #endif
5249 #ifdef FEAT_RIGHTLEFT
5250 	"rightleft",
5251 #endif
5252 #if defined(FEAT_RUBY) && !defined(DYNAMIC_RUBY)
5253 	"ruby",
5254 #endif
5255 #ifdef FEAT_SCROLLBIND
5256 	"scrollbind",
5257 #endif
5258 #ifdef FEAT_CMDL_INFO
5259 	"showcmd",
5260 	"cmdline_info",
5261 #endif
5262 #ifdef FEAT_SIGNS
5263 	"signs",
5264 #endif
5265 #ifdef FEAT_SMARTINDENT
5266 	"smartindent",
5267 #endif
5268 #ifdef FEAT_SNIFF
5269 	"sniff",
5270 #endif
5271 #ifdef FEAT_STL_OPT
5272 	"statusline",
5273 #endif
5274 #ifdef FEAT_SUN_WORKSHOP
5275 	"sun_workshop",
5276 #endif
5277 #ifdef FEAT_NETBEANS_INTG
5278 	"netbeans_intg",
5279 #endif
5280 #ifdef FEAT_SYN_HL
5281 	"syntax",
5282 #endif
5283 #if defined(USE_SYSTEM) || !defined(UNIX)
5284 	"system",
5285 #endif
5286 #ifdef FEAT_TAG_BINS
5287 	"tag_binary",
5288 #endif
5289 #ifdef FEAT_TAG_OLDSTATIC
5290 	"tag_old_static",
5291 #endif
5292 #ifdef FEAT_TAG_ANYWHITE
5293 	"tag_any_white",
5294 #endif
5295 #ifdef FEAT_TCL
5296 # ifndef DYNAMIC_TCL
5297 	"tcl",
5298 # endif
5299 #endif
5300 #ifdef TERMINFO
5301 	"terminfo",
5302 #endif
5303 #ifdef FEAT_TERMRESPONSE
5304 	"termresponse",
5305 #endif
5306 #ifdef FEAT_TEXTOBJ
5307 	"textobjects",
5308 #endif
5309 #ifdef HAVE_TGETENT
5310 	"tgetent",
5311 #endif
5312 #ifdef FEAT_TITLE
5313 	"title",
5314 #endif
5315 #ifdef FEAT_TOOLBAR
5316 	"toolbar",
5317 #endif
5318 #ifdef FEAT_USR_CMDS
5319 	"user-commands",    /* was accidentally included in 5.4 */
5320 	"user_commands",
5321 #endif
5322 #ifdef FEAT_VIMINFO
5323 	"viminfo",
5324 #endif
5325 #ifdef FEAT_VERTSPLIT
5326 	"vertsplit",
5327 #endif
5328 #ifdef FEAT_VIRTUALEDIT
5329 	"virtualedit",
5330 #endif
5331 #ifdef FEAT_VISUAL
5332 	"visual",
5333 #endif
5334 #ifdef FEAT_VISUALEXTRA
5335 	"visualextra",
5336 #endif
5337 #ifdef FEAT_VREPLACE
5338 	"vreplace",
5339 #endif
5340 #ifdef FEAT_WILDIGN
5341 	"wildignore",
5342 #endif
5343 #ifdef FEAT_WILDMENU
5344 	"wildmenu",
5345 #endif
5346 #ifdef FEAT_WINDOWS
5347 	"windows",
5348 #endif
5349 #ifdef FEAT_WAK
5350 	"winaltkeys",
5351 #endif
5352 #ifdef FEAT_WRITEBACKUP
5353 	"writebackup",
5354 #endif
5355 #ifdef FEAT_XIM
5356 	"xim",
5357 #endif
5358 #ifdef FEAT_XFONTSET
5359 	"xfontset",
5360 #endif
5361 #ifdef USE_XSMP
5362 	"xsmp",
5363 #endif
5364 #ifdef USE_XSMP_INTERACT
5365 	"xsmp_interact",
5366 #endif
5367 #ifdef FEAT_XCLIPBOARD
5368 	"xterm_clipboard",
5369 #endif
5370 #ifdef FEAT_XTERM_SAVE
5371 	"xterm_save",
5372 #endif
5373 #if defined(UNIX) && defined(FEAT_X11)
5374 	"X11",
5375 #endif
5376 	NULL
5377     };
5378 
5379     name = get_var_string(&argvars[0]);
5380     for (i = 0; has_list[i] != NULL; ++i)
5381 	if (STRICMP(name, has_list[i]) == 0)
5382 	{
5383 	    n = TRUE;
5384 	    break;
5385 	}
5386 
5387     if (n == FALSE)
5388     {
5389 	if (STRNICMP(name, "patch", 5) == 0)
5390 	    n = has_patch(atoi((char *)name + 5));
5391 	else if (STRICMP(name, "vim_starting") == 0)
5392 	    n = (starting != 0);
5393 #ifdef DYNAMIC_TCL
5394 	else if (STRICMP(name, "tcl") == 0)
5395 	    n = tcl_enabled(FALSE);
5396 #endif
5397 #if defined(USE_ICONV) && defined(DYNAMIC_ICONV)
5398 	else if (STRICMP(name, "iconv") == 0)
5399 	    n = iconv_enabled(FALSE);
5400 #endif
5401 #ifdef DYNAMIC_RUBY
5402 	else if (STRICMP(name, "ruby") == 0)
5403 	    n = ruby_enabled(FALSE);
5404 #endif
5405 #ifdef DYNAMIC_PYTHON
5406 	else if (STRICMP(name, "python") == 0)
5407 	    n = python_enabled(FALSE);
5408 #endif
5409 #ifdef DYNAMIC_PERL
5410 	else if (STRICMP(name, "perl") == 0)
5411 	    n = perl_enabled(FALSE);
5412 #endif
5413 #ifdef FEAT_GUI
5414 	else if (STRICMP(name, "gui_running") == 0)
5415 	    n = (gui.in_use || gui.starting);
5416 # ifdef FEAT_GUI_W32
5417 	else if (STRICMP(name, "gui_win32s") == 0)
5418 	    n = gui_is_win32s();
5419 # endif
5420 # ifdef FEAT_BROWSE
5421 	else if (STRICMP(name, "browse") == 0)
5422 	    n = gui.in_use;	/* gui_mch_browse() works when GUI is running */
5423 # endif
5424 #endif
5425 #ifdef FEAT_SYN_HL
5426 	else if (STRICMP(name, "syntax_items") == 0)
5427 	    n = syntax_present(curbuf);
5428 #endif
5429 #if defined(WIN3264)
5430 	else if (STRICMP(name, "win95") == 0)
5431 	    n = mch_windows95();
5432 #endif
5433     }
5434 
5435     retvar->var_val.var_number = n;
5436 }
5437 
5438 /*
5439  * "hasmapto()" function
5440  */
5441     static void
5442 f_hasmapto(argvars, retvar)
5443     VAR		argvars;
5444     VAR		retvar;
5445 {
5446     char_u	*name;
5447     char_u	*mode;
5448     char_u	buf[NUMBUFLEN];
5449 
5450     name = get_var_string(&argvars[0]);
5451     if (argvars[1].var_type == VAR_UNKNOWN)
5452 	mode = (char_u *)"nvo";
5453     else
5454 	mode = get_var_string_buf(&argvars[1], buf);
5455 
5456     if (map_to_exists(name, mode))
5457 	retvar->var_val.var_number = TRUE;
5458     else
5459 	retvar->var_val.var_number = FALSE;
5460 }
5461 
5462 /*
5463  * "histadd()" function
5464  */
5465 /*ARGSUSED*/
5466     static void
5467 f_histadd(argvars, retvar)
5468     VAR		argvars;
5469     VAR		retvar;
5470 {
5471 #ifdef FEAT_CMDHIST
5472     int		histype;
5473     char_u	*str;
5474     char_u	buf[NUMBUFLEN];
5475 #endif
5476 
5477     retvar->var_val.var_number = FALSE;
5478     if (check_restricted() || check_secure())
5479 	return;
5480 #ifdef FEAT_CMDHIST
5481     histype = get_histtype(get_var_string(&argvars[0]));
5482     if (histype >= 0)
5483     {
5484 	str = get_var_string_buf(&argvars[1], buf);
5485 	if (*str != NUL)
5486 	{
5487 	    add_to_history(histype, str, FALSE, NUL);
5488 	    retvar->var_val.var_number = TRUE;
5489 	    return;
5490 	}
5491     }
5492 #endif
5493 }
5494 
5495 /*
5496  * "histdel()" function
5497  */
5498 /*ARGSUSED*/
5499     static void
5500 f_histdel(argvars, retvar)
5501     VAR		argvars;
5502     VAR		retvar;
5503 {
5504 #ifdef FEAT_CMDHIST
5505     int		n;
5506     char_u	buf[NUMBUFLEN];
5507 
5508     if (argvars[1].var_type == VAR_UNKNOWN)
5509 	/* only one argument: clear entire history */
5510 	n = clr_history(get_histtype(get_var_string(&argvars[0])));
5511     else if (argvars[1].var_type == VAR_NUMBER)
5512 	/* index given: remove that entry */
5513 	n = del_history_idx(get_histtype(get_var_string(&argvars[0])),
5514 					    (int)get_var_number(&argvars[1]));
5515     else
5516 	/* string given: remove all matching entries */
5517 	n = del_history_entry(get_histtype(get_var_string(&argvars[0])),
5518 					get_var_string_buf(&argvars[1], buf));
5519     retvar->var_val.var_number = n;
5520 #else
5521     retvar->var_val.var_number = 0;
5522 #endif
5523 }
5524 
5525 /*
5526  * "histget()" function
5527  */
5528 /*ARGSUSED*/
5529     static void
5530 f_histget(argvars, retvar)
5531     VAR		argvars;
5532     VAR		retvar;
5533 {
5534 #ifdef FEAT_CMDHIST
5535     int		type;
5536     int		idx;
5537 
5538     type = get_histtype(get_var_string(&argvars[0]));
5539     if (argvars[1].var_type == VAR_UNKNOWN)
5540 	idx = get_history_idx(type);
5541     else
5542 	idx = (int)get_var_number(&argvars[1]);
5543     retvar->var_val.var_string = vim_strsave(get_history_entry(type, idx));
5544 #else
5545     retvar->var_val.var_string = NULL;
5546 #endif
5547     retvar->var_type = VAR_STRING;
5548 }
5549 
5550 /*
5551  * "histnr()" function
5552  */
5553 /*ARGSUSED*/
5554     static void
5555 f_histnr(argvars, retvar)
5556     VAR		argvars;
5557     VAR		retvar;
5558 {
5559     int		i;
5560 
5561 #ifdef FEAT_CMDHIST
5562     i = get_histtype(get_var_string(&argvars[0]));
5563     if (i >= HIST_CMD && i < HIST_COUNT)
5564 	i = get_history_idx(i);
5565     else
5566 #endif
5567 	i = -1;
5568     retvar->var_val.var_number = i;
5569 }
5570 
5571 /*
5572  * "highlight_exists()" function
5573  */
5574     static void
5575 f_hlexists(argvars, retvar)
5576     VAR		argvars;
5577     VAR		retvar;
5578 {
5579     retvar->var_val.var_number = highlight_exists(get_var_string(&argvars[0]));
5580 }
5581 
5582 /*
5583  * "highlightID(name)" function
5584  */
5585     static void
5586 f_hlID(argvars, retvar)
5587     VAR		argvars;
5588     VAR		retvar;
5589 {
5590     retvar->var_val.var_number = syn_name2id(get_var_string(&argvars[0]));
5591 }
5592 
5593 /*
5594  * "hostname()" function
5595  */
5596 /*ARGSUSED*/
5597     static void
5598 f_hostname(argvars, retvar)
5599     VAR		argvars;
5600     VAR		retvar;
5601 {
5602     char_u hostname[256];
5603 
5604     mch_get_host_name(hostname, 256);
5605     retvar->var_type = VAR_STRING;
5606     retvar->var_val.var_string = vim_strsave(hostname);
5607 }
5608 
5609 /*
5610  * iconv() function
5611  */
5612 /*ARGSUSED*/
5613     static void
5614 f_iconv(argvars, retvar)
5615     VAR		argvars;
5616     VAR		retvar;
5617 {
5618 #ifdef FEAT_MBYTE
5619     char_u	buf1[NUMBUFLEN];
5620     char_u	buf2[NUMBUFLEN];
5621     char_u	*from, *to, *str;
5622     vimconv_T	vimconv;
5623 #endif
5624 
5625     retvar->var_type = VAR_STRING;
5626     retvar->var_val.var_string = NULL;
5627 
5628 #ifdef FEAT_MBYTE
5629     str = get_var_string(&argvars[0]);
5630     from = enc_canonize(enc_skip(get_var_string_buf(&argvars[1], buf1)));
5631     to = enc_canonize(enc_skip(get_var_string_buf(&argvars[2], buf2)));
5632     vimconv.vc_type = CONV_NONE;
5633     convert_setup(&vimconv, from, to);
5634 
5635     /* If the encodings are equal, no conversion needed. */
5636     if (vimconv.vc_type == CONV_NONE)
5637 	retvar->var_val.var_string = vim_strsave(str);
5638     else
5639 	retvar->var_val.var_string = string_convert(&vimconv, str, NULL);
5640 
5641     convert_setup(&vimconv, NULL, NULL);
5642     vim_free(from);
5643     vim_free(to);
5644 #endif
5645 }
5646 
5647 /*
5648  * "indent()" function
5649  */
5650     static void
5651 f_indent(argvars, retvar)
5652     VAR		argvars;
5653     VAR		retvar;
5654 {
5655     linenr_T	lnum;
5656 
5657     lnum = get_var_lnum(argvars);
5658     if (lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count)
5659 	retvar->var_val.var_number = get_indent_lnum(lnum);
5660     else
5661 	retvar->var_val.var_number = -1;
5662 }
5663 
5664 static int inputsecret_flag = 0;
5665 
5666 /*
5667  * "input()" function
5668  *     Also handles inputsecret() when inputsecret is set.
5669  */
5670     static void
5671 f_input(argvars, retvar)
5672     VAR		argvars;
5673     VAR		retvar;
5674 {
5675     char_u	*prompt = get_var_string(&argvars[0]);
5676     char_u	*p = NULL;
5677     int		c;
5678     char_u	buf[NUMBUFLEN];
5679     int		cmd_silent_save = cmd_silent;
5680 
5681     retvar->var_type = VAR_STRING;
5682 
5683 #ifdef NO_CONSOLE_INPUT
5684     /* While starting up, there is no place to enter text. */
5685     if (no_console_input())
5686     {
5687 	retvar->var_val.var_string = NULL;
5688 	return;
5689     }
5690 #endif
5691 
5692     cmd_silent = FALSE;		/* Want to see the prompt. */
5693     if (prompt != NULL)
5694     {
5695 	/* Only the part of the message after the last NL is considered as
5696 	 * prompt for the command line */
5697 	p = vim_strrchr(prompt, '\n');
5698 	if (p == NULL)
5699 	    p = prompt;
5700 	else
5701 	{
5702 	    ++p;
5703 	    c = *p;
5704 	    *p = NUL;
5705 	    msg_start();
5706 	    msg_clr_eos();
5707 	    msg_puts_attr(prompt, echo_attr);
5708 	    msg_didout = FALSE;
5709 	    msg_starthere();
5710 	    *p = c;
5711 	}
5712 	cmdline_row = msg_row;
5713     }
5714 
5715     if (argvars[1].var_type != VAR_UNKNOWN)
5716 	stuffReadbuffSpec(get_var_string_buf(&argvars[1], buf));
5717 
5718     retvar->var_val.var_string =
5719 		getcmdline_prompt(inputsecret_flag ? NUL : '@', p, echo_attr);
5720 
5721     /* since the user typed this, no need to wait for return */
5722     need_wait_return = FALSE;
5723     msg_didout = FALSE;
5724     cmd_silent = cmd_silent_save;
5725 }
5726 
5727 /*
5728  * "inputdialog()" function
5729  */
5730     static void
5731 f_inputdialog(argvars, retvar)
5732     VAR		argvars;
5733     VAR		retvar;
5734 {
5735 #if defined(FEAT_GUI_TEXTDIALOG)
5736     /* Use a GUI dialog if the GUI is running and 'c' is not in 'guioptions' */
5737     if (gui.in_use && vim_strchr(p_go, GO_CONDIALOG) == NULL)
5738     {
5739 	char_u	*message;
5740 	char_u	buf[NUMBUFLEN];
5741 
5742 	message = get_var_string(&argvars[0]);
5743 	if (argvars[1].var_type != VAR_UNKNOWN)
5744 	{
5745 	    STRNCPY(IObuff, get_var_string_buf(&argvars[1], buf), IOSIZE);
5746 	    IObuff[IOSIZE - 1] = NUL;
5747 	}
5748 	else
5749 	    IObuff[0] = NUL;
5750 	if (do_dialog(VIM_QUESTION, NULL, message, (char_u *)_("&OK\n&Cancel"),
5751 							      1, IObuff) == 1)
5752 	    retvar->var_val.var_string = vim_strsave(IObuff);
5753 	else
5754 	{
5755 	    if (argvars[1].var_type != VAR_UNKNOWN
5756 					&& argvars[2].var_type != VAR_UNKNOWN)
5757 		retvar->var_val.var_string = vim_strsave(
5758 					get_var_string_buf(&argvars[2], buf));
5759 	    else
5760 		retvar->var_val.var_string = NULL;
5761 	}
5762 	retvar->var_type = VAR_STRING;
5763     }
5764     else
5765 #endif
5766 	f_input(argvars, retvar);
5767 }
5768 
5769 static garray_T	    ga_userinput = {0, 0, sizeof(tasave_T), 4, NULL};
5770 
5771 /*
5772  * "inputrestore()" function
5773  */
5774 /*ARGSUSED*/
5775     static void
5776 f_inputrestore(argvars, retvar)
5777     VAR		argvars;
5778     VAR		retvar;
5779 {
5780     if (ga_userinput.ga_len > 0)
5781     {
5782 	--ga_userinput.ga_len;
5783 	++ga_userinput.ga_room;
5784 	restore_typeahead((tasave_T *)(ga_userinput.ga_data)
5785 						       + ga_userinput.ga_len);
5786 	retvar->var_val.var_number = 0; /* OK */
5787     }
5788     else if (p_verbose > 1)
5789     {
5790 	msg((char_u *)_("called inputrestore() more often than inputsave()"));
5791 	retvar->var_val.var_number = 1; /* Failed */
5792     }
5793 }
5794 
5795 /*
5796  * "inputsave()" function
5797  */
5798 /*ARGSUSED*/
5799     static void
5800 f_inputsave(argvars, retvar)
5801     VAR		argvars;
5802     VAR		retvar;
5803 {
5804     /* Add an entry to the stack of typehead storage. */
5805     if (ga_grow(&ga_userinput, 1) == OK)
5806     {
5807 	save_typeahead((tasave_T *)(ga_userinput.ga_data)
5808 						       + ga_userinput.ga_len);
5809 	++ga_userinput.ga_len;
5810 	--ga_userinput.ga_room;
5811 	retvar->var_val.var_number = 0; /* OK */
5812     }
5813     else
5814 	retvar->var_val.var_number = 1; /* Failed */
5815 }
5816 
5817 /*
5818  * "inputsecret()" function
5819  */
5820     static void
5821 f_inputsecret(argvars, retvar)
5822     VAR		argvars;
5823     VAR		retvar;
5824 {
5825     ++cmdline_star;
5826     ++inputsecret_flag;
5827     f_input(argvars, retvar);
5828     --cmdline_star;
5829     --inputsecret_flag;
5830 }
5831 
5832 /*
5833  * "isdirectory()" function
5834  */
5835     static void
5836 f_isdirectory(argvars, retvar)
5837     VAR		argvars;
5838     VAR		retvar;
5839 {
5840     retvar->var_val.var_number = mch_isdir(get_var_string(&argvars[0]));
5841 }
5842 
5843 /*
5844  * "last_buffer_nr()" function.
5845  */
5846 /*ARGSUSED*/
5847     static void
5848 f_last_buffer_nr(argvars, retvar)
5849     VAR		argvars;
5850     VAR		retvar;
5851 {
5852     int		n = 0;
5853     buf_T	*buf;
5854 
5855     for (buf = firstbuf; buf != NULL; buf = buf->b_next)
5856 	if (n < buf->b_fnum)
5857 	    n = buf->b_fnum;
5858 
5859     retvar->var_val.var_number = n;
5860 }
5861 
5862 /*
5863  * "line(string)" function
5864  */
5865     static void
5866 f_line(argvars, retvar)
5867     VAR		argvars;
5868     VAR		retvar;
5869 {
5870     linenr_T	lnum = 0;
5871     pos_T	*fp;
5872 
5873     fp = var2fpos(&argvars[0], TRUE);
5874     if (fp != NULL)
5875 	lnum = fp->lnum;
5876     retvar->var_val.var_number = lnum;
5877 }
5878 
5879 /*
5880  * "line2byte(lnum)" function
5881  */
5882 /*ARGSUSED*/
5883     static void
5884 f_line2byte(argvars, retvar)
5885     VAR		argvars;
5886     VAR		retvar;
5887 {
5888 #ifndef FEAT_BYTEOFF
5889     retvar->var_val.var_number = -1;
5890 #else
5891     linenr_T	lnum;
5892 
5893     lnum = get_var_lnum(argvars);
5894     if (lnum < 1 || lnum > curbuf->b_ml.ml_line_count + 1)
5895 	retvar->var_val.var_number = -1;
5896     else
5897 	retvar->var_val.var_number = ml_find_line_or_offset(curbuf, lnum, NULL);
5898     if (retvar->var_val.var_number >= 0)
5899 	++retvar->var_val.var_number;
5900 #endif
5901 }
5902 
5903 /*
5904  * "lispindent(lnum)" function
5905  */
5906     static void
5907 f_lispindent(argvars, retvar)
5908     VAR		argvars;
5909     VAR		retvar;
5910 {
5911 #ifdef FEAT_LISP
5912     pos_T	pos;
5913     linenr_T	lnum;
5914 
5915     pos = curwin->w_cursor;
5916     lnum = get_var_lnum(argvars);
5917     if (lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count)
5918     {
5919 	curwin->w_cursor.lnum = lnum;
5920 	retvar->var_val.var_number = get_lisp_indent();
5921 	curwin->w_cursor = pos;
5922     }
5923     else
5924 #endif
5925 	retvar->var_val.var_number = -1;
5926 }
5927 
5928 /*
5929  * "localtime()" function
5930  */
5931 /*ARGSUSED*/
5932     static void
5933 f_localtime(argvars, retvar)
5934     VAR		argvars;
5935     VAR		retvar;
5936 {
5937     retvar->var_val.var_number = (varnumber_T)time(NULL);
5938 }
5939 
5940 /*
5941  * "maparg()" function
5942  */
5943     static void
5944 f_maparg(argvars, retvar)
5945     VAR		argvars;
5946     VAR		retvar;
5947 {
5948     get_maparg(argvars, retvar, TRUE);
5949 }
5950 
5951 /*
5952  * "mapcheck()" function
5953  */
5954     static void
5955 f_mapcheck(argvars, retvar)
5956     VAR		argvars;
5957     VAR		retvar;
5958 {
5959     get_maparg(argvars, retvar, FALSE);
5960 }
5961 
5962     static void
5963 get_maparg(argvars, retvar, exact)
5964     VAR		argvars;
5965     VAR		retvar;
5966     int		exact;
5967 {
5968     char_u	*keys;
5969     char_u	*which;
5970     char_u	buf[NUMBUFLEN];
5971     char_u	*keys_buf = NULL;
5972     char_u	*rhs;
5973     int		mode;
5974     garray_T	ga;
5975 
5976     /* return empty string for failure */
5977     retvar->var_type = VAR_STRING;
5978     retvar->var_val.var_string = NULL;
5979 
5980     keys = get_var_string(&argvars[0]);
5981     if (*keys == NUL)
5982 	return;
5983 
5984     if (argvars[1].var_type != VAR_UNKNOWN)
5985 	which = get_var_string_buf(&argvars[1], buf);
5986     else
5987 	which = (char_u *)"";
5988     mode = get_map_mode(&which, 0);
5989 
5990     keys = replace_termcodes(keys, &keys_buf, TRUE, TRUE);
5991     rhs = check_map(keys, mode, exact);
5992     vim_free(keys_buf);
5993     if (rhs != NULL)
5994     {
5995 	ga_init(&ga);
5996 	ga.ga_itemsize = 1;
5997 	ga.ga_growsize = 40;
5998 
5999 	while (*rhs != NUL)
6000 	    ga_concat(&ga, str2special(&rhs, FALSE));
6001 
6002 	ga_append(&ga, NUL);
6003 	retvar->var_val.var_string = (char_u *)ga.ga_data;
6004     }
6005 }
6006 
6007 /*
6008  * "match()" function
6009  */
6010     static void
6011 f_match(argvars, retvar)
6012     VAR		argvars;
6013     VAR		retvar;
6014 {
6015     find_some_match(argvars, retvar, 1);
6016 }
6017 
6018 /*
6019  * "matchend()" function
6020  */
6021     static void
6022 f_matchend(argvars, retvar)
6023     VAR		argvars;
6024     VAR		retvar;
6025 {
6026     find_some_match(argvars, retvar, 0);
6027 }
6028 
6029 /*
6030  * "matchstr()" function
6031  */
6032     static void
6033 f_matchstr(argvars, retvar)
6034     VAR		argvars;
6035     VAR		retvar;
6036 {
6037     find_some_match(argvars, retvar, 2);
6038 }
6039 
6040     static void
6041 find_some_match(argvars, retvar, type)
6042     VAR		argvars;
6043     VAR		retvar;
6044     int		type;
6045 {
6046     char_u	*str;
6047     char_u	*expr;
6048     char_u	*pat;
6049     regmatch_T	regmatch;
6050     char_u	patbuf[NUMBUFLEN];
6051     char_u	*save_cpo;
6052     long	start = 0;
6053     long	nth = 1;
6054     int		match;
6055 
6056     /* Make 'cpoptions' empty, the 'l' flag should not be used here. */
6057     save_cpo = p_cpo;
6058     p_cpo = (char_u *)"";
6059 
6060     expr = str = get_var_string(&argvars[0]);
6061     pat = get_var_string_buf(&argvars[1], patbuf);
6062 
6063     if (type == 2)
6064     {
6065 	retvar->var_type = VAR_STRING;
6066 	retvar->var_val.var_string = NULL;
6067     }
6068     else
6069 	retvar->var_val.var_number = -1;
6070 
6071     if (argvars[2].var_type != VAR_UNKNOWN)
6072     {
6073 	start = get_var_number(&argvars[2]);
6074 	if (start < 0)
6075 	    start = 0;
6076 	if (start > (long)STRLEN(str))
6077 	    goto theend;
6078 	str += start;
6079 
6080 	if (argvars[3].var_type != VAR_UNKNOWN)
6081 	    nth = get_var_number(&argvars[3]);
6082     }
6083 
6084     regmatch.regprog = vim_regcomp(pat, RE_MAGIC + RE_STRING);
6085     if (regmatch.regprog != NULL)
6086     {
6087 	regmatch.rm_ic = p_ic;
6088 
6089 	while (1)
6090 	{
6091 	    match = vim_regexec_nl(&regmatch, str, (colnr_T)0);
6092 	    if (!match || --nth <= 0)
6093 		break;
6094 	    /* Advance to just after the match. */
6095 #ifdef FEAT_MBYTE
6096 	    str = regmatch.startp[0] + mb_ptr2len_check(regmatch.startp[0]);
6097 #else
6098 	    str = regmatch.startp[0] + 1;
6099 #endif
6100 	}
6101 
6102 	if (match)
6103 	{
6104 	    if (type == 2)
6105 		retvar->var_val.var_string = vim_strnsave(regmatch.startp[0],
6106 				(int)(regmatch.endp[0] - regmatch.startp[0]));
6107 	    else
6108 	    {
6109 		if (type != 0)
6110 		    retvar->var_val.var_number =
6111 				      (varnumber_T)(regmatch.startp[0] - str);
6112 		else
6113 		    retvar->var_val.var_number =
6114 					(varnumber_T)(regmatch.endp[0] - str);
6115 		retvar->var_val.var_number += str - expr;
6116 	    }
6117 	}
6118 	vim_free(regmatch.regprog);
6119     }
6120 
6121 theend:
6122     p_cpo = save_cpo;
6123 }
6124 
6125 /*
6126  * "mode()" function
6127  */
6128 /*ARGSUSED*/
6129     static void
6130 f_mode(argvars, retvar)
6131     VAR		argvars;
6132     VAR		retvar;
6133 {
6134     char_u	buf[2];
6135 
6136 #ifdef FEAT_VISUAL
6137     if (VIsual_active)
6138     {
6139 	if (VIsual_select)
6140 	    buf[0] = VIsual_mode + 's' - 'v';
6141 	else
6142 	    buf[0] = VIsual_mode;
6143     }
6144     else
6145 #endif
6146 	if (State == HITRETURN || State == ASKMORE || State == SETWSIZE)
6147 	buf[0] = 'r';
6148     else if (State & INSERT)
6149     {
6150 	if (State & REPLACE_FLAG)
6151 	    buf[0] = 'R';
6152 	else
6153 	    buf[0] = 'i';
6154     }
6155     else if (State & CMDLINE)
6156 	buf[0] = 'c';
6157     else
6158 	buf[0] = 'n';
6159 
6160     buf[1] = NUL;
6161     retvar->var_val.var_string = vim_strsave(buf);
6162     retvar->var_type = VAR_STRING;
6163 }
6164 
6165 /*
6166  * "nr2char()" function
6167  */
6168     static void
6169 f_nr2char(argvars, retvar)
6170     VAR		argvars;
6171     VAR		retvar;
6172 {
6173     char_u	buf[NUMBUFLEN];
6174 
6175 #ifdef FEAT_MBYTE
6176     if (has_mbyte)
6177 	buf[(*mb_char2bytes)((int)get_var_number(&argvars[0]), buf)] = NUL;
6178     else
6179 #endif
6180     {
6181 	buf[0] = (char_u)get_var_number(&argvars[0]);
6182 	buf[1] = NUL;
6183     }
6184     retvar->var_type = VAR_STRING;
6185     retvar->var_val.var_string = vim_strsave(buf);
6186 }
6187 
6188 /*
6189  * "rename({from}, {to})" function
6190  */
6191     static void
6192 f_rename(argvars, retvar)
6193     VAR		argvars;
6194     VAR		retvar;
6195 {
6196     char_u	buf[NUMBUFLEN];
6197 
6198     if (check_restricted() || check_secure())
6199 	retvar->var_val.var_number = -1;
6200     else
6201 	retvar->var_val.var_number = vim_rename(get_var_string(&argvars[0]),
6202 					get_var_string_buf(&argvars[1], buf));
6203 }
6204 
6205 /*
6206  * "resolve()" function
6207  */
6208     static void
6209 f_resolve(argvars, retvar)
6210     VAR		argvars;
6211     VAR		retvar;
6212 {
6213     char_u	*p;
6214 
6215     p = get_var_string(&argvars[0]);
6216 #ifdef FEAT_SHORTCUT
6217     {
6218 	char_u	*v = NULL;
6219 
6220 	v = mch_resolve_shortcut(p);
6221 	if (v != NULL)
6222 	    retvar->var_val.var_string = v;
6223 	else
6224 	    retvar->var_val.var_string = vim_strsave(p);
6225     }
6226 #else
6227 # ifdef HAVE_READLINK
6228     {
6229 	char_u	buf[MAXPATHL + 1];
6230 	char_u	*cpy;
6231 	int	len;
6232 	char_u	*remain = NULL;
6233 	char_u	*q;
6234 	int	is_relative_to_current = FALSE;
6235 	int	has_trailing_pathsep = FALSE;
6236 	int	limit = 100;
6237 
6238 	p = vim_strsave(p);
6239 
6240 	if (p[0] == '.' && (vim_ispathsep(p[1])
6241 				   || (p[1] == '.' && (vim_ispathsep(p[2])))))
6242 	    is_relative_to_current = TRUE;
6243 
6244 	len = STRLEN(p);
6245 	if (len > 0 && vim_ispathsep(p[len-1]))
6246 	    has_trailing_pathsep = TRUE;
6247 
6248 	q = getnextcomp(p);
6249 	if (*q != NUL)
6250 	{
6251 	    /* Separate the first path component in "p", and keep the
6252 	     * remainder (beginning with the path separator). */
6253 	    remain = vim_strsave(q - 1);
6254 	    q[-1] = NUL;
6255 	}
6256 
6257 	for (;;)
6258 	{
6259 	    for (;;)
6260 	    {
6261 		len = readlink((char *)p, (char *)buf, MAXPATHL);
6262 		if (len <= 0)
6263 		    break;
6264 		buf[len] = NUL;
6265 
6266 		if (limit-- == 0)
6267 		{
6268 		    vim_free(p);
6269 		    vim_free(remain);
6270 		    EMSG(_("E655: Too many symbolic links (cycle?)"));
6271 		    retvar->var_val.var_string = NULL;
6272 		    goto fail;
6273 		}
6274 
6275 		/* Ensure that the result will have a trailing path separator
6276 		 * if the argument has one. */
6277 		if (remain == NULL && has_trailing_pathsep)
6278 		    add_pathsep(buf);
6279 
6280 		/* Separate the first path component in the link value and
6281 		 * concatenate the remainders. */
6282 		q = getnextcomp(vim_ispathsep(*buf) ? buf + 1 : buf);
6283 		if (*q != NUL)
6284 		{
6285 		    if (remain == NULL)
6286 			remain = vim_strsave(q - 1);
6287 		    else
6288 		    {
6289 			cpy = vim_strnsave(q-1, STRLEN(q-1)+STRLEN(remain));
6290 			if (cpy != NULL)
6291 			{
6292 			    STRCAT(cpy, remain);
6293 			    vim_free(remain);
6294 			    remain = cpy;
6295 			}
6296 		    }
6297 		    q[-1] = NUL;
6298 		}
6299 
6300 		q = gettail(p);
6301 		if (q > p && *q == NUL)
6302 		{
6303 		    /* Ignore trailing path separator. */
6304 		    q[-1] = NUL;
6305 		    q = gettail(p);
6306 		}
6307 		if (q > p && !mch_isFullName(buf))
6308 		{
6309 		    /* symlink is relative to directory of argument */
6310 		    cpy = alloc((unsigned)(STRLEN(p) + STRLEN(buf) + 1));
6311 		    if (cpy != NULL)
6312 		    {
6313 			STRCPY(cpy, p);
6314 			STRCPY(gettail(cpy), buf);
6315 			vim_free(p);
6316 			p = cpy;
6317 		    }
6318 		}
6319 		else
6320 		{
6321 		    vim_free(p);
6322 		    p = vim_strsave(buf);
6323 		}
6324 	    }
6325 
6326 	    if (remain == NULL)
6327 		break;
6328 
6329 	    /* Append the first path component of "remain" to "p". */
6330 	    q = getnextcomp(remain + 1);
6331 	    len = q - remain - (*q != NUL);
6332 	    cpy = vim_strnsave(p, STRLEN(p) + len);
6333 	    if (cpy != NULL)
6334 	    {
6335 		STRNCAT(cpy, remain, len);
6336 		vim_free(p);
6337 		p = cpy;
6338 	    }
6339 	    /* Shorten "remain". */
6340 	    if (*q != NUL)
6341 		STRCPY(remain, q - 1);
6342 	    else
6343 	    {
6344 		vim_free(remain);
6345 		remain = NULL;
6346 	    }
6347 	}
6348 
6349 	/* If the result is a relative path name, make it explicitly relative to
6350 	 * the current directory if and only if the argument had this form. */
6351 	if (!vim_ispathsep(*p))
6352 	{
6353 	    if (is_relative_to_current
6354 		    && *p != NUL
6355 		    && !(p[0] == '.'
6356 			&& (p[1] == NUL
6357 			    || vim_ispathsep(p[1])
6358 			    || (p[1] == '.'
6359 				&& (p[2] == NUL
6360 				    || vim_ispathsep(p[2]))))))
6361 	    {
6362 		/* Prepend "./". */
6363 		cpy = vim_strnsave((char_u *)"./", 2 + STRLEN(p));
6364 		if (cpy != NULL)
6365 		{
6366 		    STRCAT(cpy, p);
6367 		    vim_free(p);
6368 		    p = cpy;
6369 		}
6370 	    }
6371 	    else if (!is_relative_to_current)
6372 	    {
6373 		/* Strip leading "./". */
6374 		q = p;
6375 		while (q[0] == '.' && vim_ispathsep(q[1]))
6376 		    q += 2;
6377 		if (q > p)
6378 		    mch_memmove(p, p + 2, STRLEN(p + 2) + (size_t)1);
6379 	    }
6380 	}
6381 
6382 	/* Ensure that the result will have no trailing path separator
6383 	 * if the argument had none.  But keep "/" or "//". */
6384 	if (!has_trailing_pathsep)
6385 	{
6386 	    q = p + STRLEN(p);
6387 	    while ((q > p + 2 || (q == p + 2 && !vim_ispathsep(*p)))
6388 		   && vim_ispathsep(q[-1]))
6389 		--q;
6390 	    *q = NUL;
6391 	}
6392 
6393 	retvar->var_val.var_string = p;
6394     }
6395 # else
6396     retvar->var_val.var_string = vim_strsave(p);
6397 # endif
6398 #endif
6399 
6400     simplify_filename(retvar->var_val.var_string);
6401 
6402 #ifdef HAVE_READLINK
6403 fail:
6404 #endif
6405     retvar->var_type = VAR_STRING;
6406 }
6407 
6408 /*
6409  * "simplify()" function
6410  */
6411     static void
6412 f_simplify(argvars, retvar)
6413     VAR		argvars;
6414     VAR		retvar;
6415 {
6416     char_u	*p;
6417 
6418     p = get_var_string(&argvars[0]);
6419     retvar->var_val.var_string = vim_strsave(p);
6420     simplify_filename(retvar->var_val.var_string);	/* simplify in place */
6421     retvar->var_type = VAR_STRING;
6422 }
6423 
6424 #define SP_NOMOVE	1	/* don't move cursor */
6425 #define SP_REPEAT	2	/* repeat to find outer pair */
6426 #define SP_RETCOUNT	4	/* return matchcount */
6427 
6428 /*
6429  * "search()" function
6430  */
6431     static void
6432 f_search(argvars, retvar)
6433     VAR		argvars;
6434     VAR		retvar;
6435 {
6436     char_u	*pat;
6437     pos_T	pos;
6438     pos_T	save_cursor;
6439     int		save_p_ws = p_ws;
6440     int		dir;
6441     int		flags = 0;
6442 
6443     retvar->var_val.var_number = 0;	/* default: FAIL */
6444 
6445     pat = get_var_string(&argvars[0]);
6446     dir = get_search_arg(&argvars[1], &flags);	/* may set p_ws */
6447     if (dir == 0)
6448 	goto theend;
6449     if ((flags & ~SP_NOMOVE) != 0)
6450     {
6451 	EMSG2(_(e_invarg2), get_var_string(&argvars[1]));
6452 	goto theend;
6453     }
6454 
6455     pos = save_cursor = curwin->w_cursor;
6456     if (searchit(curwin, curbuf, &pos, dir, pat, 1L,
6457 					      SEARCH_KEEP, RE_SEARCH) != FAIL)
6458     {
6459 	retvar->var_val.var_number = pos.lnum;
6460 	curwin->w_cursor = pos;
6461 	/* "/$" will put the cursor after the end of the line, may need to
6462 	 * correct that here */
6463 	check_cursor();
6464     }
6465 
6466     /* If 'n' flag is used: restore cursor position. */
6467     if (flags & SP_NOMOVE)
6468 	curwin->w_cursor = save_cursor;
6469 theend:
6470     p_ws = save_p_ws;
6471 }
6472 
6473 /*
6474  * "searchpair()" function
6475  */
6476     static void
6477 f_searchpair(argvars, retvar)
6478     VAR		argvars;
6479     VAR		retvar;
6480 {
6481     char_u	*spat, *mpat, *epat;
6482     char_u	*skip;
6483     char_u	*pat, *pat2, *pat3;
6484     pos_T	pos;
6485     pos_T	firstpos;
6486     pos_T	save_cursor;
6487     pos_T	save_pos;
6488     int		save_p_ws = p_ws;
6489     char_u	*save_cpo;
6490     int		dir;
6491     int		flags = 0;
6492     char_u	nbuf1[NUMBUFLEN];
6493     char_u	nbuf2[NUMBUFLEN];
6494     char_u	nbuf3[NUMBUFLEN];
6495     int		n;
6496     int		r;
6497     int		nest = 1;
6498     int		err;
6499 
6500     retvar->var_val.var_number = 0;	/* default: FAIL */
6501 
6502     /* Make 'cpoptions' empty, the 'l' flag should not be used here. */
6503     save_cpo = p_cpo;
6504     p_cpo = (char_u *)"";
6505 
6506     /* Get the three pattern arguments: start, middle, end. */
6507     spat = get_var_string(&argvars[0]);
6508     mpat = get_var_string_buf(&argvars[1], nbuf1);
6509     epat = get_var_string_buf(&argvars[2], nbuf2);
6510 
6511     /* Make two search patterns: start/end (pat2, for in nested pairs) and
6512      * start/middle/end (pat3, for the top pair). */
6513     pat2 = alloc((unsigned)(STRLEN(spat) + STRLEN(epat) + 15));
6514     pat3 = alloc((unsigned)(STRLEN(spat) + STRLEN(mpat) + STRLEN(epat) + 23));
6515     if (pat2 == NULL || pat3 == NULL)
6516 	goto theend;
6517     sprintf((char *)pat2, "\\(%s\\m\\)\\|\\(%s\\m\\)", spat, epat);
6518     if (*mpat == NUL)
6519 	STRCPY(pat3, pat2);
6520     else
6521 	sprintf((char *)pat3, "\\(%s\\m\\)\\|\\(%s\\m\\)\\|\\(%s\\m\\)",
6522 							    spat, epat, mpat);
6523 
6524     /* Handle the optional fourth argument: flags */
6525     dir = get_search_arg(&argvars[3], &flags); /* may set p_ws */
6526     if (dir == 0)
6527 	goto theend;
6528 
6529     /* Optional fifth argument: skip expresion */
6530     if (argvars[3].var_type == VAR_UNKNOWN
6531 	    || argvars[4].var_type == VAR_UNKNOWN)
6532 	skip = (char_u *)"";
6533     else
6534 	skip = get_var_string_buf(&argvars[4], nbuf3);
6535 
6536     save_cursor = curwin->w_cursor;
6537     pos = curwin->w_cursor;
6538     firstpos.lnum = 0;
6539     pat = pat3;
6540     for (;;)
6541     {
6542 	n = searchit(curwin, curbuf, &pos, dir, pat, 1L,
6543 						      SEARCH_KEEP, RE_SEARCH);
6544 	if (n == FAIL || (firstpos.lnum != 0 && equalpos(pos, firstpos)))
6545 	    /* didn't find it or found the first match again: FAIL */
6546 	    break;
6547 
6548 	if (firstpos.lnum == 0)
6549 	    firstpos = pos;
6550 
6551 	/* If the skip pattern matches, ignore this match. */
6552 	if (*skip != NUL)
6553 	{
6554 	    save_pos = curwin->w_cursor;
6555 	    curwin->w_cursor = pos;
6556 	    r = eval_to_bool(skip, &err, NULL, FALSE);
6557 	    curwin->w_cursor = save_pos;
6558 	    if (err)
6559 	    {
6560 		/* Evaluating {skip} caused an error, break here. */
6561 		curwin->w_cursor = save_cursor;
6562 		retvar->var_val.var_number = -1;
6563 		break;
6564 	    }
6565 	    if (r)
6566 		continue;
6567 	}
6568 
6569 	if ((dir == BACKWARD && n == 3) || (dir == FORWARD && n == 2))
6570 	{
6571 	    /* Found end when searching backwards or start when searching
6572 	     * forward: nested pair. */
6573 	    ++nest;
6574 	    pat = pat2;		/* nested, don't search for middle */
6575 	}
6576 	else
6577 	{
6578 	    /* Found end when searching forward or start when searching
6579 	     * backward: end of (nested) pair; or found middle in outer pair. */
6580 	    if (--nest == 1)
6581 		pat = pat3;	/* outer level, search for middle */
6582 	}
6583 
6584 	if (nest == 0)
6585 	{
6586 	    /* Found the match: return matchcount or line number. */
6587 	    if (flags & SP_RETCOUNT)
6588 		++retvar->var_val.var_number;
6589 	    else
6590 		retvar->var_val.var_number = pos.lnum;
6591 	    curwin->w_cursor = pos;
6592 	    if (!(flags & SP_REPEAT))
6593 		break;
6594 	    nest = 1;	    /* search for next unmatched */
6595 	}
6596     }
6597 
6598     /* If 'n' flag is used or search failed: restore cursor position. */
6599     if ((flags & SP_NOMOVE) || retvar->var_val.var_number == 0)
6600 	curwin->w_cursor = save_cursor;
6601 
6602 theend:
6603     vim_free(pat2);
6604     vim_free(pat3);
6605     p_ws = save_p_ws;
6606     p_cpo = save_cpo;
6607 }
6608 
6609 /*
6610  * Get flags for a search function.
6611  * Possibly sets "p_ws".
6612  * Returns BACKWARD, FORWARD or zero (for an error).
6613  */
6614     static int
6615 get_search_arg(varp, flagsp)
6616     VAR		varp;
6617     int		*flagsp;
6618 {
6619     int		dir = FORWARD;
6620     char_u	*flags;
6621     char_u	nbuf[NUMBUFLEN];
6622     int		mask;
6623 
6624     if (varp->var_type != VAR_UNKNOWN)
6625     {
6626 	flags = get_var_string_buf(varp, nbuf);
6627 	while (*flags != NUL)
6628 	{
6629 	    switch (*flags)
6630 	    {
6631 		case 'b': dir = BACKWARD; break;
6632 		case 'w': p_ws = TRUE; break;
6633 		case 'W': p_ws = FALSE; break;
6634 		default:  mask = 0;
6635 			  if (flagsp != NULL)
6636 			     switch (*flags)
6637 			     {
6638 				 case 'n': mask = SP_NOMOVE; break;
6639 				 case 'r': mask = SP_REPEAT; break;
6640 				 case 'm': mask = SP_RETCOUNT; break;
6641 			     }
6642 			  if (mask == 0)
6643 			  {
6644 			      EMSG2(_(e_invarg2), flags);
6645 			      dir = 0;
6646 			  }
6647 			  else
6648 			      *flagsp |= mask;
6649 	    }
6650 	    if (dir == 0)
6651 		break;
6652 	    ++flags;
6653 	}
6654     }
6655     return dir;
6656 }
6657 
6658 /*
6659  * "setbufvar()" function
6660  */
6661 /*ARGSUSED*/
6662     static void
6663 f_setbufvar(argvars, retvar)
6664     VAR		argvars;
6665     VAR		retvar;
6666 {
6667     buf_T	*buf;
6668 #ifdef FEAT_AUTOCMD
6669     aco_save_T	aco;
6670 #else
6671     buf_T	*save_curbuf;
6672 #endif
6673     char_u	*varname, *bufvarname;
6674     VAR		varp;
6675     char_u	nbuf[NUMBUFLEN];
6676 
6677     if (check_restricted() || check_secure())
6678 	return;
6679     ++emsg_off;
6680     buf = get_buf_var(&argvars[0]);
6681     varname = get_var_string(&argvars[1]);
6682     varp = &argvars[2];
6683 
6684     if (buf != NULL && varname != NULL && varp != NULL)
6685     {
6686 	/* set curbuf to be our buf, temporarily */
6687 #ifdef FEAT_AUTOCMD
6688 	aucmd_prepbuf(&aco, buf);
6689 #else
6690 	save_curbuf = curbuf;
6691 	curbuf = buf;
6692 #endif
6693 
6694 	if (*varname == '&')
6695 	{
6696 	    ++varname;
6697 	    set_option_value(varname, get_var_number(varp),
6698 				   get_var_string_buf(varp, nbuf), OPT_LOCAL);
6699 	}
6700 	else
6701 	{
6702 	    bufvarname = alloc((unsigned)STRLEN(varname) + 3);
6703 	    if (bufvarname != NULL)
6704 	    {
6705 		STRCPY(bufvarname, "b:");
6706 		STRCPY(bufvarname + 2, varname);
6707 		set_var(bufvarname, varp);
6708 		vim_free(bufvarname);
6709 	    }
6710 	}
6711 
6712 	/* reset notion of buffer */
6713 #ifdef FEAT_AUTOCMD
6714 	aucmd_restbuf(&aco);
6715 #else
6716 	curbuf = save_curbuf;
6717 #endif
6718     }
6719     --emsg_off;
6720 }
6721 
6722 /*
6723  * "setcmdpos()" function
6724  */
6725     static void
6726 f_setcmdpos(argvars, retvar)
6727     VAR		argvars;
6728     VAR		retvar;
6729 {
6730     retvar->var_val.var_number = set_cmdline_pos(
6731 					(int)get_var_number(&argvars[0]) - 1);
6732 }
6733 
6734 /*
6735  * "setline()" function
6736  */
6737     static void
6738 f_setline(argvars, retvar)
6739     VAR		argvars;
6740     VAR		retvar;
6741 {
6742     linenr_T	lnum;
6743     char_u	*line;
6744 
6745     lnum = get_var_lnum(argvars);
6746     line = get_var_string(&argvars[1]);
6747     retvar->var_val.var_number = 1;		/* FAIL is default */
6748 
6749     if (lnum >= 1
6750 	    && lnum <= curbuf->b_ml.ml_line_count
6751 	    && u_savesub(lnum) == OK
6752 	    && ml_replace(lnum, line, TRUE) == OK)
6753     {
6754 	changed_bytes(lnum, 0);
6755 	check_cursor_col();
6756 	retvar->var_val.var_number = 0;
6757     }
6758 }
6759 
6760 /*
6761  * "setreg()" function
6762  */
6763     static void
6764 f_setreg(argvars, retvar)
6765     VAR		argvars;
6766     VAR		retvar;
6767 {
6768     int		regname;
6769     char_u	*strregname;
6770     char_u	*stropt;
6771     int		append;
6772     char_u	yank_type;
6773     long	block_len;
6774 
6775     block_len = -1;
6776     yank_type = MAUTO;
6777     append = FALSE;
6778 
6779     strregname = get_var_string(argvars);
6780     retvar->var_val.var_number = 1;		/* FAIL is default */
6781 
6782     regname = (strregname == NULL ? '"' : *strregname);
6783     if (regname == 0 || regname == '@')
6784 	regname = '"';
6785     else if (regname == '=')
6786 	return;
6787 
6788     if (argvars[2].var_type != VAR_UNKNOWN)
6789     {
6790 	for (stropt = get_var_string(&argvars[2]); *stropt != NUL; ++stropt)
6791 	    switch (*stropt)
6792 	    {
6793 		case 'a': case 'A':	/* append */
6794 		    append = TRUE;
6795 		    break;
6796 		case 'v': case 'c':	/* character-wise selection */
6797 		    yank_type = MCHAR;
6798 		    break;
6799 		case 'V': case 'l':	/* line-wise selection */
6800 		    yank_type = MLINE;
6801 		    break;
6802 #ifdef FEAT_VISUAL
6803 		case 'b': case Ctrl_V:	/* block-wise selection */
6804 		    yank_type = MBLOCK;
6805 		    if (VIM_ISDIGIT(stropt[1]))
6806 		    {
6807 			++stropt;
6808 			block_len = getdigits(&stropt) - 1;
6809 			--stropt;
6810 		    }
6811 		    break;
6812 #endif
6813 	    }
6814     }
6815 
6816     write_reg_contents_ex(regname, get_var_string(&argvars[1]), -1,
6817 						append, yank_type, block_len);
6818     retvar->var_val.var_number = 0;
6819 }
6820 
6821 
6822 /*
6823  * "setwinvar(expr)" function
6824  */
6825 /*ARGSUSED*/
6826     static void
6827 f_setwinvar(argvars, retvar)
6828     VAR		argvars;
6829     VAR		retvar;
6830 {
6831     win_T	*win;
6832 #ifdef FEAT_WINDOWS
6833     win_T	*save_curwin;
6834 #endif
6835     char_u	*varname, *winvarname;
6836     VAR		varp;
6837     char_u	nbuf[NUMBUFLEN];
6838 
6839     if (check_restricted() || check_secure())
6840 	return;
6841     ++emsg_off;
6842     win = find_win_by_nr(&argvars[0]);
6843     varname = get_var_string(&argvars[1]);
6844     varp = &argvars[2];
6845 
6846     if (win != NULL && varname != NULL && varp != NULL)
6847     {
6848 #ifdef FEAT_WINDOWS
6849 	/* set curwin to be our win, temporarily */
6850 	save_curwin = curwin;
6851 	curwin = win;
6852 	curbuf = curwin->w_buffer;
6853 #endif
6854 
6855 	if (*varname == '&')
6856 	{
6857 	    ++varname;
6858 	    set_option_value(varname, get_var_number(varp),
6859 				   get_var_string_buf(varp, nbuf), OPT_LOCAL);
6860 	}
6861 	else
6862 	{
6863 	    winvarname = alloc((unsigned)STRLEN(varname) + 3);
6864 	    if (winvarname != NULL)
6865 	    {
6866 		STRCPY(winvarname, "w:");
6867 		STRCPY(winvarname + 2, varname);
6868 		set_var(winvarname, varp);
6869 		vim_free(winvarname);
6870 	    }
6871 	}
6872 
6873 #ifdef FEAT_WINDOWS
6874 	/* Restore current window, if it's still valid (autocomands can make
6875 	 * it invalid). */
6876 	if (win_valid(save_curwin))
6877 	{
6878 	    curwin = save_curwin;
6879 	    curbuf = curwin->w_buffer;
6880 	}
6881 #endif
6882     }
6883     --emsg_off;
6884 }
6885 
6886 /*
6887  * "nextnonblank()" function
6888  */
6889     static void
6890 f_nextnonblank(argvars, retvar)
6891     VAR		argvars;
6892     VAR		retvar;
6893 {
6894     linenr_T	lnum;
6895 
6896     for (lnum = get_var_lnum(argvars); ; ++lnum)
6897     {
6898 	if (lnum > curbuf->b_ml.ml_line_count)
6899 	{
6900 	    lnum = 0;
6901 	    break;
6902 	}
6903 	if (*skipwhite(ml_get(lnum)) != NUL)
6904 	    break;
6905     }
6906     retvar->var_val.var_number = lnum;
6907 }
6908 
6909 /*
6910  * "prevnonblank()" function
6911  */
6912     static void
6913 f_prevnonblank(argvars, retvar)
6914     VAR		argvars;
6915     VAR		retvar;
6916 {
6917     linenr_T	lnum;
6918 
6919     lnum = get_var_lnum(argvars);
6920     if (lnum < 1 || lnum > curbuf->b_ml.ml_line_count)
6921 	lnum = 0;
6922     else
6923 	while (lnum >= 1 && *skipwhite(ml_get(lnum)) == NUL)
6924 	    --lnum;
6925     retvar->var_val.var_number = lnum;
6926 }
6927 
6928 #if defined(FEAT_CLIENTSERVER) && defined(FEAT_X11)
6929 static void make_connection __ARGS((void));
6930 static int check_connection __ARGS((void));
6931 
6932     static void
6933 make_connection()
6934 {
6935     if (X_DISPLAY == NULL
6936 # ifdef FEAT_GUI
6937 	    && !gui.in_use
6938 # endif
6939 	    )
6940     {
6941 	x_force_connect = TRUE;
6942 	setup_term_clip();
6943 	x_force_connect = FALSE;
6944     }
6945 }
6946 
6947     static int
6948 check_connection()
6949 {
6950     make_connection();
6951     if (X_DISPLAY == NULL)
6952     {
6953 	EMSG(_("E240: No connection to Vim server"));
6954 	return FAIL;
6955     }
6956     return OK;
6957 }
6958 #endif
6959 
6960 /*ARGSUSED*/
6961     static void
6962 f_serverlist(argvars, retvar)
6963     VAR		argvars;
6964     VAR		retvar;
6965 {
6966     char_u	*r = NULL;
6967 
6968 #ifdef FEAT_CLIENTSERVER
6969 # ifdef WIN32
6970     r = serverGetVimNames();
6971 # else
6972     make_connection();
6973     if (X_DISPLAY != NULL)
6974 	r = serverGetVimNames(X_DISPLAY);
6975 # endif
6976 #endif
6977     retvar->var_type = VAR_STRING;
6978     retvar->var_val.var_string = r;
6979 }
6980 
6981 /*ARGSUSED*/
6982     static void
6983 f_remote_peek(argvars, retvar)
6984     VAR		argvars;
6985     VAR		retvar;
6986 {
6987 #ifdef FEAT_CLIENTSERVER
6988     var		v;
6989     char_u	*s = NULL;
6990 # ifdef WIN32
6991     int		n = 0;
6992 # endif
6993 
6994     if (check_restricted() || check_secure())
6995     {
6996 	retvar->var_val.var_number = -1;
6997 	return;
6998     }
6999 # ifdef WIN32
7000     sscanf(get_var_string(&argvars[0]), "%x", &n);
7001     if (n == 0)
7002 	retvar->var_val.var_number = -1;
7003     else
7004     {
7005 	s = serverGetReply((HWND)n, FALSE, FALSE, FALSE);
7006 	retvar->var_val.var_number = (s != NULL);
7007     }
7008 # else
7009     retvar->var_val.var_number = 0;
7010     if (check_connection() == FAIL)
7011 	return;
7012 
7013     retvar->var_val.var_number = serverPeekReply(X_DISPLAY,
7014 			     serverStrToWin(get_var_string(&argvars[0])), &s);
7015 # endif
7016 
7017     if (argvars[1].var_type != VAR_UNKNOWN && retvar->var_val.var_number > 0)
7018     {
7019 	v.var_type = VAR_STRING;
7020 	v.var_val.var_string = vim_strsave(s);
7021 	set_var(get_var_string(&argvars[1]), &v);
7022     }
7023 #else
7024     retvar->var_val.var_number = -1;
7025 #endif
7026 }
7027 
7028 /*ARGSUSED*/
7029     static void
7030 f_remote_read(argvars, retvar)
7031     VAR		argvars;
7032     VAR		retvar;
7033 {
7034     char_u	*r = NULL;
7035 
7036 #ifdef FEAT_CLIENTSERVER
7037     if (!check_restricted() && !check_secure())
7038     {
7039 # ifdef WIN32
7040 	/* The server's HWND is encoded in the 'id' parameter */
7041 	int		n = 0;
7042 
7043 	sscanf(get_var_string(&argvars[0]), "%x", &n);
7044 	if (n != 0)
7045 	    r = serverGetReply((HWND)n, FALSE, TRUE, TRUE);
7046 	if (r == NULL)
7047 # else
7048 	if (check_connection() == FAIL || serverReadReply(X_DISPLAY,
7049 		  serverStrToWin(get_var_string(&argvars[0])), &r, FALSE) < 0)
7050 # endif
7051 	    EMSG(_("E277: Unable to read a server reply"));
7052     }
7053 #endif
7054     retvar->var_type = VAR_STRING;
7055     retvar->var_val.var_string = r;
7056 }
7057 
7058 /*ARGSUSED*/
7059     static void
7060 f_server2client(argvars, retvar)
7061     VAR		argvars;
7062     VAR		retvar;
7063 {
7064 #ifdef FEAT_CLIENTSERVER
7065     char_u	buf[NUMBUFLEN];
7066     char_u	*server = get_var_string(&argvars[0]);
7067     char_u	*reply = get_var_string_buf(&argvars[1], buf);
7068 
7069     retvar->var_val.var_number = -1;
7070     if (check_restricted() || check_secure())
7071 	return;
7072 # ifdef FEAT_X11
7073     if (check_connection() == FAIL)
7074 	return;
7075 # endif
7076 
7077     if (serverSendReply(server, reply) < 0)
7078     {
7079 	EMSG(_("E258: Unable to send to client"));
7080 	return;
7081     }
7082     retvar->var_val.var_number = 0;
7083 #else
7084     retvar->var_val.var_number = -1;
7085 #endif
7086 }
7087 
7088 #ifdef FEAT_CLIENTSERVER
7089 static void remote_common __ARGS((VAR argvars, VAR retvar, int expr));
7090 
7091     static void
7092 remote_common(argvars, retvar, expr)
7093     VAR		argvars;
7094     VAR		retvar;
7095     int		expr;
7096 {
7097     char_u	*server_name;
7098     char_u	*keys;
7099     char_u	*r = NULL;
7100     char_u	buf[NUMBUFLEN];
7101 # ifdef WIN32
7102     HWND	w;
7103 # else
7104     Window	w;
7105 # endif
7106 
7107     if (check_restricted() || check_secure())
7108 	return;
7109 
7110 # ifdef FEAT_X11
7111     if (check_connection() == FAIL)
7112 	return;
7113 # endif
7114 
7115     server_name = get_var_string(&argvars[0]);
7116     keys = get_var_string_buf(&argvars[1], buf);
7117 # ifdef WIN32
7118     if (serverSendToVim(server_name, keys, &r, &w, expr, TRUE) < 0)
7119 # else
7120     if (serverSendToVim(X_DISPLAY, server_name, keys, &r, &w, expr, 0, TRUE)
7121 									  < 0)
7122 # endif
7123     {
7124 	if (r != NULL)
7125 	    EMSG(r);		/* sending worked but evaluation failed */
7126 	else
7127 	    EMSG2(_("E241: Unable to send to %s"), server_name);
7128 	return;
7129     }
7130 
7131     retvar->var_val.var_string = r;
7132 
7133     if (argvars[2].var_type != VAR_UNKNOWN)
7134     {
7135 	var	v;
7136 	char_u	str[30];
7137 
7138 	sprintf((char *)str, "0x%x", (unsigned int)w);
7139 	v.var_type = VAR_STRING;
7140 	v.var_val.var_string = vim_strsave(str);
7141 	set_var(get_var_string(&argvars[2]), &v);
7142     }
7143 }
7144 #endif
7145 
7146 /*
7147  * "remote_expr()" function
7148  */
7149 /*ARGSUSED*/
7150     static void
7151 f_remote_expr(argvars, retvar)
7152     VAR		argvars;
7153     VAR		retvar;
7154 {
7155     retvar->var_type = VAR_STRING;
7156     retvar->var_val.var_string = NULL;
7157 #ifdef FEAT_CLIENTSERVER
7158     remote_common(argvars, retvar, TRUE);
7159 #endif
7160 }
7161 
7162 /*
7163  * "remote_send()" function
7164  */
7165 /*ARGSUSED*/
7166     static void
7167 f_remote_send(argvars, retvar)
7168     VAR		argvars;
7169     VAR		retvar;
7170 {
7171     retvar->var_type = VAR_STRING;
7172     retvar->var_val.var_string = NULL;
7173 #ifdef FEAT_CLIENTSERVER
7174     remote_common(argvars, retvar, FALSE);
7175 #endif
7176 }
7177 
7178 /*
7179  * "remote_foreground()" function
7180  */
7181 /*ARGSUSED*/
7182     static void
7183 f_remote_foreground(argvars, retvar)
7184     VAR		argvars;
7185     VAR		retvar;
7186 {
7187     retvar->var_val.var_number = 0;
7188 #ifdef FEAT_CLIENTSERVER
7189 # ifdef WIN32
7190     /* On Win32 it's done in this application. */
7191     serverForeground(get_var_string(&argvars[0]));
7192 # else
7193     /* Send a foreground() expression to the server. */
7194     argvars[1].var_type = VAR_STRING;
7195     argvars[1].var_val.var_string = vim_strsave((char_u *)"foreground()");
7196     argvars[2].var_type = VAR_UNKNOWN;
7197     remote_common(argvars, retvar, TRUE);
7198     vim_free(argvars[1].var_val.var_string);
7199 # endif
7200 #endif
7201 }
7202 
7203 /*
7204  * "repeat()" function
7205  */
7206 /*ARGSUSED*/
7207     static void
7208 f_repeat(argvars, retvar)
7209     VAR		argvars;
7210     VAR		retvar;
7211 {
7212     char_u	*p;
7213     int		n;
7214     int		slen;
7215     int		len;
7216     char_u	*r;
7217     int		i;
7218 
7219     p = get_var_string(&argvars[0]);
7220     n = get_var_number(&argvars[1]);
7221 
7222     retvar->var_type = VAR_STRING;
7223     retvar->var_val.var_string = NULL;
7224 
7225     slen = (int)STRLEN(p);
7226     len = slen * n;
7227 
7228     if (len <= 0)
7229         return;
7230 
7231     r = alloc(len + 1);
7232     if (r != NULL)
7233     {
7234         for (i = 0; i < n; i++)
7235 	    mch_memmove(r + i * slen, p, (size_t)slen);
7236         r[len] = NUL;
7237     }
7238 
7239     retvar->var_val.var_string = r;
7240 }
7241 
7242 #ifdef HAVE_STRFTIME
7243 /*
7244  * "strftime({format}[, {time}])" function
7245  */
7246     static void
7247 f_strftime(argvars, retvar)
7248     VAR		argvars;
7249     VAR		retvar;
7250 {
7251     char_u	result_buf[256];
7252     struct tm	*curtime;
7253     time_t	seconds;
7254     char_u	*p;
7255 
7256     retvar->var_type = VAR_STRING;
7257 
7258     p = get_var_string(&argvars[0]);
7259     if (argvars[1].var_type == VAR_UNKNOWN)
7260 	seconds = time(NULL);
7261     else
7262 	seconds = (time_t)get_var_number(&argvars[1]);
7263     curtime = localtime(&seconds);
7264     /* MSVC returns NULL for an invalid value of seconds. */
7265     if (curtime == NULL)
7266 	retvar->var_val.var_string = vim_strsave((char_u *)_("(Invalid)"));
7267     else
7268     {
7269 # ifdef FEAT_MBYTE
7270 	vimconv_T   conv;
7271 	char_u	    *enc;
7272 
7273 	conv.vc_type = CONV_NONE;
7274 	enc = enc_locale();
7275 	convert_setup(&conv, p_enc, enc);
7276 	if (conv.vc_type != CONV_NONE)
7277 	    p = string_convert(&conv, p, NULL);
7278 # endif
7279 	if (p != NULL)
7280 	    (void)strftime((char *)result_buf, sizeof(result_buf),
7281 							  (char *)p, curtime);
7282 	else
7283 	    result_buf[0] = NUL;
7284 
7285 # ifdef FEAT_MBYTE
7286 	if (conv.vc_type != CONV_NONE)
7287 	    vim_free(p);
7288 	convert_setup(&conv, enc, p_enc);
7289 	if (conv.vc_type != CONV_NONE)
7290 	    retvar->var_val.var_string =
7291 				      string_convert(&conv, result_buf, NULL);
7292 	else
7293 # endif
7294 	    retvar->var_val.var_string = vim_strsave(result_buf);
7295 
7296 # ifdef FEAT_MBYTE
7297 	/* Release conversion descriptors */
7298 	convert_setup(&conv, NULL, NULL);
7299 	vim_free(enc);
7300 # endif
7301     }
7302 }
7303 #endif
7304 
7305 /*
7306  * "stridx()" function
7307  */
7308     static void
7309 f_stridx(argvars, retvar)
7310     VAR		argvars;
7311     VAR		retvar;
7312 {
7313     char_u	buf[NUMBUFLEN];
7314     char_u	*needle;
7315     char_u	*haystack;
7316     char_u	*pos;
7317 
7318     needle = get_var_string(&argvars[1]);
7319     haystack = get_var_string_buf(&argvars[0], buf);
7320     pos	= (char_u *)strstr((char *)haystack, (char *)needle);
7321 
7322     if (pos == NULL)
7323 	retvar->var_val.var_number = -1;
7324     else
7325 	retvar->var_val.var_number = (varnumber_T) (pos - haystack);
7326 }
7327 
7328 /*
7329  * "strridx()" function
7330  */
7331     static void
7332 f_strridx(argvars, retvar)
7333     VAR		argvars;
7334     VAR		retvar;
7335 {
7336     char_u	buf[NUMBUFLEN];
7337     char_u	*needle;
7338     char_u	*haystack;
7339     char_u	*rest;
7340     char_u	*lastmatch = NULL;
7341 
7342     needle = get_var_string(&argvars[1]);
7343     haystack = get_var_string_buf(&argvars[0], buf);
7344     if (*needle == NUL)
7345 	/* Empty string matches past the end. */
7346 	lastmatch = haystack + STRLEN(haystack);
7347     else
7348 	for (rest = haystack; *rest != '\0'; ++rest)
7349 	{
7350 	    rest = (char_u *)strstr((char *)rest, (char *)needle);
7351 	    if (rest == NULL)
7352 		break;
7353 	    lastmatch = rest;
7354 	}
7355 
7356     if (lastmatch == NULL)
7357 	retvar->var_val.var_number = -1;
7358     else
7359 	retvar->var_val.var_number = (varnumber_T)(lastmatch - haystack);
7360 }
7361 
7362 /*
7363  * "strlen()" function
7364  */
7365     static void
7366 f_strlen(argvars, retvar)
7367     VAR		argvars;
7368     VAR		retvar;
7369 {
7370     retvar->var_val.var_number = (varnumber_T) (STRLEN(get_var_string(&argvars[0])));
7371 }
7372 
7373 /*
7374  * "strpart()" function
7375  */
7376     static void
7377 f_strpart(argvars, retvar)
7378     VAR		argvars;
7379     VAR		retvar;
7380 {
7381     char_u	*p;
7382     int		n;
7383     int		len;
7384     int		slen;
7385 
7386     p = get_var_string(&argvars[0]);
7387     slen = (int)STRLEN(p);
7388 
7389     n = get_var_number(&argvars[1]);
7390     if (argvars[2].var_type != VAR_UNKNOWN)
7391 	len = get_var_number(&argvars[2]);
7392     else
7393 	len = slen - n;	    /* default len: all bytes that are available. */
7394 
7395     /*
7396      * Only return the overlap between the specified part and the actual
7397      * string.
7398      */
7399     if (n < 0)
7400     {
7401 	len += n;
7402 	n = 0;
7403     }
7404     else if (n > slen)
7405 	n = slen;
7406     if (len < 0)
7407 	len = 0;
7408     else if (n + len > slen)
7409 	len = slen - n;
7410 
7411     retvar->var_type = VAR_STRING;
7412     retvar->var_val.var_string = vim_strnsave(p + n, len);
7413 }
7414 
7415 /*
7416  * "strtrans()" function
7417  */
7418     static void
7419 f_strtrans(argvars, retvar)
7420     VAR		argvars;
7421     VAR		retvar;
7422 {
7423     retvar->var_type = VAR_STRING;
7424     retvar->var_val.var_string = transstr(get_var_string(&argvars[0]));
7425 }
7426 
7427 /*
7428  * "synID(line, col, trans)" function
7429  */
7430 /*ARGSUSED*/
7431     static void
7432 f_synID(argvars, retvar)
7433     VAR		argvars;
7434     VAR		retvar;
7435 {
7436     int		id = 0;
7437 #ifdef FEAT_SYN_HL
7438     long	line;
7439     long	col;
7440     int		trans;
7441 
7442     line = get_var_lnum(argvars);
7443     col = get_var_number(&argvars[1]) - 1;
7444     trans = get_var_number(&argvars[2]);
7445 
7446     if (line >= 1 && line <= curbuf->b_ml.ml_line_count
7447 	    && col >= 0 && col < (long)STRLEN(ml_get(line)))
7448 	id = syn_get_id(line, col, trans);
7449 #endif
7450 
7451     retvar->var_val.var_number = id;
7452 }
7453 
7454 /*
7455  * "synIDattr(id, what [, mode])" function
7456  */
7457 /*ARGSUSED*/
7458     static void
7459 f_synIDattr(argvars, retvar)
7460     VAR		argvars;
7461     VAR		retvar;
7462 {
7463     char_u	*p = NULL;
7464 #ifdef FEAT_SYN_HL
7465     int		id;
7466     char_u	*what;
7467     char_u	*mode;
7468     char_u	modebuf[NUMBUFLEN];
7469     int		modec;
7470 
7471     id = get_var_number(&argvars[0]);
7472     what = get_var_string(&argvars[1]);
7473     if (argvars[2].var_type != VAR_UNKNOWN)
7474     {
7475 	mode = get_var_string_buf(&argvars[2], modebuf);
7476 	modec = TOLOWER_ASC(mode[0]);
7477 	if (modec != 't' && modec != 'c'
7478 #ifdef FEAT_GUI
7479 		&& modec != 'g'
7480 #endif
7481 		)
7482 	    modec = 0;	/* replace invalid with current */
7483     }
7484     else
7485     {
7486 #ifdef FEAT_GUI
7487 	if (gui.in_use)
7488 	    modec = 'g';
7489 	else
7490 #endif
7491 	    if (t_colors > 1)
7492 	    modec = 'c';
7493 	else
7494 	    modec = 't';
7495     }
7496 
7497 
7498     switch (TOLOWER_ASC(what[0]))
7499     {
7500 	case 'b':
7501 		if (TOLOWER_ASC(what[1]) == 'g')	/* bg[#] */
7502 		    p = highlight_color(id, what, modec);
7503 		else					/* bold */
7504 		    p = highlight_has_attr(id, HL_BOLD, modec);
7505 		break;
7506 
7507 	case 'f':					/* fg[#] */
7508 		p = highlight_color(id, what, modec);
7509 		break;
7510 
7511 	case 'i':
7512 		if (TOLOWER_ASC(what[1]) == 'n')	/* inverse */
7513 		    p = highlight_has_attr(id, HL_INVERSE, modec);
7514 		else					/* italic */
7515 		    p = highlight_has_attr(id, HL_ITALIC, modec);
7516 		break;
7517 
7518 	case 'n':					/* name */
7519 		p = get_highlight_name(NULL, id - 1);
7520 		break;
7521 
7522 	case 'r':					/* reverse */
7523 		p = highlight_has_attr(id, HL_INVERSE, modec);
7524 		break;
7525 
7526 	case 's':					/* standout */
7527 		p = highlight_has_attr(id, HL_STANDOUT, modec);
7528 		break;
7529 
7530 	case 'u':					/* underline */
7531 		p = highlight_has_attr(id, HL_UNDERLINE, modec);
7532 		break;
7533     }
7534 
7535     if (p != NULL)
7536 	p = vim_strsave(p);
7537 #endif
7538     retvar->var_type = VAR_STRING;
7539     retvar->var_val.var_string = p;
7540 }
7541 
7542 /*
7543  * "synIDtrans(id)" function
7544  */
7545 /*ARGSUSED*/
7546     static void
7547 f_synIDtrans(argvars, retvar)
7548     VAR		argvars;
7549     VAR		retvar;
7550 {
7551     int		id;
7552 
7553 #ifdef FEAT_SYN_HL
7554     id = get_var_number(&argvars[0]);
7555 
7556     if (id > 0)
7557 	id = syn_get_final_id(id);
7558     else
7559 #endif
7560 	id = 0;
7561 
7562     retvar->var_val.var_number = id;
7563 }
7564 
7565 /*
7566  * "system()" function
7567  */
7568     static void
7569 f_system(argvars, retvar)
7570     VAR		argvars;
7571     VAR		retvar;
7572 {
7573     char_u	*res = NULL;
7574     char_u	*p;
7575     char_u	*infile = NULL;
7576     char_u	buf[NUMBUFLEN];
7577     int		err = FALSE;
7578     FILE	*fd;
7579 
7580     if (argvars[1].var_type != VAR_UNKNOWN)
7581     {
7582 	/*
7583 	 * Write the string to a temp file, to be used for input of the shell
7584 	 * command.
7585 	 */
7586 	if ((infile = vim_tempname('i')) == NULL)
7587 	{
7588 	    EMSG(_(e_notmp));
7589 	    return;
7590 	}
7591 
7592 	fd = mch_fopen((char *)infile, WRITEBIN);
7593 	if (fd == NULL)
7594 	{
7595 	    EMSG2(_(e_notopen), infile);
7596 	    goto done;
7597 	}
7598 	p = get_var_string_buf(&argvars[1], buf);
7599 	if (fwrite(p, STRLEN(p), 1, fd) != 1)
7600 	    err = TRUE;
7601 	if (fclose(fd) != 0)
7602 	    err = TRUE;
7603 	if (err)
7604 	{
7605 	    EMSG(_("E677: Error writing temp file"));
7606 	    goto done;
7607 	}
7608     }
7609 
7610     res = get_cmd_output(get_var_string(&argvars[0]), infile, SHELL_SILENT);
7611 
7612 #ifdef USE_CR
7613     /* translate <CR> into <NL> */
7614     if (res != NULL)
7615     {
7616 	char_u	*s;
7617 
7618 	for (s = res; *s; ++s)
7619 	{
7620 	    if (*s == CAR)
7621 		*s = NL;
7622 	}
7623     }
7624 #else
7625 # ifdef USE_CRNL
7626     /* translate <CR><NL> into <NL> */
7627     if (res != NULL)
7628     {
7629 	char_u	*s, *d;
7630 
7631 	d = res;
7632 	for (s = res; *s; ++s)
7633 	{
7634 	    if (s[0] == CAR && s[1] == NL)
7635 		++s;
7636 	    *d++ = *s;
7637 	}
7638 	*d = NUL;
7639     }
7640 # endif
7641 #endif
7642 
7643 done:
7644     if (infile != NULL)
7645     {
7646 	mch_remove(infile);
7647 	vim_free(infile);
7648     }
7649     retvar->var_type = VAR_STRING;
7650     retvar->var_val.var_string = res;
7651 }
7652 
7653 /*
7654  * "submatch()" function
7655  */
7656     static void
7657 f_submatch(argvars, retvar)
7658     VAR		argvars;
7659     VAR		retvar;
7660 {
7661     retvar->var_type = VAR_STRING;
7662     retvar->var_val.var_string = reg_submatch((int)get_var_number(&argvars[0]));
7663 }
7664 
7665 /*
7666  * "substitute()" function
7667  */
7668     static void
7669 f_substitute(argvars, retvar)
7670     VAR		argvars;
7671     VAR		retvar;
7672 {
7673     char_u	patbuf[NUMBUFLEN];
7674     char_u	subbuf[NUMBUFLEN];
7675     char_u	flagsbuf[NUMBUFLEN];
7676 
7677     retvar->var_type = VAR_STRING;
7678     retvar->var_val.var_string = do_string_sub(
7679 	    get_var_string(&argvars[0]),
7680 	    get_var_string_buf(&argvars[1], patbuf),
7681 	    get_var_string_buf(&argvars[2], subbuf),
7682 	    get_var_string_buf(&argvars[3], flagsbuf));
7683 }
7684 
7685 /*
7686  * "tempname()" function
7687  */
7688 /*ARGSUSED*/
7689     static void
7690 f_tempname(argvars, retvar)
7691     VAR		argvars;
7692     VAR		retvar;
7693 {
7694     static int	x = 'A';
7695 
7696     retvar->var_type = VAR_STRING;
7697     retvar->var_val.var_string = vim_tempname(x);
7698 
7699     /* Advance 'x' to use A-Z and 0-9, so that there are at least 34 different
7700      * names.  Skip 'I' and 'O', they are used for shell redirection. */
7701     do
7702     {
7703 	if (x == 'Z')
7704 	    x = '0';
7705 	else if (x == '9')
7706 	    x = 'A';
7707 	else
7708 	{
7709 #ifdef EBCDIC
7710 	    if (x == 'I')
7711 		x = 'J';
7712 	    else if (x == 'R')
7713 		x = 'S';
7714 	    else
7715 #endif
7716 		++x;
7717 	}
7718     } while (x == 'I' || x == 'O');
7719 }
7720 
7721 /*
7722  * "tolower(string)" function
7723  */
7724     static void
7725 f_tolower(argvars, retvar)
7726     VAR		argvars;
7727     VAR		retvar;
7728 {
7729     char_u	*p;
7730 
7731     p = vim_strsave(get_var_string(&argvars[0]));
7732     retvar->var_type = VAR_STRING;
7733     retvar->var_val.var_string = p;
7734 
7735     if (p != NULL)
7736 	while (*p != NUL)
7737 	{
7738 #ifdef FEAT_MBYTE
7739 	    int		l;
7740 
7741 	    if (enc_utf8)
7742 	    {
7743 		int c, lc;
7744 
7745 		c = utf_ptr2char(p);
7746 		lc = utf_tolower(c);
7747 		l = utf_ptr2len_check(p);
7748 		/* TODO: reallocate string when byte count changes. */
7749 		if (utf_char2len(lc) == l)
7750 		    utf_char2bytes(lc, p);
7751 		p += l;
7752 	    }
7753 	    else if (has_mbyte && (l = (*mb_ptr2len_check)(p)) > 1)
7754 		p += l;		/* skip multi-byte character */
7755 	    else
7756 #endif
7757 	    {
7758 		*p = TOLOWER_LOC(*p); /* note that tolower() can be a macro */
7759 		++p;
7760 	    }
7761 	}
7762 }
7763 
7764 /*
7765  * "toupper(string)" function
7766  */
7767     static void
7768 f_toupper(argvars, retvar)
7769     VAR		argvars;
7770     VAR		retvar;
7771 {
7772     char_u	*p;
7773 
7774     p = vim_strsave(get_var_string(&argvars[0]));
7775     retvar->var_type = VAR_STRING;
7776     retvar->var_val.var_string = p;
7777 
7778     if (p != NULL)
7779 	while (*p != NUL)
7780 	{
7781 #ifdef FEAT_MBYTE
7782 	    int		l;
7783 
7784 	    if (enc_utf8)
7785 	    {
7786 		int c, uc;
7787 
7788 		c = utf_ptr2char(p);
7789 		uc = utf_toupper(c);
7790 		l = utf_ptr2len_check(p);
7791 		/* TODO: reallocate string when byte count changes. */
7792 		if (utf_char2len(uc) == l)
7793 		    utf_char2bytes(uc, p);
7794 		p += l;
7795 	    }
7796 	    else if (has_mbyte && (l = (*mb_ptr2len_check)(p)) > 1)
7797 		p += l;		/* skip multi-byte character */
7798 	    else
7799 #endif
7800 	    {
7801 		*p = TOUPPER_LOC(*p); /* note that toupper() can be a macro */
7802 		p++;
7803 	    }
7804 	}
7805 }
7806 
7807 /*
7808  * "tr(string, fromstr, tostr)" function
7809  */
7810     static void
7811 f_tr(argvars, retvar)
7812     VAR		argvars;
7813     VAR		retvar;
7814 {
7815     char_u	*instr;
7816     char_u	*fromstr;
7817     char_u	*tostr;
7818     char_u	*p;
7819 #ifdef FEAT_MBYTE
7820     int	        inlen;
7821     int	        fromlen;
7822     int	        tolen;
7823     int		idx;
7824     char_u	*cpstr;
7825     int		cplen;
7826     int		first = TRUE;
7827 #endif
7828     char_u	buf[NUMBUFLEN];
7829     char_u	buf2[NUMBUFLEN];
7830     garray_T	ga;
7831 
7832     instr = get_var_string(&argvars[0]);
7833     fromstr = get_var_string_buf(&argvars[1], buf);
7834     tostr = get_var_string_buf(&argvars[2], buf2);
7835 
7836     /* Default return value: empty string. */
7837     retvar->var_type = VAR_STRING;
7838     retvar->var_val.var_string = NULL;
7839     ga_init2(&ga, (int)sizeof(char), 80);
7840 
7841 #ifdef FEAT_MBYTE
7842     if (!has_mbyte)
7843 #endif
7844 	/* not multi-byte: fromstr and tostr must be the same length */
7845 	if (STRLEN(fromstr) != STRLEN(tostr))
7846 	{
7847 #ifdef FEAT_MBYTE
7848 error:
7849 #endif
7850 	    EMSG2(_(e_invarg2), fromstr);
7851 	    ga_clear(&ga);
7852 	    return;
7853 	}
7854 
7855     /* fromstr and tostr have to contain the same number of chars */
7856     while (*instr != NUL)
7857     {
7858 #ifdef FEAT_MBYTE
7859 	if (has_mbyte)
7860 	{
7861 	    inlen = mb_ptr2len_check(instr);
7862 	    cpstr = instr;
7863 	    cplen = inlen;
7864 	    idx = 0;
7865 	    for (p = fromstr; *p != NUL; p += fromlen)
7866 	    {
7867 		fromlen = mb_ptr2len_check(p);
7868 		if (fromlen == inlen && STRNCMP(instr, p, inlen) == 0)
7869 		{
7870 		    for (p = tostr; *p != NUL; p += tolen)
7871 		    {
7872 			tolen = mb_ptr2len_check(p);
7873 			if (idx-- == 0)
7874 			{
7875 			    cplen = tolen;
7876 			    cpstr = p;
7877 			    break;
7878 			}
7879 		    }
7880 		    if (*p == NUL)	/* tostr is shorter than fromstr */
7881 			goto error;
7882 		    break;
7883 		}
7884 		++idx;
7885 	    }
7886 
7887 	    if (first && cpstr == instr)
7888 	    {
7889 		/* Check that fromstr and tostr have the same number of
7890 		 * (multi-byte) characters.  Done only once when a character
7891 		 * of instr doesn't appear in fromstr. */
7892 		first = FALSE;
7893 		for (p = tostr; *p != NUL; p += tolen)
7894 		{
7895 		    tolen = mb_ptr2len_check(p);
7896 		    --idx;
7897 		}
7898 		if (idx != 0)
7899 		    goto error;
7900 	    }
7901 
7902 	    ga_grow(&ga, cplen);
7903 	    mch_memmove((char *)ga.ga_data + ga.ga_len, cpstr, (size_t)cplen);
7904 	    ga.ga_len += cplen;
7905 	    ga.ga_room -= cplen;
7906 
7907 	    instr += inlen;
7908 	}
7909 	else
7910 #endif
7911 	{
7912 	    /* When not using multi-byte chars we can do it faster. */
7913 	    p = vim_strchr(fromstr, *instr);
7914 	    if (p != NULL)
7915 		ga_append(&ga, tostr[p - fromstr]);
7916 	    else
7917 		ga_append(&ga, *instr);
7918 	    ++instr;
7919 	}
7920     }
7921 
7922     retvar->var_val.var_string = ga.ga_data;
7923 }
7924 
7925 /*
7926  * "type(expr)" function
7927  */
7928     static void
7929 f_type(argvars, retvar)
7930     VAR		argvars;
7931     VAR		retvar;
7932 {
7933     if (argvars[0].var_type == VAR_NUMBER)
7934 	retvar->var_val.var_number = 0;
7935     else
7936 	retvar->var_val.var_number = 1;
7937 }
7938 
7939 /*
7940  * "virtcol(string)" function
7941  */
7942     static void
7943 f_virtcol(argvars, retvar)
7944     VAR		argvars;
7945     VAR		retvar;
7946 {
7947     colnr_T	vcol = 0;
7948     pos_T	*fp;
7949 
7950     fp = var2fpos(&argvars[0], FALSE);
7951     if (fp != NULL && fp->lnum <= curbuf->b_ml.ml_line_count)
7952     {
7953 	getvvcol(curwin, fp, NULL, NULL, &vcol);
7954 	++vcol;
7955     }
7956 
7957     retvar->var_val.var_number = vcol;
7958 }
7959 
7960 /*
7961  * "visualmode()" function
7962  */
7963 /*ARGSUSED*/
7964     static void
7965 f_visualmode(argvars, retvar)
7966     VAR		argvars;
7967     VAR		retvar;
7968 {
7969 #ifdef FEAT_VISUAL
7970     char_u	str[2];
7971 
7972     retvar->var_type = VAR_STRING;
7973     str[0] = curbuf->b_visual_mode_eval;
7974     str[1] = NUL;
7975     retvar->var_val.var_string = vim_strsave(str);
7976 
7977     /* A non-zero number or non-empty string argument: reset mode. */
7978     if ((argvars[0].var_type == VAR_NUMBER
7979 		&& argvars[0].var_val.var_number != 0)
7980 	    || (argvars[0].var_type == VAR_STRING
7981 		&& *get_var_string(&argvars[0]) != NUL))
7982 	curbuf->b_visual_mode_eval = NUL;
7983 #else
7984     retvar->var_val.var_number = 0; /* return anything, it won't work anyway */
7985 #endif
7986 }
7987 
7988 /*
7989  * "winbufnr(nr)" function
7990  */
7991     static void
7992 f_winbufnr(argvars, retvar)
7993     VAR		argvars;
7994     VAR		retvar;
7995 {
7996     win_T	*wp;
7997 
7998     wp = find_win_by_nr(&argvars[0]);
7999     if (wp == NULL)
8000 	retvar->var_val.var_number = -1;
8001     else
8002 	retvar->var_val.var_number = wp->w_buffer->b_fnum;
8003 }
8004 
8005 /*
8006  * "wincol()" function
8007  */
8008 /*ARGSUSED*/
8009     static void
8010 f_wincol(argvars, retvar)
8011     VAR		argvars;
8012     VAR		retvar;
8013 {
8014     validate_cursor();
8015     retvar->var_val.var_number = curwin->w_wcol + 1;
8016 }
8017 
8018 /*
8019  * "winheight(nr)" function
8020  */
8021     static void
8022 f_winheight(argvars, retvar)
8023     VAR		argvars;
8024     VAR		retvar;
8025 {
8026     win_T	*wp;
8027 
8028     wp = find_win_by_nr(&argvars[0]);
8029     if (wp == NULL)
8030 	retvar->var_val.var_number = -1;
8031     else
8032 	retvar->var_val.var_number = wp->w_height;
8033 }
8034 
8035 /*
8036  * "winline()" function
8037  */
8038 /*ARGSUSED*/
8039     static void
8040 f_winline(argvars, retvar)
8041     VAR		argvars;
8042     VAR		retvar;
8043 {
8044     validate_cursor();
8045     retvar->var_val.var_number = curwin->w_wrow + 1;
8046 }
8047 
8048 /*
8049  * "winnr()" function
8050  */
8051 /* ARGSUSED */
8052     static void
8053 f_winnr(argvars, retvar)
8054     VAR		argvars;
8055     VAR		retvar;
8056 {
8057     int		nr = 1;
8058 #ifdef FEAT_WINDOWS
8059     win_T	*wp;
8060     win_T	*twin = curwin;
8061     char_u	*arg;
8062 
8063     if (argvars[0].var_type != VAR_UNKNOWN)
8064     {
8065 	arg = get_var_string(&argvars[0]);
8066 	if (STRCMP(arg, "$") == 0)
8067 	    twin = lastwin;
8068 	else if (STRCMP(arg, "#") == 0)
8069 	{
8070 	    twin = prevwin;
8071 	    if (prevwin == NULL)
8072 		nr = 0;
8073 	}
8074 	else
8075 	{
8076 	    EMSG2(_(e_invexpr2), arg);
8077 	    nr = 0;
8078 	}
8079     }
8080 
8081     if (nr > 0)
8082 	for (wp = firstwin; wp != twin; wp = wp->w_next)
8083 	    ++nr;
8084 #endif
8085     retvar->var_val.var_number = nr;
8086 }
8087 
8088 /*
8089  * "winrestcmd()" function
8090  */
8091 /* ARGSUSED */
8092     static void
8093 f_winrestcmd(argvars, retvar)
8094     VAR		argvars;
8095     VAR		retvar;
8096 {
8097 #ifdef FEAT_WINDOWS
8098     win_T	*wp;
8099     int		winnr = 1;
8100     garray_T	ga;
8101     char_u	buf[50];
8102 
8103     ga_init2(&ga, (int)sizeof(char), 70);
8104     for (wp = firstwin; wp != NULL; wp = wp->w_next)
8105     {
8106 	sprintf((char *)buf, "%dresize %d|", winnr, wp->w_height);
8107 	ga_concat(&ga, buf);
8108 # ifdef FEAT_VERTSPLIT
8109 	sprintf((char *)buf, "vert %dresize %d|", winnr, wp->w_width);
8110 	ga_concat(&ga, buf);
8111 # endif
8112 	++winnr;
8113     }
8114     ga_append(&ga, NUL);
8115 
8116     retvar->var_val.var_string = ga.ga_data;
8117 #else
8118     retvar->var_val.var_string = NULL;
8119 #endif
8120     retvar->var_type = VAR_STRING;
8121 }
8122 
8123 /*
8124  * "winwidth(nr)" function
8125  */
8126     static void
8127 f_winwidth(argvars, retvar)
8128     VAR		argvars;
8129     VAR		retvar;
8130 {
8131     win_T	*wp;
8132 
8133     wp = find_win_by_nr(&argvars[0]);
8134     if (wp == NULL)
8135 	retvar->var_val.var_number = -1;
8136     else
8137 #ifdef FEAT_VERTSPLIT
8138 	retvar->var_val.var_number = wp->w_width;
8139 #else
8140 	retvar->var_val.var_number = Columns;
8141 #endif
8142 }
8143 
8144     static win_T *
8145 find_win_by_nr(vp)
8146     VAR		vp;
8147 {
8148 #ifdef FEAT_WINDOWS
8149     win_T	*wp;
8150 #endif
8151     int		nr;
8152 
8153     nr = get_var_number(vp);
8154 
8155 #ifdef FEAT_WINDOWS
8156     if (nr == 0)
8157 	return curwin;
8158 
8159     for (wp = firstwin; wp != NULL; wp = wp->w_next)
8160 	if (--nr <= 0)
8161 	    break;
8162     return wp;
8163 #else
8164     if (nr == 0 || nr == 1)
8165 	return curwin;
8166     return NULL;
8167 #endif
8168 }
8169 
8170 /*
8171  * Translate a String variable into a position.
8172  */
8173     static pos_T *
8174 var2fpos(varp, lnum)
8175     VAR		varp;
8176     int		lnum;		/* TRUE when $ is last line */
8177 {
8178     char_u	*name;
8179     static pos_T	pos;
8180     pos_T	*pp;
8181 
8182     name = get_var_string(varp);
8183     if (name[0] == '.')		/* cursor */
8184 	return &curwin->w_cursor;
8185     if (name[0] == '\'')	/* mark */
8186     {
8187 	pp = getmark(name[1], FALSE);
8188 	if (pp == NULL || pp == (pos_T *)-1 || pp->lnum <= 0)
8189 	    return NULL;
8190 	return pp;
8191     }
8192     if (name[0] == '$')		/* last column or line */
8193     {
8194 	if (lnum)
8195 	{
8196 	    pos.lnum = curbuf->b_ml.ml_line_count;
8197 	    pos.col = 0;
8198 	}
8199 	else
8200 	{
8201 	    pos.lnum = curwin->w_cursor.lnum;
8202 	    pos.col = (colnr_T)STRLEN(ml_get_curline());
8203 	}
8204 	return &pos;
8205     }
8206     return NULL;
8207 }
8208 
8209 /*
8210  * Get the length of an environment variable name.
8211  * Advance "arg" to the first character after the name.
8212  * Return 0 for error.
8213  */
8214     static int
8215 get_env_len(arg)
8216     char_u	**arg;
8217 {
8218     char_u	*p;
8219     int		len;
8220 
8221     for (p = *arg; vim_isIDc(*p); ++p)
8222 	;
8223     if (p == *arg)	    /* no name found */
8224 	return 0;
8225 
8226     len = (int)(p - *arg);
8227     *arg = p;
8228     return len;
8229 }
8230 
8231 /*
8232  * Get the length of the name of a function or internal variable.
8233  * "arg" is advanced to the first non-white character after the name.
8234  * Return 0 if something is wrong.
8235  */
8236     static int
8237 get_id_len(arg)
8238     char_u	**arg;
8239 {
8240     char_u	*p;
8241     int		len;
8242 
8243     /* Find the end of the name. */
8244     for (p = *arg; eval_isnamec(*p); ++p)
8245 	;
8246     if (p == *arg)	    /* no name found */
8247 	return 0;
8248 
8249     len = (int)(p - *arg);
8250     *arg = skipwhite(p);
8251 
8252     return len;
8253 }
8254 
8255 /*
8256  * Get the length of the name of a function.
8257  * "arg" is advanced to the first non-white character after the name.
8258  * Return 0 if something is wrong.
8259  * If the name contains 'magic' {}'s, expand them and return the
8260  * expanded name in an allocated string via 'alias' - caller must free.
8261  */
8262     static int
8263 get_func_len(arg, alias, evaluate)
8264     char_u	**arg;
8265     char_u	**alias;
8266     int		evaluate;
8267 {
8268     int		len;
8269 #ifdef FEAT_MAGIC_BRACES
8270     char_u	*p;
8271     char_u	*expr_start;
8272     char_u	*expr_end;
8273 #endif
8274 
8275     *alias = NULL;  /* default to no alias */
8276 
8277     if ((*arg)[0] == K_SPECIAL && (*arg)[1] == KS_EXTRA
8278 						  && (*arg)[2] == (int)KE_SNR)
8279     {
8280 	/* hard coded <SNR>, already translated */
8281 	*arg += 3;
8282 	return get_id_len(arg) + 3;
8283     }
8284     len = eval_fname_script(*arg);
8285     if (len > 0)
8286     {
8287 	/* literal "<SID>", "s:" or "<SNR>" */
8288 	*arg += len;
8289     }
8290 
8291 #ifdef FEAT_MAGIC_BRACES
8292     /*
8293      * Find the end of the name;
8294      */
8295     p = find_name_end(*arg, &expr_start, &expr_end);
8296     /* check for {} construction */
8297     if (expr_start != NULL)
8298     {
8299 	char_u	*temp_string;
8300 
8301 	if (!evaluate)
8302 	{
8303 	    len += (int)(p - *arg);
8304 	    *arg = skipwhite(p);
8305 	    return len;
8306 	}
8307 
8308 	/*
8309 	 * Include any <SID> etc in the expanded string:
8310 	 * Thus the -len here.
8311 	 */
8312 	temp_string = make_expanded_name(*arg - len, expr_start, expr_end, p);
8313 	if (temp_string == NULL)
8314 	    return 0;
8315 	*alias = temp_string;
8316 	*arg = skipwhite(p);
8317 	return (int)STRLEN(temp_string);
8318     }
8319 #endif
8320 
8321     len += get_id_len(arg);
8322     if (len == 0)
8323 	EMSG2(_(e_invexpr2), *arg);
8324 
8325     return len;
8326 }
8327 
8328     static char_u *
8329 find_name_end(arg, expr_start, expr_end)
8330     char_u	*arg;
8331     char_u	**expr_start;
8332     char_u	**expr_end;
8333 {
8334     int		nesting = 0;
8335     char_u	*p;
8336 
8337     *expr_start = NULL;
8338     *expr_end = NULL;
8339 
8340     for (p = arg; (*p != NUL && (eval_isnamec(*p) || nesting != 0)); ++p)
8341     {
8342 #ifdef FEAT_MAGIC_BRACES
8343 	if (*p == '{')
8344 	{
8345 	    nesting++;
8346 	    if (*expr_start == NULL)
8347 		*expr_start = p;
8348 	}
8349 	else if (*p == '}')
8350 	{
8351 	    nesting--;
8352 	    if (nesting == 0 && *expr_end == NULL)
8353 		*expr_end = p;
8354 	}
8355 #endif
8356     }
8357 
8358     return p;
8359 }
8360 
8361 /*
8362  * Return TRUE if character "c" can be used in a variable or function name.
8363  */
8364     static int
8365 eval_isnamec(c)
8366     int	    c;
8367 {
8368     return (ASCII_ISALNUM(c) || c == '_' || c == ':'
8369 #ifdef FEAT_MAGIC_BRACES
8370 	    || c == '{' || c == '}'
8371 #endif
8372 	    );
8373 }
8374 
8375 /*
8376  * Find a v: variable.
8377  * Return it's index, or -1 if not found.
8378  */
8379     static int
8380 find_vim_var(name, len)
8381     char_u	*name;
8382     int		len;		/* length of "name" */
8383 {
8384     char_u	*vname;
8385     int		vlen;
8386     int		i;
8387 
8388     /*
8389      * Ignore "v:" for old built-in variables, require it for new ones.
8390      */
8391     if (name[0] == 'v' && name[1] == ':')
8392     {
8393 	vname = name + 2;
8394 	vlen = len - 2;
8395     }
8396     else
8397     {
8398 	vname = name;
8399 	vlen = len;
8400     }
8401     for (i = 0; i < VV_LEN; ++i)
8402 	if (vlen == vimvars[i].len && STRCMP(vname, vimvars[i].name) == 0
8403 			 && ((vimvars[i].flags & VV_COMPAT) || vname != name))
8404 	    return i;
8405     return -1;
8406 }
8407 
8408 /*
8409  * Set number v: variable to "val".
8410  */
8411     void
8412 set_vim_var_nr(idx, val)
8413     int		idx;
8414     long	val;
8415 {
8416     vimvars[idx].val = (char_u *)val;
8417 }
8418 
8419 /*
8420  * Get number v: variable value;
8421  */
8422     long
8423 get_vim_var_nr(idx)
8424     int		idx;
8425 {
8426     return (long)vimvars[idx].val;
8427 }
8428 
8429 /*
8430  * Set v:count, v:count1 and v:prevcount.
8431  */
8432     void
8433 set_vcount(count, count1)
8434     long	count;
8435     long	count1;
8436 {
8437     vimvars[VV_PREVCOUNT].val = vimvars[VV_COUNT].val;
8438     vimvars[VV_COUNT].val = (char_u *)count;
8439     vimvars[VV_COUNT1].val = (char_u *)count1;
8440 }
8441 
8442 /*
8443  * Set string v: variable to a copy of "val".
8444  */
8445     void
8446 set_vim_var_string(idx, val, len)
8447     int		idx;
8448     char_u	*val;
8449     int		len;	    /* length of "val" to use or -1 (whole string) */
8450 {
8451     vim_free(vimvars[idx].val);
8452     if (val == NULL)
8453 	vimvars[idx].val = NULL;
8454     else if (len == -1)
8455 	vimvars[idx].val = vim_strsave(val);
8456     else
8457 	vimvars[idx].val = vim_strnsave(val, len);
8458 }
8459 
8460 /*
8461  * Set v:register if needed.
8462  */
8463     void
8464 set_reg_var(c)
8465     int		c;
8466 {
8467     char_u	regname;
8468 
8469     if (c == 0 || c == ' ')
8470 	regname = '"';
8471     else
8472 	regname = c;
8473     /* Avoid free/alloc when the value is already right. */
8474     if (vimvars[VV_REG].val == NULL || vimvars[VV_REG].val[0] != c)
8475 	set_vim_var_string(VV_REG, &regname, 1);
8476 }
8477 
8478 /*
8479  * Get or set v:exception.  If "oldval" == NULL, return the current value.
8480  * Otherwise, restore the value to "oldval" and return NULL.
8481  * Must always be called in pairs to save and restore v:exception!  Does not
8482  * take care of memory allocations.
8483  */
8484     char_u *
8485 v_exception(oldval)
8486     char_u	*oldval;
8487 {
8488     if (oldval == NULL)
8489 	return vimvars[VV_EXCEPTION].val;
8490 
8491     vimvars[VV_EXCEPTION].val = oldval;
8492     return NULL;
8493 }
8494 
8495 /*
8496  * Get or set v:throwpoint.  If "oldval" == NULL, return the current value.
8497  * Otherwise, restore the value to "oldval" and return NULL.
8498  * Must always be called in pairs to save and restore v:throwpoint!  Does not
8499  * take care of memory allocations.
8500  */
8501     char_u *
8502 v_throwpoint(oldval)
8503     char_u	*oldval;
8504 {
8505     if (oldval == NULL)
8506 	return vimvars[VV_THROWPOINT].val;
8507 
8508     vimvars[VV_THROWPOINT].val = oldval;
8509     return NULL;
8510 }
8511 
8512 #if defined(FEAT_AUTOCMD) || defined(PROTO)
8513 /*
8514  * Set v:cmdarg.
8515  * If "eap" != NULL, use "eap" to generate the value and return the old value.
8516  * If "oldarg" != NULL, restore the value to "oldarg" and return NULL.
8517  * Must always be called in pairs!
8518  */
8519     char_u *
8520 set_cmdarg(eap, oldarg)
8521     exarg_T	*eap;
8522     char_u	*oldarg;
8523 {
8524     char_u	*oldval;
8525     char_u	*newval;
8526     unsigned	len;
8527 
8528     oldval = vimvars[VV_CMDARG].val;
8529     if (eap != NULL)
8530     {
8531 	if (eap->force_bin == FORCE_BIN)
8532 	    len = 6;
8533 	else if (eap->force_bin == FORCE_NOBIN)
8534 	    len = 8;
8535 	else
8536 	    len = 0;
8537 	if (eap->force_ff != 0)
8538 	    len += (unsigned)STRLEN(eap->cmd + eap->force_ff) + 6;
8539 # ifdef FEAT_MBYTE
8540 	if (eap->force_enc != 0)
8541 	    len += (unsigned)STRLEN(eap->cmd + eap->force_enc) + 7;
8542 # endif
8543 
8544 	newval = alloc(len + 1);
8545 	if (newval == NULL)
8546 	    return NULL;
8547 
8548 	if (eap->force_bin == FORCE_BIN)
8549 	    sprintf((char *)newval, " ++bin");
8550 	else if (eap->force_bin == FORCE_NOBIN)
8551 	    sprintf((char *)newval, " ++nobin");
8552 	else
8553 	    *newval = NUL;
8554 	if (eap->force_ff != 0)
8555 	    sprintf((char *)newval + STRLEN(newval), " ++ff=%s",
8556 						    eap->cmd + eap->force_ff);
8557 # ifdef FEAT_MBYTE
8558 	if (eap->force_enc != 0)
8559 	    sprintf((char *)newval + STRLEN(newval), " ++enc=%s",
8560 						   eap->cmd + eap->force_enc);
8561 # endif
8562 	vimvars[VV_CMDARG].val = newval;
8563 	return oldval;
8564     }
8565 
8566     vim_free(oldval);
8567     vimvars[VV_CMDARG].val = oldarg;
8568     return NULL;
8569 }
8570 #endif
8571 
8572 /*
8573  * Get the value of internal variable "name".
8574  * Return OK or FAIL.
8575  */
8576     static int
8577 get_var_var(name, len, retvar)
8578     char_u	*name;
8579     int		len;		/* length of "name" */
8580     VAR		retvar;		/* NULL when only checking existence */
8581 {
8582     int		ret = OK;
8583     int		type = VAR_UNKNOWN;
8584     long	number = 1;
8585     char_u	*string = NULL;
8586     VAR		v;
8587     int		cc;
8588     int		i;
8589 
8590     /* truncate the name, so that we can use strcmp() */
8591     cc = name[len];
8592     name[len] = NUL;
8593 
8594     /*
8595      * Check for "b:changedtick".
8596      */
8597     if (STRCMP(name, "b:changedtick") == 0)
8598     {
8599 	type = VAR_NUMBER;
8600 	number = curbuf->b_changedtick;
8601     }
8602 
8603     /*
8604      * Check for built-in v: variables.
8605      */
8606     else if ((i = find_vim_var(name, len)) >= 0)
8607     {
8608 	type = vimvars[i].type;
8609 	number = (long)vimvars[i].val;
8610 	string = vimvars[i].val;
8611     }
8612 
8613     /*
8614      * Check for user-defined variables.
8615      */
8616     else
8617     {
8618 	v = find_var(name, FALSE);
8619 	if (v != NULL)
8620 	{
8621 	    type = v->var_type;
8622 	    number = v->var_val.var_number;
8623 	    string = v->var_val.var_string;
8624 	}
8625     }
8626 
8627     if (type == VAR_UNKNOWN)
8628     {
8629 	if (retvar != NULL)
8630 	    EMSG2(_("E121: Undefined variable: %s"), name);
8631 	ret = FAIL;
8632     }
8633     else if (retvar != NULL)
8634     {
8635 	retvar->var_type = type;
8636 	if (type == VAR_NUMBER)
8637 	    retvar->var_val.var_number = number;
8638 	else if (type == VAR_STRING)
8639 	{
8640 	    if (string != NULL)
8641 		string = vim_strsave(string);
8642 	    retvar->var_val.var_string = string;
8643 	}
8644     }
8645 
8646     name[len] = cc;
8647 
8648     return ret;
8649 }
8650 
8651 /*
8652  * Allocate memory for a variable, and make it emtpy (0 or NULL value).
8653  */
8654     static VAR
8655 alloc_var()
8656 {
8657     return (VAR)alloc_clear((unsigned)sizeof(var));
8658 }
8659 
8660 /*
8661  * Allocate memory for a variable, and assign a string to it.
8662  * The string "s" must have been allocated, it is consumed.
8663  * Return NULL for out of memory, the variable otherwise.
8664  */
8665     static VAR
8666 alloc_string_var(s)
8667     char_u	*s;
8668 {
8669     VAR	    retvar;
8670 
8671     retvar = alloc_var();
8672     if (retvar != NULL)
8673     {
8674 	retvar->var_type = VAR_STRING;
8675 	retvar->var_val.var_string = s;
8676     }
8677     else
8678 	vim_free(s);
8679     return retvar;
8680 }
8681 
8682 /*
8683  * Free the memory for a variable.
8684  */
8685     static void
8686 free_var(varp)
8687     VAR	    varp;
8688 {
8689     if (varp != NULL)
8690     {
8691 	if (varp->var_type == VAR_STRING)
8692 	    vim_free(varp->var_val.var_string);
8693 	vim_free(varp->var_name);
8694 	vim_free(varp);
8695     }
8696 }
8697 
8698 /*
8699  * Free the memory for a variable value and set the value to NULL or 0.
8700  */
8701     static void
8702 clear_var(varp)
8703     VAR	    varp;
8704 {
8705     if (varp != NULL)
8706     {
8707 	if (varp->var_type == VAR_STRING)
8708 	{
8709 	    vim_free(varp->var_val.var_string);
8710 	    varp->var_val.var_string = NULL;
8711 	}
8712 	else
8713 	    varp->var_val.var_number = 0;
8714     }
8715 }
8716 
8717 /*
8718  * Get the number value of a variable.
8719  * If it is a String variable, uses vim_str2nr().
8720  */
8721     static long
8722 get_var_number(varp)
8723     VAR		varp;
8724 {
8725     long	n;
8726 
8727     if (varp->var_type == VAR_NUMBER)
8728 	return (long)(varp->var_val.var_number);
8729     else if (varp->var_type == VAR_UNKNOWN || varp->var_val.var_string == NULL)
8730 	return 0L;
8731     else
8732     {
8733 	vim_str2nr(varp->var_val.var_string, NULL, NULL, TRUE, TRUE, &n, NULL);
8734 	return n;
8735     }
8736 }
8737 
8738 /*
8739  * Get the lnum from the first argument.  Also accepts ".", "$", etc.
8740  */
8741     static linenr_T
8742 get_var_lnum(argvars)
8743     VAR		argvars;
8744 {
8745     var		retvar;
8746     linenr_T	lnum;
8747 
8748     lnum = get_var_number(&argvars[0]);
8749     if (lnum == 0)  /* no valid number, try using line() */
8750     {
8751 	retvar.var_type = VAR_NUMBER;
8752 	f_line(argvars, &retvar);
8753 	lnum = retvar.var_val.var_number;
8754 	clear_var(&retvar);
8755     }
8756     return lnum;
8757 }
8758 
8759 /*
8760  * Get the string value of a variable.
8761  * If it is a Number variable, the number is converted into a string.
8762  * get_var_string() uses a single, static buffer.  YOU CAN ONLY USE IT ONCE!
8763  * get_var_string_buf() uses a given buffer.
8764  * If the String variable has never been set, return an empty string.
8765  * Never returns NULL;
8766  */
8767     static char_u *
8768 get_var_string(varp)
8769     VAR	    varp;
8770 {
8771     static char_u   mybuf[NUMBUFLEN];
8772 
8773     return get_var_string_buf(varp, mybuf);
8774 }
8775 
8776     static char_u *
8777 get_var_string_buf(varp, buf)
8778     VAR	    varp;
8779     char_u  *buf;
8780 {
8781     if (varp->var_type == VAR_NUMBER)
8782     {
8783 	sprintf((char *)buf, "%ld", (long)varp->var_val.var_number);
8784 	return buf;
8785     }
8786     else if (varp->var_val.var_string == NULL)
8787 	return (char_u *)"";
8788     else
8789 	return varp->var_val.var_string;
8790 }
8791 
8792 /*
8793  * Find variable "name" in the list of variables.
8794  * Return a pointer to it if found, NULL if not found.
8795  */
8796     static VAR
8797 find_var(name, writing)
8798     char_u	*name;
8799     int		writing;
8800 {
8801     int		i;
8802     char_u	*varname;
8803     garray_T	*gap;
8804 
8805     /* Check for function arguments "a:" */
8806     if (name[0] == 'a' && name[1] == ':')
8807     {
8808 	if (writing)
8809 	{
8810 	    EMSG2(_(e_readonlyvar), name);
8811 	    return NULL;
8812 	}
8813 	name += 2;
8814 	if (current_funccal == NULL)
8815 	    return NULL;
8816 	if (VIM_ISDIGIT(*name))
8817 	{
8818 	    i = atol((char *)name);
8819 	    if (i == 0)					/* a:0 */
8820 		return &current_funccal->a0_var;
8821 	    i += current_funccal->func->args.ga_len;
8822 	    if (i > current_funccal->argcount)		/* a:999 */
8823 		return NULL;
8824 	    return &(current_funccal->argvars[i - 1]);	/* a:1, a:2, etc. */
8825 	}
8826 	if (STRCMP(name, "firstline") == 0)
8827 	    return &(current_funccal->firstline);
8828 	if (STRCMP(name, "lastline") == 0)
8829 	    return &(current_funccal->lastline);
8830 	for (i = 0; i < current_funccal->func->args.ga_len; ++i)
8831 	    if (STRCMP(name, ((char_u **)
8832 			      (current_funccal->func->args.ga_data))[i]) == 0)
8833 	    return &(current_funccal->argvars[i]);	/* a:name */
8834 	return NULL;
8835     }
8836 
8837     gap = find_var_ga(name, &varname);
8838     if (gap == NULL)
8839 	return NULL;
8840     return find_var_in_ga(gap, varname);
8841 }
8842 
8843     static VAR
8844 find_var_in_ga(gap, varname)
8845     garray_T	*gap;
8846     char_u	*varname;
8847 {
8848     int	i;
8849 
8850     for (i = gap->ga_len; --i >= 0; )
8851 	if (VAR_GAP_ENTRY(i, gap).var_name != NULL
8852 		&& STRCMP(VAR_GAP_ENTRY(i, gap).var_name, varname) == 0)
8853 	    break;
8854     if (i < 0)
8855 	return NULL;
8856     return &VAR_GAP_ENTRY(i, gap);
8857 }
8858 
8859 /*
8860  * Find the growarray and start of name without ':' for a variable name.
8861  */
8862     static garray_T *
8863 find_var_ga(name, varname)
8864     char_u  *name;
8865     char_u  **varname;
8866 {
8867     if (name[1] != ':')
8868     {
8869 	/* If not "x:name" there must not be any ":" in the name. */
8870 	if (vim_strchr(name, ':') != NULL)
8871 	    return NULL;
8872 	*varname = name;
8873 	if (current_funccal == NULL)
8874 	    return &variables;			/* global variable */
8875 	return &current_funccal->l_vars;	/* local function variable */
8876     }
8877     *varname = name + 2;
8878     if (*name == 'b')				/* buffer variable */
8879 	return &curbuf->b_vars;
8880     if (*name == 'w')				/* window variable */
8881 	return &curwin->w_vars;
8882     if (*name == 'g')				/* global variable */
8883 	return &variables;
8884     if (*name == 'l' && current_funccal != NULL)/* local function variable */
8885 	return &current_funccal->l_vars;
8886     if (*name == 's'				/* script variable */
8887 	    && current_SID > 0 && current_SID <= ga_scripts.ga_len)
8888 	return &SCRIPT_VARS(current_SID);
8889     return NULL;
8890 }
8891 
8892 /*
8893  * Get the string value of a (global/local) variable.
8894  * Returns NULL when it doesn't exist.
8895  */
8896     char_u *
8897 get_var_value(name)
8898     char_u	*name;
8899 {
8900     VAR		v;
8901 
8902     v = find_var(name, FALSE);
8903     if (v == NULL)
8904 	return NULL;
8905     return get_var_string(v);
8906 }
8907 
8908 /*
8909  * Allocate a new growarry for a sourced script.  It will be used while
8910  * sourcing this script and when executing functions defined in the script.
8911  */
8912     void
8913 new_script_vars(id)
8914     scid_T id;
8915 {
8916     if (ga_grow(&ga_scripts, (int)(id - ga_scripts.ga_len)) == OK)
8917     {
8918 	while (ga_scripts.ga_len < id)
8919 	{
8920 	    var_init(&SCRIPT_VARS(ga_scripts.ga_len + 1));
8921 	    ++ga_scripts.ga_len;
8922 	    --ga_scripts.ga_room;
8923 	}
8924     }
8925 }
8926 
8927 /*
8928  * Initialize internal variables for use.
8929  */
8930     void
8931 var_init(gap)
8932     garray_T *gap;
8933 {
8934     ga_init2(gap, (int)sizeof(var), 4);
8935 }
8936 
8937 /*
8938  * Clean up a list of internal variables.
8939  */
8940     void
8941 var_clear(gap)
8942     garray_T *gap;
8943 {
8944     int	    i;
8945 
8946     for (i = gap->ga_len; --i >= 0; )
8947 	var_free_one(&VAR_GAP_ENTRY(i, gap));
8948     ga_clear(gap);
8949 }
8950 
8951     static void
8952 var_free_one(v)
8953     VAR	    v;
8954 {
8955     vim_free(v->var_name);
8956     v->var_name = NULL;
8957     if (v->var_type == VAR_STRING)
8958 	vim_free(v->var_val.var_string);
8959     v->var_val.var_string = NULL;
8960 }
8961 
8962 /*
8963  * List the value of one internal variable.
8964  */
8965     static void
8966 list_one_var(v, prefix)
8967     VAR		v;
8968     char_u	*prefix;
8969 {
8970     list_one_var_a(prefix, v->var_name, v->var_type, get_var_string(v));
8971 }
8972 
8973 /*
8974  * List the value of one "v:" variable.
8975  */
8976     static void
8977 list_vim_var(i)
8978     int		i;	/* index in vimvars[] */
8979 {
8980     char_u	*p;
8981     char_u	numbuf[NUMBUFLEN];
8982 
8983     if (vimvars[i].type == VAR_NUMBER)
8984     {
8985 	p = numbuf;
8986 	sprintf((char *)p, "%ld", (long)vimvars[i].val);
8987     }
8988     else if (vimvars[i].val == NULL)
8989 	p = (char_u *)"";
8990     else
8991 	p = vimvars[i].val;
8992     list_one_var_a((char_u *)"v:", (char_u *)vimvars[i].name,
8993 							  vimvars[i].type, p);
8994 }
8995 
8996     static void
8997 list_one_var_a(prefix, name, type, string)
8998     char_u	*prefix;
8999     char_u	*name;
9000     int		type;
9001     char_u	*string;
9002 {
9003     msg_attr(prefix, 0);    /* don't use msg(), it overwrites "v:statusmsg" */
9004     if (name != NULL)	/* "a:" vars don't have a name stored */
9005 	msg_puts(name);
9006     msg_putchar(' ');
9007     msg_advance(22);
9008     if (type == VAR_NUMBER)
9009 	msg_putchar('#');
9010     else
9011 	msg_putchar(' ');
9012     msg_outtrans(string);
9013 }
9014 
9015 /*
9016  * Set variable "name" to value in "varp".
9017  * If the variable already exists, the value is updated.
9018  * Otherwise the variable is created.
9019  */
9020     static void
9021 set_var(name, varp)
9022     char_u	*name;
9023     VAR		varp;
9024 {
9025     int		i;
9026     VAR		v;
9027     char_u	*varname;
9028     garray_T	*gap;
9029 
9030     /*
9031      * Handle setting internal v: variables.
9032      */
9033     i = find_vim_var(name, (int)STRLEN(name));
9034     if (i >= 0)
9035     {
9036 	if (vimvars[i].flags & VV_RO)
9037 	    EMSG2(_(e_readonlyvar), name);
9038 	else
9039 	{
9040 	    if (vimvars[i].type == VAR_STRING)
9041 	    {
9042 		vim_free(vimvars[i].val);
9043 		vimvars[i].val = vim_strsave(get_var_string(varp));
9044 	    }
9045 	    else
9046 		vimvars[i].val = (char_u *)(long)varp->var_val.var_number;
9047 	}
9048 	return;
9049     }
9050 
9051     v = find_var(name, TRUE);
9052     if (v != NULL)	    /* existing variable, only need to free string */
9053     {
9054 	if (v->var_type == VAR_STRING)
9055 	    vim_free(v->var_val.var_string);
9056     }
9057     else		    /* add a new variable */
9058     {
9059 	gap = find_var_ga(name, &varname);
9060 	if (gap == NULL)    /* illegal name */
9061 	{
9062 	    EMSG2(_("E461: Illegal variable name: %s"), name);
9063 	    return;
9064 	}
9065 
9066 	/* Try to use an empty entry */
9067 	for (i = gap->ga_len; --i >= 0; )
9068 	    if (VAR_GAP_ENTRY(i, gap).var_name == NULL)
9069 		break;
9070 	if (i < 0)	    /* need to allocate more room */
9071 	{
9072 	    if (ga_grow(gap, 1) == FAIL)
9073 		return;
9074 	    i = gap->ga_len;
9075 	}
9076 	v = &VAR_GAP_ENTRY(i, gap);
9077 	if ((v->var_name = vim_strsave(varname)) == NULL)
9078 	    return;
9079 	if (i == gap->ga_len)
9080 	{
9081 	    ++gap->ga_len;
9082 	    --gap->ga_room;
9083 	}
9084     }
9085     copy_var(varp, v);
9086 }
9087 
9088     static void
9089 copy_var(from, to)
9090     VAR	from;
9091     VAR	to;
9092 {
9093     to->var_type = from->var_type;
9094     if (from->var_type == VAR_STRING)
9095 	to->var_val.var_string = vim_strsave(get_var_string(from));
9096     else
9097 	to->var_val.var_number = from->var_val.var_number;
9098 }
9099 
9100 /*
9101  * ":echo expr1 ..."	print each argument separated with a space, add a
9102  *			newline at the end.
9103  * ":echon expr1 ..."	print each argument plain.
9104  */
9105     void
9106 ex_echo(eap)
9107     exarg_T	*eap;
9108 {
9109     char_u	*arg = eap->arg;
9110     var		retvar;
9111     char_u	*p;
9112     int		needclr = TRUE;
9113     int		atstart = TRUE;
9114 
9115     if (eap->skip)
9116 	++emsg_skip;
9117     while (*arg != NUL && *arg != '|' && *arg != '\n' && !got_int)
9118     {
9119 	p = arg;
9120 	if (eval1(&arg, &retvar, !eap->skip) == FAIL)
9121 	{
9122 	    /*
9123 	     * Report the invalid expression unless the expression evaluation
9124 	     * has been cancelled due to an aborting error, an interrupt, or an
9125 	     * exception.
9126 	     */
9127 	    if (!aborting())
9128 		EMSG2(_(e_invexpr2), p);
9129 	    break;
9130 	}
9131 	if (!eap->skip)
9132 	{
9133 	    if (atstart)
9134 	    {
9135 		atstart = FALSE;
9136 		/* Call msg_start() after eval1(), evaluating the expression
9137 		 * may cause a message to appear. */
9138 		if (eap->cmdidx == CMD_echo)
9139 		    msg_start();
9140 	    }
9141 	    else if (eap->cmdidx == CMD_echo)
9142 		msg_puts_attr((char_u *)" ", echo_attr);
9143 	    for (p = get_var_string(&retvar); *p != NUL && !got_int; ++p)
9144 		if (*p == '\n' || *p == '\r' || *p == TAB)
9145 		{
9146 		    if (*p != TAB && needclr)
9147 		    {
9148 			/* remove any text still there from the command */
9149 			msg_clr_eos();
9150 			needclr = FALSE;
9151 		    }
9152 		    msg_putchar_attr(*p, echo_attr);
9153 		}
9154 		else
9155 		{
9156 #ifdef FEAT_MBYTE
9157 		    if (has_mbyte)
9158 		    {
9159 			int i = (*mb_ptr2len_check)(p);
9160 
9161 			(void)msg_outtrans_len_attr(p, i, echo_attr);
9162 			p += i - 1;
9163 		    }
9164 		    else
9165 #endif
9166 			(void)msg_outtrans_len_attr(p, 1, echo_attr);
9167 		}
9168 	}
9169 	clear_var(&retvar);
9170 	arg = skipwhite(arg);
9171     }
9172     eap->nextcmd = check_nextcmd(arg);
9173 
9174     if (eap->skip)
9175 	--emsg_skip;
9176     else
9177     {
9178 	/* remove text that may still be there from the command */
9179 	if (needclr)
9180 	    msg_clr_eos();
9181 	if (eap->cmdidx == CMD_echo)
9182 	    msg_end();
9183     }
9184 }
9185 
9186 /*
9187  * ":echohl {name}".
9188  */
9189     void
9190 ex_echohl(eap)
9191     exarg_T	*eap;
9192 {
9193     int		id;
9194 
9195     id = syn_name2id(eap->arg);
9196     if (id == 0)
9197 	echo_attr = 0;
9198     else
9199 	echo_attr = syn_id2attr(id);
9200 }
9201 
9202 /*
9203  * ":execute expr1 ..."	execute the result of an expression.
9204  * ":echomsg expr1 ..."	Print a message
9205  * ":echoerr expr1 ..."	Print an error
9206  * Each gets spaces around each argument and a newline at the end for
9207  * echo commands
9208  */
9209     void
9210 ex_execute(eap)
9211     exarg_T	*eap;
9212 {
9213     char_u	*arg = eap->arg;
9214     var		retvar;
9215     int		ret = OK;
9216     char_u	*p;
9217     garray_T	ga;
9218     int		len;
9219     int		save_did_emsg;
9220 
9221     ga_init2(&ga, 1, 80);
9222 
9223     if (eap->skip)
9224 	++emsg_skip;
9225     while (*arg != NUL && *arg != '|' && *arg != '\n')
9226     {
9227 	p = arg;
9228 	if (eval1(&arg, &retvar, !eap->skip) == FAIL)
9229 	{
9230 	    /*
9231 	     * Report the invalid expression unless the expression evaluation
9232 	     * has been cancelled due to an aborting error, an interrupt, or an
9233 	     * exception.
9234 	     */
9235 	    if (!aborting())
9236 		EMSG2(_(e_invexpr2), p);
9237 	    ret = FAIL;
9238 	    break;
9239 	}
9240 
9241 	if (!eap->skip)
9242 	{
9243 	    p = get_var_string(&retvar);
9244 	    len = (int)STRLEN(p);
9245 	    if (ga_grow(&ga, len + 2) == FAIL)
9246 	    {
9247 		clear_var(&retvar);
9248 		ret = FAIL;
9249 		break;
9250 	    }
9251 	    if (ga.ga_len)
9252 	    {
9253 		((char_u *)(ga.ga_data))[ga.ga_len++] = ' ';
9254 		--ga.ga_room;
9255 	    }
9256 	    STRCPY((char_u *)(ga.ga_data) + ga.ga_len, p);
9257 	    ga.ga_room -= len;
9258 	    ga.ga_len += len;
9259 	}
9260 
9261 	clear_var(&retvar);
9262 	arg = skipwhite(arg);
9263     }
9264 
9265     if (ret != FAIL && ga.ga_data != NULL)
9266     {
9267 	if (eap->cmdidx == CMD_echomsg)
9268 	    MSG_ATTR(ga.ga_data, echo_attr);
9269 	else if (eap->cmdidx == CMD_echoerr)
9270 	{
9271 	    /* We don't want to abort following commands, restore did_emsg. */
9272 	    save_did_emsg = did_emsg;
9273 	    EMSG((char_u *)ga.ga_data);
9274 	    if (!force_abort)
9275 		did_emsg = save_did_emsg;
9276 	}
9277 	else if (eap->cmdidx == CMD_execute)
9278 	    do_cmdline((char_u *)ga.ga_data,
9279 		       eap->getline, eap->cookie, DOCMD_NOWAIT|DOCMD_VERBOSE);
9280     }
9281 
9282     ga_clear(&ga);
9283 
9284     if (eap->skip)
9285 	--emsg_skip;
9286 
9287     eap->nextcmd = check_nextcmd(arg);
9288 }
9289 
9290 /*
9291  * Skip over the name of an option: "&option", "&g:option" or "&l:option".
9292  * "arg" points to the "&" or '+' when called, to "option" when returning.
9293  * Returns NULL when no option name found.  Otherwise pointer to the char
9294  * after the option name.
9295  */
9296     static char_u *
9297 find_option_end(arg, opt_flags)
9298     char_u	**arg;
9299     int		*opt_flags;
9300 {
9301     char_u	*p = *arg;
9302 
9303     ++p;
9304     if (*p == 'g' && p[1] == ':')
9305     {
9306 	*opt_flags = OPT_GLOBAL;
9307 	p += 2;
9308     }
9309     else if (*p == 'l' && p[1] == ':')
9310     {
9311 	*opt_flags = OPT_LOCAL;
9312 	p += 2;
9313     }
9314     else
9315 	*opt_flags = 0;
9316 
9317     if (!ASCII_ISALPHA(*p))
9318 	return NULL;
9319     *arg = p;
9320 
9321     if (p[0] == 't' && p[1] == '_' && p[2] != NUL && p[3] != NUL)
9322 	p += 4;	    /* termcap option */
9323     else
9324 	while (ASCII_ISALPHA(*p))
9325 	    ++p;
9326     return p;
9327 }
9328 
9329 /*
9330  * ":function"
9331  */
9332     void
9333 ex_function(eap)
9334     exarg_T	*eap;
9335 {
9336     char_u	*theline;
9337     int		j;
9338     int		c;
9339 #ifdef FEAT_MAGIC_BRACES
9340     int		saved_did_emsg;
9341 #endif
9342     char_u	*name = NULL;
9343     char_u	*p;
9344     char_u	*arg;
9345     garray_T	newargs;
9346     garray_T	newlines;
9347     int		varargs = FALSE;
9348     int		mustend = FALSE;
9349     int		flags = 0;
9350     ufunc_T	*fp;
9351     int		indent;
9352     int		nesting;
9353     char_u	*skip_until = NULL;
9354     static char_u e_funcexts[] = N_("E122: Function %s already exists, add ! to replace it");
9355 
9356     /*
9357      * ":function" without argument: list functions.
9358      */
9359     if (ends_excmd(*eap->arg))
9360     {
9361 	if (!eap->skip)
9362 	    for (fp = firstfunc; fp != NULL && !got_int; fp = fp->next)
9363 		list_func_head(fp, FALSE);
9364 	eap->nextcmd = check_nextcmd(eap->arg);
9365 	return;
9366     }
9367 
9368     p = eap->arg;
9369     name = trans_function_name(&p, eap->skip, FALSE);
9370     if (name == NULL && !eap->skip)
9371     {
9372 	/*
9373 	 * Return on an invalid expression in braces, unless the expression
9374 	 * evaluation has been cancelled due to an aborting error, an
9375 	 * interrupt, or an exception.
9376 	 */
9377 	if (!aborting())
9378 	    return;
9379 	else
9380 	    eap->skip = TRUE;
9381     }
9382 #ifdef FEAT_MAGIC_BRACES
9383     /* An error in a function call during evaluation of an expression in magic
9384      * braces should not cause the function not to be defined. */
9385     saved_did_emsg = did_emsg;
9386     did_emsg = FALSE;
9387 #endif
9388 
9389     /*
9390      * ":function func" with only function name: list function.
9391      */
9392     if (vim_strchr(p, '(') == NULL)
9393     {
9394 	if (!ends_excmd(*skipwhite(p)))
9395 	{
9396 	    EMSG(_(e_trailing));
9397 	    goto erret_name;
9398 	}
9399 	eap->nextcmd = check_nextcmd(p);
9400 	if (eap->nextcmd != NULL)
9401 	    *p = NUL;
9402 	if (!eap->skip && !got_int)
9403 	{
9404 	    fp = find_func(name);
9405 	    if (fp != NULL)
9406 	    {
9407 		list_func_head(fp, TRUE);
9408 		for (j = 0; j < fp->lines.ga_len && !got_int; ++j)
9409 		{
9410 		    msg_putchar('\n');
9411 		    msg_outnum((long)(j + 1));
9412 		    if (j < 9)
9413 			msg_putchar(' ');
9414 		    if (j < 99)
9415 			msg_putchar(' ');
9416 		    msg_prt_line(FUNCLINE(fp, j));
9417 		    out_flush();	/* show a line at a time */
9418 		    ui_breakcheck();
9419 		}
9420 		if (!got_int)
9421 		{
9422 		    msg_putchar('\n');
9423 		    msg_puts((char_u *)"   endfunction");
9424 		}
9425 	    }
9426 	    else
9427 		EMSG2(_("E123: Undefined function: %s"), eap->arg);
9428 	}
9429 	goto erret_name;
9430     }
9431 
9432     /*
9433      * ":function name(arg1, arg2)" Define function.
9434      */
9435     p = skipwhite(p);
9436     if (*p != '(')
9437     {
9438 	if (!eap->skip)
9439 	{
9440 	    EMSG2(_("E124: Missing '(': %s"), eap->arg);
9441 	    goto erret_name;
9442 	}
9443 	/* attempt to continue by skipping some text */
9444 	if (vim_strchr(p, '(') != NULL)
9445 	    p = vim_strchr(p, '(');
9446     }
9447     p = skipwhite(p + 1);
9448 
9449     ga_init2(&newargs, (int)sizeof(char_u *), 3);
9450     ga_init2(&newlines, (int)sizeof(char_u *), 3);
9451 
9452     /*
9453      * Isolate the arguments: "arg1, arg2, ...)"
9454      */
9455     while (*p != ')')
9456     {
9457 	if (p[0] == '.' && p[1] == '.' && p[2] == '.')
9458 	{
9459 	    varargs = TRUE;
9460 	    p += 3;
9461 	    mustend = TRUE;
9462 	}
9463 	else
9464 	{
9465 	    arg = p;
9466 	    while (ASCII_ISALNUM(*p) || *p == '_')
9467 		++p;
9468 	    if (arg == p || isdigit(*arg)
9469 		    || (p - arg == 9 && STRNCMP(arg, "firstline", 9) == 0)
9470 		    || (p - arg == 8 && STRNCMP(arg, "lastline", 8) == 0))
9471 	    {
9472 		if (!eap->skip)
9473 		    EMSG2(_("E125: Illegal argument: %s"), arg);
9474 		break;
9475 	    }
9476 	    if (ga_grow(&newargs, 1) == FAIL)
9477 		goto erret;
9478 	    c = *p;
9479 	    *p = NUL;
9480 	    arg = vim_strsave(arg);
9481 	    if (arg == NULL)
9482 		goto erret;
9483 	    ((char_u **)(newargs.ga_data))[newargs.ga_len] = arg;
9484 	    *p = c;
9485 	    newargs.ga_len++;
9486 	    newargs.ga_room--;
9487 	    if (*p == ',')
9488 		++p;
9489 	    else
9490 		mustend = TRUE;
9491 	}
9492 	p = skipwhite(p);
9493 	if (mustend && *p != ')')
9494 	{
9495 	    if (!eap->skip)
9496 		EMSG2(_(e_invarg2), eap->arg);
9497 	    break;
9498 	}
9499     }
9500     ++p;	/* skip the ')' */
9501 
9502     /* find extra arguments "range" and "abort" */
9503     for (;;)
9504     {
9505 	p = skipwhite(p);
9506 	if (STRNCMP(p, "range", 5) == 0)
9507 	{
9508 	    flags |= FC_RANGE;
9509 	    p += 5;
9510 	}
9511 	else if (STRNCMP(p, "abort", 5) == 0)
9512 	{
9513 	    flags |= FC_ABORT;
9514 	    p += 5;
9515 	}
9516 	else
9517 	    break;
9518     }
9519 
9520     if (*p != NUL && *p != '"' && *p != '\n' && !eap->skip && !did_emsg)
9521 	EMSG(_(e_trailing));
9522 
9523     /*
9524      * Read the body of the function, until ":endfunction" is found.
9525      */
9526     if (KeyTyped)
9527     {
9528 	/* Check if the function already exists, don't let the user type the
9529 	 * whole function before telling him it doesn't work!  For a script we
9530 	 * need to skip the body to be able to find what follows. */
9531 	if (!eap->skip && !eap->forceit && find_func(name) != NULL)
9532 	    EMSG2(_(e_funcexts), name);
9533 
9534 	msg_putchar('\n');	    /* don't overwrite the function name */
9535 	cmdline_row = msg_row;
9536     }
9537 
9538     indent = 2;
9539     nesting = 0;
9540     for (;;)
9541     {
9542 	msg_scroll = TRUE;
9543 	need_wait_return = FALSE;
9544 	if (eap->getline == NULL)
9545 	    theline = getcmdline(':', 0L, indent);
9546 	else
9547 	    theline = eap->getline(':', eap->cookie, indent);
9548 	if (KeyTyped)
9549 	    lines_left = Rows - 1;
9550 	if (theline == NULL)
9551 	{
9552 	    EMSG(_("E126: Missing :endfunction"));
9553 	    goto erret;
9554 	}
9555 
9556 	if (skip_until != NULL)
9557 	{
9558 	    /* between ":append" and "." and between ":python <<EOF" and "EOF"
9559 	     * don't check for ":endfunc". */
9560 	    if (STRCMP(theline, skip_until) == 0)
9561 	    {
9562 		vim_free(skip_until);
9563 		skip_until = NULL;
9564 	    }
9565 	}
9566 	else
9567 	{
9568 	    /* skip ':' and blanks*/
9569 	    for (p = theline; vim_iswhite(*p) || *p == ':'; ++p)
9570 		;
9571 
9572 	    /* Check for "endfunction" (should be more strict...). */
9573 	    if (STRNCMP(p, "endf", 4) == 0 && nesting-- == 0)
9574 	    {
9575 		vim_free(theline);
9576 		break;
9577 	    }
9578 
9579 	    /* Increase indent inside "if", "while", and "try", decrease
9580 	     * at "end". */
9581 	    if (indent > 2 && STRNCMP(p, "end", 3) == 0)
9582 		indent -= 2;
9583 	    else if (STRNCMP(p, "if", 2) == 0 || STRNCMP(p, "wh", 2) == 0
9584 		    || STRNCMP(p, "try", 3) == 0)
9585 		indent += 2;
9586 
9587 	    /* Check for defining a function inside this function. */
9588 	    if (STRNCMP(p, "fu", 2) == 0)
9589 	    {
9590 		p = skipwhite(skiptowhite(p));
9591 		p += eval_fname_script(p);
9592 		if (ASCII_ISALPHA(*p))
9593 		{
9594 		    vim_free(trans_function_name(&p, TRUE, FALSE));
9595 		    if (*skipwhite(p) == '(')
9596 		    {
9597 			++nesting;
9598 			indent += 2;
9599 		    }
9600 		}
9601 	    }
9602 
9603 	    /* Check for ":append" or ":insert". */
9604 	    p = skip_range(p, NULL);
9605 	    if ((p[0] == 'a' && (!ASCII_ISALPHA(p[1]) || p[1] == 'p'))
9606 		    || (p[0] == 'i'
9607 			&& (!ASCII_ISALPHA(p[1]) || (p[1] == 'n'
9608 				&& (!ASCII_ISALPHA(p[2]) || (p[2] == 's'))))))
9609 		skip_until = vim_strsave((char_u *)".");
9610 
9611 	    /* Check for ":python <<EOF", ":tcl <<EOF", etc. */
9612 	    arg = skipwhite(skiptowhite(p));
9613 	    if (arg[0] == '<' && arg[1] =='<'
9614 		    && ((p[0] == 'p' && p[1] == 'y'
9615 				    && (!ASCII_ISALPHA(p[2]) || p[2] == 't'))
9616 			|| (p[0] == 'p' && p[1] == 'e'
9617 				    && (!ASCII_ISALPHA(p[2]) || p[2] == 'r'))
9618 			|| (p[0] == 't' && p[1] == 'c'
9619 				    && (!ASCII_ISALPHA(p[2]) || p[2] == 'l'))
9620 			|| (p[0] == 'r' && p[1] == 'u' && p[2] == 'b'
9621 				    && (!ASCII_ISALPHA(p[3]) || p[3] == 'y'))
9622 			|| (p[0] == 'm' && p[1] == 'z'
9623 				    && (!ASCII_ISALPHA(p[2]) || p[2] == 's'))
9624 			))
9625 	    {
9626 		/* ":python <<" continues until a dot, like ":append" */
9627 		p = skipwhite(arg + 2);
9628 		if (*p == NUL)
9629 		    skip_until = vim_strsave((char_u *)".");
9630 		else
9631 		    skip_until = vim_strsave(p);
9632 	    }
9633 	}
9634 
9635 	/* Add the line to the function. */
9636 	if (ga_grow(&newlines, 1) == FAIL)
9637 	    goto erret;
9638 	((char_u **)(newlines.ga_data))[newlines.ga_len] = theline;
9639 	newlines.ga_len++;
9640 	newlines.ga_room--;
9641     }
9642 
9643     /* Don't define the function when skipping commands or when an error was
9644      * detected. */
9645     if (eap->skip || did_emsg)
9646 	goto erret;
9647 
9648     /*
9649      * If there are no errors, add the function
9650      */
9651     fp = find_func(name);
9652     if (fp != NULL)
9653     {
9654 	if (!eap->forceit)
9655 	{
9656 	    EMSG2(_(e_funcexts), name);
9657 	    goto erret;
9658 	}
9659 	if (fp->calls)
9660 	{
9661 	    EMSG2(_("E127: Cannot redefine function %s: It is in use"), name);
9662 	    goto erret;
9663 	}
9664 	/* redefine existing function */
9665 	ga_clear_strings(&(fp->args));
9666 	ga_clear_strings(&(fp->lines));
9667 	vim_free(name);
9668     }
9669     else
9670     {
9671 	fp = (ufunc_T *)alloc((unsigned)sizeof(ufunc_T));
9672 	if (fp == NULL)
9673 	    goto erret;
9674 	/* insert the new function in the function list */
9675 	fp->next = firstfunc;
9676 	firstfunc = fp;
9677 	fp->name = name;
9678     }
9679     fp->args = newargs;
9680     fp->lines = newlines;
9681     fp->varargs = varargs;
9682     fp->flags = flags;
9683     fp->calls = 0;
9684     fp->script_ID = current_SID;
9685 #ifdef FEAT_MAGIC_BRACES
9686     did_emsg |= saved_did_emsg;
9687 #endif
9688     vim_free(skip_until);
9689     return;
9690 
9691 erret:
9692     vim_free(skip_until);
9693     ga_clear_strings(&newargs);
9694     ga_clear_strings(&newlines);
9695 erret_name:
9696     vim_free(name);
9697 #ifdef FEAT_MAGIC_BRACES
9698     did_emsg |= saved_did_emsg;
9699 #endif
9700 }
9701 
9702 /*
9703  * Get a function name, translating "<SID>" and "<SNR>".
9704  * Returns the function name in allocated memory, or NULL for failure.
9705  * Advances "pp" to just after the function name (if no error).
9706  */
9707     static char_u *
9708 trans_function_name(pp, skip, internal)
9709     char_u	**pp;
9710     int		skip;		/* only find the end, don't evaluate */
9711     int		internal;	/* TRUE if internal function name OK */
9712 {
9713     char_u	*name;
9714     char_u	*start;
9715     char_u	*end;
9716     int		lead;
9717     char_u	sid_buf[20];
9718     char_u	*temp_string = NULL;
9719     char_u	*expr_start, *expr_end;
9720     int		len;
9721 
9722     /* A name starting with "<SID>" or "<SNR>" is local to a script. */
9723     start = *pp;
9724     lead = eval_fname_script(start);
9725     if (lead > 0)
9726 	start += lead;
9727     end = find_name_end(start, &expr_start, &expr_end);
9728     if (end == start)
9729     {
9730 	if (!skip)
9731 	    EMSG(_("E129: Function name required"));
9732 	return NULL;
9733     }
9734 #ifdef FEAT_MAGIC_BRACES
9735     if (expr_start != NULL && !skip)
9736     {
9737 	/* expand magic curlies */
9738 	temp_string = make_expanded_name(start, expr_start, expr_end, end);
9739 	if (temp_string == NULL)
9740 	{
9741 	    /*
9742 	     * Report an invalid expression in braces, unless the expression
9743 	     * evaluation has been cancelled due to an aborting error, an
9744 	     * interrupt, or an exception.
9745 	     */
9746 	    if (!aborting())
9747 		EMSG2(_(e_invarg2), start);
9748 	    else
9749 		*pp = end;
9750 	    return NULL;
9751 	}
9752 	start = temp_string;
9753 	len = (int)STRLEN(temp_string);
9754     }
9755     else
9756 #endif
9757 	len = (int)(end - start);
9758 
9759     /*
9760      * Copy the function name to allocated memory.
9761      * Accept <SID>name() inside a script, translate into <SNR>123_name().
9762      * Accept <SNR>123_name() outside a script.
9763      */
9764     if (skip)
9765 	lead = 0;	/* do nothing */
9766     else if (lead > 0)
9767     {
9768 	lead = 3;
9769 	if (eval_fname_sid(*pp))	/* If it's "<SID>" */
9770 	{
9771 	    if (current_SID <= 0)
9772 	    {
9773 		EMSG(_(e_usingsid));
9774 		return NULL;
9775 	    }
9776 	    sprintf((char *)sid_buf, "%ld_", (long)current_SID);
9777 	    lead += (int)STRLEN(sid_buf);
9778 	}
9779     }
9780     else if (!internal && !ASCII_ISUPPER(*start))
9781     {
9782 	EMSG2(_("E128: Function name must start with a capital: %s"), start);
9783 	return NULL;
9784     }
9785     name = alloc((unsigned)(len + lead + 1));
9786     if (name != NULL)
9787     {
9788 	if (lead > 0)
9789 	{
9790 	    name[0] = K_SPECIAL;
9791 	    name[1] = KS_EXTRA;
9792 	    name[2] = (int)KE_SNR;
9793 	    if (eval_fname_sid(*pp))	/* If it's "<SID>" */
9794 		STRCPY(name + 3, sid_buf);
9795 	}
9796 	mch_memmove(name + lead, start, (size_t)len);
9797 	name[len + lead] = NUL;
9798     }
9799     *pp = end;
9800 
9801     vim_free(temp_string);
9802     return name;
9803 }
9804 
9805 /*
9806  * Return 5 if "p" starts with "<SID>" or "<SNR>" (ignoring case).
9807  * Return 2 if "p" starts with "s:".
9808  * Return 0 otherwise.
9809  */
9810     static int
9811 eval_fname_script(p)
9812     char_u	*p;
9813 {
9814     if (p[0] == '<' && (STRNICMP(p + 1, "SID>", 4) == 0
9815 					  || STRNICMP(p + 1, "SNR>", 4) == 0))
9816 	return 5;
9817     if (p[0] == 's' && p[1] == ':')
9818 	return 2;
9819     return 0;
9820 }
9821 
9822 /*
9823  * Return TRUE if "p" starts with "<SID>" or "s:".
9824  * Only works if eval_fname_script() returned non-zero for "p"!
9825  */
9826     static int
9827 eval_fname_sid(p)
9828     char_u	*p;
9829 {
9830     return (*p == 's' || TOUPPER_ASC(p[2]) == 'I');
9831 }
9832 
9833 /*
9834  * List the head of the function: "name(arg1, arg2)".
9835  */
9836     static void
9837 list_func_head(fp, indent)
9838     ufunc_T	*fp;
9839     int		indent;
9840 {
9841     int		j;
9842 
9843     msg_start();
9844     if (indent)
9845 	MSG_PUTS("   ");
9846     MSG_PUTS("function ");
9847     if (fp->name[0] == K_SPECIAL)
9848     {
9849 	MSG_PUTS_ATTR("<SNR>", hl_attr(HLF_8));
9850 	msg_puts(fp->name + 3);
9851     }
9852     else
9853 	msg_puts(fp->name);
9854     msg_putchar('(');
9855     for (j = 0; j < fp->args.ga_len; ++j)
9856     {
9857 	if (j)
9858 	    MSG_PUTS(", ");
9859 	msg_puts(FUNCARG(fp, j));
9860     }
9861     if (fp->varargs)
9862     {
9863 	if (j)
9864 	    MSG_PUTS(", ");
9865 	MSG_PUTS("...");
9866     }
9867     msg_putchar(')');
9868 }
9869 
9870 /*
9871  * Find a function by name, return pointer to it in ufuncs.
9872  * Return NULL for unknown function.
9873  */
9874     static ufunc_T *
9875 find_func(name)
9876     char_u	*name;
9877 {
9878     ufunc_T	*fp;
9879 
9880     for (fp = firstfunc; fp != NULL; fp = fp->next)
9881 	if (STRCMP(name, fp->name) == 0)
9882 	    break;
9883     return fp;
9884 }
9885 
9886 #if defined(FEAT_CMDL_COMPL) || defined(PROTO)
9887 
9888 /*
9889  * Function given to ExpandGeneric() to obtain the list of user defined
9890  * function names.
9891  */
9892     char_u *
9893 get_user_func_name(xp, idx)
9894     expand_T	*xp;
9895     int		idx;
9896 {
9897     static ufunc_T *fp = NULL;
9898 
9899     if (idx == 0)
9900 	fp = firstfunc;
9901     if (fp != NULL)
9902     {
9903 	if (STRLEN(fp->name) + 4 >= IOSIZE)
9904 	    return fp->name;	/* prevents overflow */
9905 
9906 	cat_func_name(IObuff, fp);
9907 	if (xp->xp_context != EXPAND_USER_FUNC)
9908 	{
9909 	    STRCAT(IObuff, "(");
9910 	    if (!fp->varargs && fp->args.ga_len == 0)
9911 		STRCAT(IObuff, ")");
9912 	}
9913 
9914 	fp = fp->next;
9915 	return IObuff;
9916     }
9917     return NULL;
9918 }
9919 
9920 #endif /* FEAT_CMDL_COMPL */
9921 
9922 /*
9923  * Copy the function name of "fp" to buffer "buf".
9924  * "buf" must be able to hold the function name plus three bytes.
9925  * Takes care of script-local function names.
9926  */
9927     static void
9928 cat_func_name(buf, fp)
9929     char_u	*buf;
9930     ufunc_T	*fp;
9931 {
9932     if (fp->name[0] == K_SPECIAL)
9933     {
9934 	STRCPY(buf, "<SNR>");
9935 	STRCAT(buf, fp->name + 3);
9936     }
9937     else
9938 	STRCPY(buf, fp->name);
9939 }
9940 
9941 /*
9942  * ":delfunction {name}"
9943  */
9944     void
9945 ex_delfunction(eap)
9946     exarg_T	*eap;
9947 {
9948     ufunc_T	*fp = NULL, *pfp;
9949     char_u	*p;
9950     char_u	*name;
9951 
9952     p = eap->arg;
9953     name = trans_function_name(&p, eap->skip, FALSE);
9954     if (name == NULL)
9955 	return;
9956     if (!ends_excmd(*skipwhite(p)))
9957     {
9958 	vim_free(name);
9959 	EMSG(_(e_trailing));
9960 	return;
9961     }
9962     eap->nextcmd = check_nextcmd(p);
9963     if (eap->nextcmd != NULL)
9964 	*p = NUL;
9965 
9966     if (!eap->skip)
9967 	fp = find_func(name);
9968     vim_free(name);
9969 
9970     if (!eap->skip)
9971     {
9972 	if (fp == NULL)
9973 	{
9974 	    EMSG2(_("E130: Undefined function: %s"), eap->arg);
9975 	    return;
9976 	}
9977 	if (fp->calls)
9978 	{
9979 	    EMSG2(_("E131: Cannot delete function %s: It is in use"), eap->arg);
9980 	    return;
9981 	}
9982 
9983 	/* clear this function */
9984 	vim_free(fp->name);
9985 	ga_clear_strings(&(fp->args));
9986 	ga_clear_strings(&(fp->lines));
9987 
9988 	/* remove the function from the function list */
9989 	if (firstfunc == fp)
9990 	    firstfunc = fp->next;
9991 	else
9992 	{
9993 	    for (pfp = firstfunc; pfp != NULL; pfp = pfp->next)
9994 		if (pfp->next == fp)
9995 		{
9996 		    pfp->next = fp->next;
9997 		    break;
9998 		}
9999 	}
10000 	vim_free(fp);
10001     }
10002 }
10003 
10004 /*
10005  * Call a user function.
10006  */
10007     static void
10008 call_user_func(fp, argcount, argvars, retvar, firstline, lastline)
10009     ufunc_T	*fp;		/* pointer to function */
10010     int		argcount;	/* nr of args */
10011     VAR		argvars;	/* arguments */
10012     VAR		retvar;		/* return value */
10013     linenr_T	firstline;	/* first line of range */
10014     linenr_T	lastline;	/* last line of range */
10015 {
10016     char_u		*save_sourcing_name;
10017     linenr_T		save_sourcing_lnum;
10018     scid_T		save_current_SID;
10019     struct funccall	fc;
10020     struct funccall	*save_fcp = current_funccal;
10021     int			save_did_emsg;
10022     static int		depth = 0;
10023 
10024     /* If depth of calling is getting too high, don't execute the function */
10025     if (depth >= p_mfd)
10026     {
10027 	EMSG(_("E132: Function call depth is higher than 'maxfuncdepth'"));
10028 	retvar->var_type = VAR_NUMBER;
10029 	retvar->var_val.var_number = -1;
10030 	return;
10031     }
10032     ++depth;
10033 
10034     line_breakcheck();		/* check for CTRL-C hit */
10035 
10036     /* set local variables */
10037     var_init(&fc.l_vars);
10038     fc.func = fp;
10039     fc.argcount = argcount;
10040     fc.argvars = argvars;
10041     fc.retvar = retvar;
10042     retvar->var_val.var_number = 0;
10043     fc.linenr = 0;
10044     fc.returned = FALSE;
10045     fc.level = ex_nesting_level;
10046     fc.a0_var.var_type = VAR_NUMBER;
10047     fc.a0_var.var_val.var_number = argcount - fp->args.ga_len;
10048     fc.a0_var.var_name = NULL;
10049     current_funccal = &fc;
10050     fc.firstline.var_type = VAR_NUMBER;
10051     fc.firstline.var_val.var_number = firstline;
10052     fc.firstline.var_name = NULL;
10053     fc.lastline.var_type = VAR_NUMBER;
10054     fc.lastline.var_val.var_number = lastline;
10055     fc.lastline.var_name = NULL;
10056     /* Check if this function has a breakpoint. */
10057     fc.breakpoint = dbg_find_breakpoint(FALSE, fp->name, (linenr_T)0);
10058     fc.dbg_tick = debug_tick;
10059 
10060     /* Don't redraw while executing the function. */
10061     ++RedrawingDisabled;
10062     save_sourcing_name = sourcing_name;
10063     save_sourcing_lnum = sourcing_lnum;
10064     sourcing_lnum = 1;
10065     sourcing_name = alloc((unsigned)((save_sourcing_name == NULL ? 0
10066 		: STRLEN(save_sourcing_name)) + STRLEN(fp->name) + 13));
10067     if (sourcing_name != NULL)
10068     {
10069 	if (save_sourcing_name != NULL
10070 			  && STRNCMP(save_sourcing_name, "function ", 9) == 0)
10071 	    sprintf((char *)sourcing_name, "%s..", save_sourcing_name);
10072 	else
10073 	    STRCPY(sourcing_name, "function ");
10074 	cat_func_name(sourcing_name + STRLEN(sourcing_name), fp);
10075 
10076 	if (p_verbose >= 12)
10077 	{
10078 	    ++no_wait_return;
10079 	    msg_scroll = TRUE;	    /* always scroll up, don't overwrite */
10080 	    msg_str((char_u *)_("calling %s"), sourcing_name);
10081 	    if (p_verbose >= 14)
10082 	    {
10083 		int	i;
10084 		char_u	buf[MSG_BUF_LEN];
10085 
10086 		msg_puts((char_u *)"(");
10087 		for (i = 0; i < argcount; ++i)
10088 		{
10089 		    if (i > 0)
10090 			msg_puts((char_u *)", ");
10091 		    if (argvars[i].var_type == VAR_NUMBER)
10092 			msg_outnum((long)argvars[i].var_val.var_number);
10093 		    else
10094 		    {
10095 			trunc_string(get_var_string(&argvars[i]),
10096 							    buf, MSG_BUF_LEN);
10097 			msg_puts((char_u *)"\"");
10098 			msg_puts(buf);
10099 			msg_puts((char_u *)"\"");
10100 		    }
10101 		}
10102 		msg_puts((char_u *)")");
10103 	    }
10104 	    msg_puts((char_u *)"\n");   /* don't overwrite this either */
10105 	    cmdline_row = msg_row;
10106 	    --no_wait_return;
10107 	}
10108     }
10109     save_current_SID = current_SID;
10110     current_SID = fp->script_ID;
10111     save_did_emsg = did_emsg;
10112     did_emsg = FALSE;
10113 
10114     /* call do_cmdline() to execute the lines */
10115     do_cmdline(NULL, get_func_line, (void *)&fc,
10116 				     DOCMD_NOWAIT|DOCMD_VERBOSE|DOCMD_REPEAT);
10117 
10118     --RedrawingDisabled;
10119 
10120     /* when the function was aborted because of an error, return -1 */
10121     if ((did_emsg && (fp->flags & FC_ABORT)) || retvar->var_type == VAR_UNKNOWN)
10122     {
10123 	clear_var(retvar);
10124 	retvar->var_type = VAR_NUMBER;
10125 	retvar->var_val.var_number = -1;
10126     }
10127 
10128     /* when being verbose, mention the return value */
10129     if (p_verbose >= 12)
10130     {
10131 	char_u	*sn, *val;
10132 
10133 	++no_wait_return;
10134 	msg_scroll = TRUE;	    /* always scroll up, don't overwrite */
10135 
10136 	/* Make sure the output fits in IObuff. */
10137 	sn = sourcing_name;
10138 	if (STRLEN(sourcing_name) > IOSIZE / 2 - 50)
10139 	    sn = sourcing_name + STRLEN(sourcing_name) - (IOSIZE / 2 - 50);
10140 
10141 	if (aborting())
10142 	    smsg((char_u *)_("%s aborted"), sn);
10143 	else if (fc.retvar->var_type == VAR_NUMBER)
10144 	    smsg((char_u *)_("%s returning #%ld"), sn,
10145 				       (long)fc.retvar->var_val.var_number);
10146 	else if (fc.retvar->var_type == VAR_STRING)
10147 	{
10148 	    val = get_var_string(fc.retvar);
10149 	    if (STRLEN(val) > IOSIZE / 2 - 50)
10150 		val = val + STRLEN(val) - (IOSIZE / 2 - 50);
10151 	    smsg((char_u *)_("%s returning \"%s\""), sn, val);
10152 	}
10153 	msg_puts((char_u *)"\n");   /* don't overwrite this either */
10154 	cmdline_row = msg_row;
10155 	--no_wait_return;
10156     }
10157 
10158     vim_free(sourcing_name);
10159     sourcing_name = save_sourcing_name;
10160     sourcing_lnum = save_sourcing_lnum;
10161     current_SID = save_current_SID;
10162 
10163     if (p_verbose >= 12 && sourcing_name != NULL)
10164     {
10165 	++no_wait_return;
10166 	msg_scroll = TRUE;	    /* always scroll up, don't overwrite */
10167 	msg_str((char_u *)_("continuing in %s"), sourcing_name);
10168 	msg_puts((char_u *)"\n");   /* don't overwrite this either */
10169 	cmdline_row = msg_row;
10170 	--no_wait_return;
10171     }
10172 
10173     did_emsg |= save_did_emsg;
10174     current_funccal = save_fcp;
10175 
10176     var_clear(&fc.l_vars);		/* free all local variables */
10177     --depth;
10178 }
10179 
10180 /*
10181  * ":return [expr]"
10182  */
10183     void
10184 ex_return(eap)
10185     exarg_T	*eap;
10186 {
10187     char_u	*arg = eap->arg;
10188     var		retvar;
10189     int		returning = FALSE;
10190 
10191     if (current_funccal == NULL)
10192     {
10193 	EMSG(_("E133: :return not inside a function"));
10194 	return;
10195     }
10196 
10197     if (eap->skip)
10198 	++emsg_skip;
10199 
10200     eap->nextcmd = NULL;
10201     if ((*arg != NUL && *arg != '|' && *arg != '\n')
10202 	    && eval0(arg, &retvar, &eap->nextcmd, !eap->skip) != FAIL)
10203     {
10204 	if (!eap->skip)
10205 	    returning = do_return(eap, FALSE, TRUE, &retvar);
10206 	else
10207 	    clear_var(&retvar);
10208     }
10209     /* It's safer to return also on error. */
10210     else if (!eap->skip)
10211     {
10212 	/*
10213 	 * Return unless the expression evaluation has been cancelled due to an
10214 	 * aborting error, an interrupt, or an exception.
10215 	 */
10216 	if (!aborting())
10217 	    returning = do_return(eap, FALSE, TRUE, NULL);
10218     }
10219 
10220     /* When skipping or the return gets pending, advance to the next command
10221      * in this line (!returning).  Otherwise, ignore the rest of the line.
10222      * Following lines will be ignored by get_func_line(). */
10223     if (returning)
10224 	eap->nextcmd = NULL;
10225     else if (eap->nextcmd == NULL)	    /* no argument */
10226 	eap->nextcmd = check_nextcmd(arg);
10227 
10228     if (eap->skip)
10229 	--emsg_skip;
10230 }
10231 
10232 /*
10233  * Return from a function.  Possibly makes the return pending.  Also called
10234  * for a pending return at the ":endtry" or after returning from an extra
10235  * do_cmdline().  "reanimate" is used in the latter case.  "is_cmd" is set
10236  * when called due to a ":return" command.  "value" may point to a variable
10237  * with the return value.  Returns TRUE when the return can be carried out,
10238  * FALSE when the return gets pending.
10239  */
10240     int
10241 do_return(eap, reanimate, is_cmd, value)
10242     exarg_T	*eap;
10243     int		reanimate;
10244     int		is_cmd;
10245     void	*value;
10246 {
10247     int		idx;
10248     struct condstack *cstack = eap->cstack;
10249 
10250     if (reanimate)
10251 	/* Undo the return. */
10252 	current_funccal->returned = FALSE;
10253 
10254     /*
10255      * Cleanup (and inactivate) conditionals, but stop when a try conditional
10256      * not in its finally clause (which then is to be executed next) is found.
10257      * In this case, make the ":return" pending for execution at the ":endtry".
10258      * Otherwise, return normally.
10259      */
10260     idx = cleanup_conditionals(eap->cstack, 0, TRUE);
10261     if (idx >= 0)
10262     {
10263 	cstack->cs_pending[idx] = CSTP_RETURN;
10264 
10265 	if (!is_cmd && !reanimate)
10266 	    /* A pending return again gets pending.  "value" points to an
10267 	     * allocated variable with the value of the original ":return"'s
10268 	     * argument if present or is NULL else. */
10269 	    cstack->cs_retvar[idx] = value;
10270 	else
10271 	{
10272 	    /* When undoing a return in order to make it pending, get the stored
10273 	     * return value. */
10274 	    if (reanimate)
10275 		value = current_funccal->retvar;
10276 
10277 	    if (value != NULL)
10278 	    {
10279 		/* Store the value of the pending return. */
10280 		if ((cstack->cs_retvar[idx] = alloc_var()) != NULL)
10281 		    *(VAR)cstack->cs_retvar[idx] = *(VAR)value;
10282 		else
10283 		    EMSG(_(e_outofmem));
10284 	    }
10285 	    else
10286 		cstack->cs_retvar[idx] = NULL;
10287 
10288 	    if (reanimate)
10289 	    {
10290 		/* The pending return value could be overwritten by a ":return"
10291 		 * without argument in a finally clause; reset the default
10292 		 * return value. */
10293 		current_funccal->retvar->var_type = VAR_NUMBER;
10294 		current_funccal->retvar->var_val.var_number = 0;
10295 	    }
10296 	}
10297 	report_make_pending(CSTP_RETURN, value);
10298     }
10299     else
10300     {
10301 	current_funccal->returned = TRUE;
10302 
10303 	/* If the return is carried out now, store the return value.  For
10304 	 * a return immediately after reanimation, the value is already
10305 	 * there. */
10306 	if (!reanimate && value != NULL)
10307 	{
10308 	    clear_var(current_funccal->retvar);
10309 	    *current_funccal->retvar = *(VAR)value;
10310 	    if (!is_cmd)
10311 		vim_free(value);
10312 	}
10313     }
10314 
10315     return idx < 0;
10316 }
10317 
10318 /*
10319  * Free the variable with a pending return value.
10320  */
10321     void
10322 discard_pending_return(retvar)
10323     void	*retvar;
10324 {
10325     /* The variable was copied from one with an undefined var_name.  So we can't
10326      * use free_var() to clear and free it. */
10327     clear_var((VAR)retvar);
10328     vim_free(retvar);
10329 }
10330 
10331 /*
10332  * Generate a return command for producing the value of "retvar".  The result
10333  * is an allocated string.  Used by report_pending() for verbose messages.
10334  */
10335     char_u *
10336 get_return_cmd(retvar)
10337     void	*retvar;
10338 {
10339     char_u	*s = IObuff;
10340 
10341     if (retvar == NULL || ((VAR)retvar)->var_type == VAR_UNKNOWN)
10342 	s = (char_u *)":return";
10343     else if (((VAR)retvar)->var_type == VAR_STRING)
10344 	sprintf((char *)IObuff, ":return \"%s\"",
10345 		((VAR)retvar)->var_val.var_string);
10346     else
10347 	sprintf((char *)IObuff, ":return %ld",
10348 		(long)(((VAR)retvar)->var_val.var_number));
10349     return vim_strsave(s);
10350 }
10351 
10352 /*
10353  * Get next function line.
10354  * Called by do_cmdline() to get the next line.
10355  * Returns allocated string, or NULL for end of function.
10356  */
10357 /* ARGSUSED */
10358     char_u *
10359 get_func_line(c, cookie, indent)
10360     int	    c;		    /* not used */
10361     void    *cookie;
10362     int	    indent;	    /* not used */
10363 {
10364     struct funccall	*fcp = (struct funccall *)cookie;
10365     char_u		*retval;
10366     garray_T		*gap;  /* growarray with function lines */
10367 
10368     /* If breakpoints have been added/deleted need to check for it. */
10369     if (fcp->dbg_tick != debug_tick)
10370     {
10371 	fcp->breakpoint = dbg_find_breakpoint(FALSE, fcp->func->name,
10372 							       sourcing_lnum);
10373 	fcp->dbg_tick = debug_tick;
10374     }
10375 
10376     gap = &fcp->func->lines;
10377     if ((fcp->func->flags & FC_ABORT) && did_emsg && !aborted_in_try())
10378 	retval = NULL;
10379     else if (fcp->returned || fcp->linenr >= gap->ga_len)
10380 	retval = NULL;
10381     else
10382     {
10383 	retval = vim_strsave(((char_u **)(gap->ga_data))[fcp->linenr++]);
10384 	sourcing_lnum = fcp->linenr;
10385     }
10386 
10387     /* Did we encounter a breakpoint? */
10388     if (fcp->breakpoint != 0 && fcp->breakpoint <= sourcing_lnum)
10389     {
10390 	dbg_breakpoint(fcp->func->name, sourcing_lnum);
10391 	/* Find next breakpoint. */
10392 	fcp->breakpoint = dbg_find_breakpoint(FALSE, fcp->func->name,
10393 							       sourcing_lnum);
10394 	fcp->dbg_tick = debug_tick;
10395     }
10396 
10397     return retval;
10398 }
10399 
10400 /*
10401  * Return TRUE if the currently active function should be ended, because a
10402  * return was encountered or an error occured.  Used inside a ":while".
10403  */
10404     int
10405 func_has_ended(cookie)
10406     void    *cookie;
10407 {
10408     struct funccall  *fcp = (struct funccall *)cookie;
10409 
10410     /* Ignore the "abort" flag if the abortion behavior has been changed due to
10411      * an error inside a try conditional. */
10412     return (((fcp->func->flags & FC_ABORT) && did_emsg && !aborted_in_try())
10413 	    || fcp->returned);
10414 }
10415 
10416 /*
10417  * return TRUE if cookie indicates a function which "abort"s on errors.
10418  */
10419     int
10420 func_has_abort(cookie)
10421     void    *cookie;
10422 {
10423     return ((struct funccall *)cookie)->func->flags & FC_ABORT;
10424 }
10425 
10426 #if defined(FEAT_VIMINFO) || defined(FEAT_SESSION)
10427 typedef enum
10428 {
10429     VAR_FLAVOUR_DEFAULT,
10430     VAR_FLAVOUR_SESSION,
10431     VAR_FLAVOUR_VIMINFO
10432 } var_flavour_T;
10433 
10434 static var_flavour_T var_flavour __ARGS((char_u *varname));
10435 
10436     static var_flavour_T
10437 var_flavour(varname)
10438     char_u *varname;
10439 {
10440     char_u *p = varname;
10441 
10442     if (ASCII_ISUPPER(*p))
10443     {
10444 	while (*(++p))
10445 	    if (ASCII_ISLOWER(*p))
10446 		return VAR_FLAVOUR_SESSION;
10447 	return VAR_FLAVOUR_VIMINFO;
10448     }
10449     else
10450 	return VAR_FLAVOUR_DEFAULT;
10451 }
10452 #endif
10453 
10454 #if defined(FEAT_VIMINFO) || defined(PROTO)
10455 /*
10456  * Restore global vars that start with a capital from the viminfo file
10457  */
10458     int
10459 read_viminfo_varlist(virp, writing)
10460     vir_T	*virp;
10461     int		writing;
10462 {
10463     char_u	*tab;
10464     int		is_string = FALSE;
10465     VAR		varp = NULL;
10466     char_u	*val;
10467 
10468     if (!writing && (find_viminfo_parameter('!') != NULL))
10469     {
10470 	tab = vim_strchr(virp->vir_line + 1, '\t');
10471 	if (tab != NULL)
10472 	{
10473 	    *tab++ = '\0';	/* isolate the variable name */
10474 	    if (*tab == 'S')	/* string var */
10475 		is_string = TRUE;
10476 
10477 	    tab = vim_strchr(tab, '\t');
10478 	    if (tab != NULL)
10479 	    {
10480 		/* create a nameless variable to hold the value */
10481 		if (is_string)
10482 		{
10483 		    val = viminfo_readstring(virp,
10484 				       (int)(tab - virp->vir_line + 1), TRUE);
10485 		    if (val != NULL)
10486 			varp = alloc_string_var(val);
10487 		}
10488 		else
10489 		{
10490 		    varp = alloc_var();
10491 		    if (varp != NULL)
10492 		    {
10493 			varp->var_type = VAR_NUMBER;
10494 			varp->var_val.var_number = atol((char *)tab + 1);
10495 		    }
10496 		}
10497 		/* assign the value to the variable */
10498 		if (varp != NULL)
10499 		{
10500 		    set_var(virp->vir_line + 1, varp);
10501 		    free_var(varp);
10502 		}
10503 	    }
10504 	}
10505     }
10506 
10507     return viminfo_readline(virp);
10508 }
10509 
10510 /*
10511  * Write global vars that start with a capital to the viminfo file
10512  */
10513     void
10514 write_viminfo_varlist(fp)
10515     FILE    *fp;
10516 {
10517     garray_T	*gap = &variables;		/* global variable */
10518     VAR		this_var;
10519     int		i;
10520 
10521     if (find_viminfo_parameter('!') == NULL)
10522 	return;
10523 
10524     fprintf(fp, _("\n# global variables:\n"));
10525     for (i = gap->ga_len; --i >= 0; )
10526     {
10527 	this_var = &VAR_GAP_ENTRY(i, gap);
10528 	if (this_var->var_name != NULL
10529 		&& var_flavour(this_var->var_name) == VAR_FLAVOUR_VIMINFO)
10530 	{
10531 	    fprintf(fp, "!%s\t%s\t", this_var->var_name,
10532 			  (this_var->var_type == VAR_STRING) ? "STR" : "NUM");
10533 	    viminfo_writestring(fp, get_var_string(this_var));
10534 	}
10535     }
10536 }
10537 #endif
10538 
10539 #if defined(FEAT_SESSION) || defined(PROTO)
10540     int
10541 store_session_globals(fd)
10542     FILE	*fd;
10543 {
10544     garray_T	*gap = &variables;		/* global variable */
10545     VAR		this_var;
10546     int		i;
10547     char_u	*p, *t;
10548 
10549     for (i = gap->ga_len; --i >= 0; )
10550     {
10551 	this_var = &VAR_GAP_ENTRY(i, gap);
10552 	if (this_var->var_name != NULL)
10553 	{
10554 	    if (var_flavour(this_var->var_name) == VAR_FLAVOUR_SESSION)
10555 	    {
10556 		/* Escapse special characters with a backslash.  Turn a LF and
10557 		 * CR into \n and \r. */
10558 		p = vim_strsave_escaped(get_var_string(this_var),
10559 							(char_u *)"\\\"\n\r");
10560 		if (p == NULL)	    /* out of memory */
10561 		    continue;
10562 		for (t = p; *t != NUL; ++t)
10563 		    if (*t == '\n')
10564 			*t = 'n';
10565 		    else if (*t == '\r')
10566 			*t = 'r';
10567 		if ((fprintf(fd, "let %s = %c%s%c",
10568 			    this_var->var_name,
10569 			    (this_var->var_type == VAR_STRING) ? '"' : ' ',
10570 			    p,
10571 			    (this_var->var_type == VAR_STRING) ? '"' : ' ') < 0)
10572 			|| put_eol(fd) == FAIL)
10573 		{
10574 		    vim_free(p);
10575 		    return FAIL;
10576 		}
10577 		vim_free(p);
10578 	    }
10579 
10580 	}
10581     }
10582     return OK;
10583 }
10584 #endif
10585 
10586 #endif /* FEAT_EVAL */
10587 
10588 #if defined(FEAT_MODIFY_FNAME) || defined(FEAT_EVAL) || defined(PROTO)
10589 
10590 
10591 #ifdef WIN3264
10592 /*
10593  * Functions for ":8" filename modifier: get 8.3 version of a filename.
10594  */
10595 static int get_short_pathname __ARGS((char_u **fnamep, char_u **bufp, int *fnamelen));
10596 static int shortpath_for_invalid_fname __ARGS((char_u **fname, char_u **bufp, int *fnamelen));
10597 static int shortpath_for_partial __ARGS((char_u **fnamep, char_u **bufp, int *fnamelen));
10598 
10599 /*
10600  * Get the short pathname of a file.
10601  * Returns 1 on success. *fnamelen is 0 for nonexistant path.
10602  */
10603     static int
10604 get_short_pathname(fnamep, bufp, fnamelen)
10605     char_u	**fnamep;
10606     char_u	**bufp;
10607     int		*fnamelen;
10608 {
10609     int		l,len;
10610     char_u	*newbuf;
10611 
10612     len = *fnamelen;
10613 
10614     l = GetShortPathName(*fnamep, *fnamep, len);
10615     if (l > len - 1)
10616     {
10617 	/* If that doesn't work (not enough space), then save the string
10618 	 * and try again with a new buffer big enough
10619 	 */
10620 	newbuf = vim_strnsave(*fnamep, l);
10621 	if (newbuf == NULL)
10622 	    return 0;
10623 
10624 	vim_free(*bufp);
10625 	*fnamep = *bufp = newbuf;
10626 
10627 	l = GetShortPathName(*fnamep,*fnamep,l+1);
10628 
10629 	/* Really should always succeed, as the buffer is big enough */
10630     }
10631 
10632     *fnamelen = l;
10633     return 1;
10634 }
10635 
10636 /*
10637  * Create a short path name.  Returns the length of the buffer it needs.
10638  * Doesn't copy over the end of the buffer passed in.
10639  */
10640     static int
10641 shortpath_for_invalid_fname(fname, bufp, fnamelen)
10642     char_u	**fname;
10643     char_u	**bufp;
10644     int		*fnamelen;
10645 {
10646     char_u	*s, *p, *pbuf2, *pbuf3;
10647     char_u	ch;
10648     int		l,len,len2,plen,slen;
10649 
10650     /* Make a copy */
10651     len2 = *fnamelen;
10652     pbuf2 = vim_strnsave(*fname, len2);
10653     pbuf3 = NULL;
10654 
10655     s = pbuf2 + len2 - 1; /* Find the end */
10656     slen = 1;
10657     plen = len2;
10658 
10659     l = 0;
10660     if (vim_ispathsep(*s))
10661     {
10662 	--s;
10663 	++slen;
10664 	--plen;
10665     }
10666 
10667     do
10668     {
10669 	/* Go back one path-seperator */
10670 	while (s > pbuf2 && !vim_ispathsep(*s))
10671 	{
10672 	    --s;
10673 	    ++slen;
10674 	    --plen;
10675 	}
10676 	if (s <= pbuf2)
10677 	    break;
10678 
10679 	/* Remeber the character that is about to be blatted */
10680 	ch = *s;
10681 	*s = 0; /* get_short_pathname requires a null-terminated string */
10682 
10683 	/* Try it in situ */
10684 	p = pbuf2;
10685 	if (!get_short_pathname(&p, &pbuf3, &plen))
10686 	{
10687 	    vim_free(pbuf2);
10688 	    return -1;
10689 	}
10690 	*s = ch;    /* Preserve the string */
10691     } while (plen == 0);
10692 
10693     if (plen > 0)
10694     {
10695 	/* Remeber the length of the new string.  */
10696 	*fnamelen = len = plen + slen;
10697 	vim_free(*bufp);
10698 	if (len > len2)
10699 	{
10700 	    /* If there's not enough space in the currently allocated string,
10701 	     * then copy it to a buffer big enough.
10702 	     */
10703 	    *fname= *bufp = vim_strnsave(p, len);
10704 	    if (*fname == NULL)
10705 		return -1;
10706 	}
10707 	else
10708 	{
10709 	    /* Transfer pbuf2 to being the main buffer  (it's big enough) */
10710 	    *fname = *bufp = pbuf2;
10711 	    if (p != pbuf2)
10712 		strncpy(*fname, p, plen);
10713 	    pbuf2 = NULL;
10714 	}
10715 	/* Concat the next bit */
10716 	strncpy(*fname + plen, s, slen);
10717 	(*fname)[len] = '\0';
10718     }
10719     vim_free(pbuf3);
10720     vim_free(pbuf2);
10721     return 0;
10722 }
10723 
10724 /*
10725  * Get a pathname for a partial path.
10726  */
10727     static int
10728 shortpath_for_partial(fnamep, bufp, fnamelen)
10729     char_u	**fnamep;
10730     char_u	**bufp;
10731     int		*fnamelen;
10732 {
10733     int		sepcount, len, tflen;
10734     char_u	*p;
10735     char_u	*pbuf, *tfname;
10736     int		hasTilde;
10737 
10738     /* Count up the path seperators from the RHS.. so we know which part
10739      * of the path to return.
10740      */
10741     sepcount = 0;
10742     for (p = *fnamep + *fnamelen - 1; p >= *fnamep; --p)
10743 	if (vim_ispathsep(*p))
10744 	    ++sepcount;
10745 
10746     /* Need full path first (use expand_env() to remove a "~/") */
10747     hasTilde = (**fnamep == '~');
10748     if (hasTilde)
10749 	pbuf = tfname = expand_env_save(*fnamep);
10750     else
10751 	pbuf = tfname = FullName_save(*fnamep, FALSE);
10752 
10753     len = tflen = STRLEN(tfname);
10754 
10755     if (!get_short_pathname(&tfname, &pbuf, &len))
10756 	return -1;
10757 
10758     if (len == 0)
10759     {
10760 	/* Don't have a valid filename, so shorten the rest of the
10761 	 * path if we can. This CAN give us invalid 8.3 filenames, but
10762 	 * there's not a lot of point in guessing what it might be.
10763 	 */
10764 	len = tflen;
10765 	if (shortpath_for_invalid_fname(&tfname, &pbuf, &len) == -1)
10766 	    return -1;
10767     }
10768 
10769     /* Count the paths backward to find the beginning of the desired string. */
10770     for (p = tfname + len - 1; p >= tfname; --p)
10771 	if (vim_ispathsep(*p))
10772 	{
10773 	    if (sepcount == 0 || (hasTilde && sepcount == 1))
10774 		break;
10775 	    else
10776 		sepcount --;
10777 	}
10778     if (hasTilde)
10779     {
10780 	--p;
10781 	if (p >= tfname)
10782 	    *p = '~';
10783 	else
10784 	    return -1;
10785     }
10786     else
10787 	++p;
10788 
10789     /* Copy in the string - p indexes into tfname - allocated at pbuf */
10790     vim_free(*bufp);
10791     *fnamelen = (int)STRLEN(p);
10792     *bufp = pbuf;
10793     *fnamep = p;
10794 
10795     return 0;
10796 }
10797 #endif /* WIN3264 */
10798 
10799 /*
10800  * Adjust a filename, according to a string of modifiers.
10801  * *fnamep must be NUL terminated when called.  When returning, the length is
10802  * determined by *fnamelen.
10803  * Returns valid flags.
10804  * When there is an error, *fnamep is set to NULL.
10805  */
10806     int
10807 modify_fname(src, usedlen, fnamep, bufp, fnamelen)
10808     char_u	*src;		/* string with modifiers */
10809     int		*usedlen;	/* characters after src that are used */
10810     char_u	**fnamep;	/* file name so far */
10811     char_u	**bufp;		/* buffer for allocated file name or NULL */
10812     int		*fnamelen;	/* length of fnamep */
10813 {
10814     int		valid = 0;
10815     char_u	*tail;
10816     char_u	*s, *p, *pbuf;
10817     char_u	dirname[MAXPATHL];
10818     int		c;
10819     int		has_fullname = 0;
10820 #ifdef WIN3264
10821     int		has_shortname = 0;
10822 #endif
10823 
10824 repeat:
10825     /* ":p" - full path/file_name */
10826     if (src[*usedlen] == ':' && src[*usedlen + 1] == 'p')
10827     {
10828 	has_fullname = 1;
10829 
10830 	valid |= VALID_PATH;
10831 	*usedlen += 2;
10832 
10833 	/* Expand "~/path" for all systems and "~user/path" for Unix and VMS */
10834 	if ((*fnamep)[0] == '~'
10835 #if !defined(UNIX) && !(defined(VMS) && defined(USER_HOME))
10836 		&& ((*fnamep)[1] == '/'
10837 # ifdef BACKSLASH_IN_FILENAME
10838 		    || (*fnamep)[1] == '\\'
10839 # endif
10840 		    || (*fnamep)[1] == NUL)
10841 
10842 #endif
10843 	   )
10844 	{
10845 	    *fnamep = expand_env_save(*fnamep);
10846 	    vim_free(*bufp);	/* free any allocated file name */
10847 	    *bufp = *fnamep;
10848 	    if (*fnamep == NULL)
10849 		return -1;
10850 	}
10851 
10852 	/* When "/." or "/.." is used: force expansion to get rid of it. */
10853 	for (p = *fnamep; *p != NUL; ++p)
10854 	{
10855 	    if (vim_ispathsep(*p)
10856 		    && p[1] == '.'
10857 		    && (p[2] == NUL
10858 			|| vim_ispathsep(p[2])
10859 			|| (p[2] == '.'
10860 			    && (p[3] == NUL || vim_ispathsep(p[3])))))
10861 		break;
10862 	}
10863 
10864 	/* FullName_save() is slow, don't use it when not needed. */
10865 	if (*p != NUL || !vim_isAbsName(*fnamep))
10866 	{
10867 	    *fnamep = FullName_save(*fnamep, *p != NUL);
10868 	    vim_free(*bufp);	/* free any allocated file name */
10869 	    *bufp = *fnamep;
10870 	    if (*fnamep == NULL)
10871 		return -1;
10872 	}
10873 
10874 	/* Append a path separator to a directory. */
10875 	if (mch_isdir(*fnamep))
10876 	{
10877 	    /* Make room for one or two extra characters. */
10878 	    *fnamep = vim_strnsave(*fnamep, (int)STRLEN(*fnamep) + 2);
10879 	    vim_free(*bufp);	/* free any allocated file name */
10880 	    *bufp = *fnamep;
10881 	    if (*fnamep == NULL)
10882 		return -1;
10883 	    add_pathsep(*fnamep);
10884 	}
10885     }
10886 
10887     /* ":." - path relative to the current directory */
10888     /* ":~" - path relative to the home directory */
10889     /* ":8" - shortname path - postponed till after */
10890     while (src[*usedlen] == ':'
10891 		  && ((c = src[*usedlen + 1]) == '.' || c == '~' || c == '8'))
10892     {
10893 	*usedlen += 2;
10894 	if (c == '8')
10895 	{
10896 #ifdef WIN3264
10897 	    has_shortname = 1; /* Postpone this. */
10898 #endif
10899 	    continue;
10900 	}
10901 	pbuf = NULL;
10902 	/* Need full path first (use expand_env() to remove a "~/") */
10903 	if (!has_fullname)
10904 	{
10905 	    if (c == '.' && **fnamep == '~')
10906 		p = pbuf = expand_env_save(*fnamep);
10907 	    else
10908 		p = pbuf = FullName_save(*fnamep, FALSE);
10909 	}
10910 	else
10911 	    p = *fnamep;
10912 
10913 	has_fullname = 0;
10914 
10915 	if (p != NULL)
10916 	{
10917 	    if (c == '.')
10918 	    {
10919 		mch_dirname(dirname, MAXPATHL);
10920 		s = shorten_fname(p, dirname);
10921 		if (s != NULL)
10922 		{
10923 		    *fnamep = s;
10924 		    if (pbuf != NULL)
10925 		    {
10926 			vim_free(*bufp);   /* free any allocated file name */
10927 			*bufp = pbuf;
10928 			pbuf = NULL;
10929 		    }
10930 		}
10931 	    }
10932 	    else
10933 	    {
10934 		home_replace(NULL, p, dirname, MAXPATHL, TRUE);
10935 		/* Only replace it when it starts with '~' */
10936 		if (*dirname == '~')
10937 		{
10938 		    s = vim_strsave(dirname);
10939 		    if (s != NULL)
10940 		    {
10941 			*fnamep = s;
10942 			vim_free(*bufp);
10943 			*bufp = s;
10944 		    }
10945 		}
10946 	    }
10947 	    vim_free(pbuf);
10948 	}
10949     }
10950 
10951     tail = gettail(*fnamep);
10952     *fnamelen = (int)STRLEN(*fnamep);
10953 
10954     /* ":h" - head, remove "/file_name", can be repeated  */
10955     /* Don't remove the first "/" or "c:\" */
10956     while (src[*usedlen] == ':' && src[*usedlen + 1] == 'h')
10957     {
10958 	valid |= VALID_HEAD;
10959 	*usedlen += 2;
10960 	s = get_past_head(*fnamep);
10961 	while (tail > s && vim_ispathsep(tail[-1]))
10962 	    --tail;
10963 	*fnamelen = (int)(tail - *fnamep);
10964 #ifdef VMS
10965 	if (*fnamelen > 0)
10966 	    *fnamelen += 1; /* the path separator is part of the path */
10967 #endif
10968 	while (tail > s && !vim_ispathsep(tail[-1]))
10969 	    --tail;
10970     }
10971 
10972     /* ":8" - shortname  */
10973     if (src[*usedlen] == ':' && src[*usedlen + 1] == '8')
10974     {
10975 	*usedlen += 2;
10976 #ifdef WIN3264
10977 	has_shortname = 1;
10978 #endif
10979     }
10980 
10981 #ifdef WIN3264
10982     /* Check shortname after we have done 'heads' and before we do 'tails'
10983      */
10984     if (has_shortname)
10985     {
10986 	pbuf = NULL;
10987 	/* Copy the string if it is shortened by :h */
10988 	if (*fnamelen < (int)STRLEN(*fnamep))
10989 	{
10990 	    p = vim_strnsave(*fnamep, *fnamelen);
10991 	    if (p == 0)
10992 		return -1;
10993 	    vim_free(*bufp);
10994 	    *bufp = *fnamep = p;
10995 	}
10996 
10997 	/* Split into two implementations - makes it easier.  First is where
10998 	 * there isn't a full name already, second is where there is.
10999 	 */
11000 	if (!has_fullname && !vim_isAbsName(*fnamep))
11001 	{
11002 	    if (shortpath_for_partial(fnamep, bufp, fnamelen) == -1)
11003 		return -1;
11004 	}
11005 	else
11006 	{
11007 	    int		l;
11008 
11009 	    /* Simple case, already have the full-name
11010 	     * Nearly always shorter, so try first time. */
11011 	    l = *fnamelen;
11012 	    if (!get_short_pathname(fnamep, bufp, &l))
11013 		return -1;
11014 
11015 	    if (l == 0)
11016 	    {
11017 		/* Couldn't find the filename.. search the paths.
11018 		 */
11019 		l = *fnamelen;
11020 		if (shortpath_for_invalid_fname(fnamep, bufp, &l ) == -1)
11021 		    return -1;
11022 	    }
11023 	    *fnamelen = l;
11024 	}
11025     }
11026 #endif /* WIN3264 */
11027 
11028     /* ":t" - tail, just the basename */
11029     if (src[*usedlen] == ':' && src[*usedlen + 1] == 't')
11030     {
11031 	*usedlen += 2;
11032 	*fnamelen -= (int)(tail - *fnamep);
11033 	*fnamep = tail;
11034     }
11035 
11036     /* ":e" - extension, can be repeated */
11037     /* ":r" - root, without extension, can be repeated */
11038     while (src[*usedlen] == ':'
11039 	    && (src[*usedlen + 1] == 'e' || src[*usedlen + 1] == 'r'))
11040     {
11041 	/* find a '.' in the tail:
11042 	 * - for second :e: before the current fname
11043 	 * - otherwise: The last '.'
11044 	 */
11045 	if (src[*usedlen + 1] == 'e' && *fnamep > tail)
11046 	    s = *fnamep - 2;
11047 	else
11048 	    s = *fnamep + *fnamelen - 1;
11049 	for ( ; s > tail; --s)
11050 	    if (s[0] == '.')
11051 		break;
11052 	if (src[*usedlen + 1] == 'e')		/* :e */
11053 	{
11054 	    if (s > tail)
11055 	    {
11056 		*fnamelen += (int)(*fnamep - (s + 1));
11057 		*fnamep = s + 1;
11058 #ifdef VMS
11059 		/* cut version from the extension */
11060 		s = *fnamep + *fnamelen - 1;
11061 		for ( ; s > *fnamep; --s)
11062 		    if (s[0] == ';')
11063 			break;
11064 		if (s > *fnamep)
11065 		    *fnamelen = s - *fnamep;
11066 #endif
11067 	    }
11068 	    else if (*fnamep <= tail)
11069 		*fnamelen = 0;
11070 	}
11071 	else				/* :r */
11072 	{
11073 	    if (s > tail)	/* remove one extension */
11074 		*fnamelen = (int)(s - *fnamep);
11075 	}
11076 	*usedlen += 2;
11077     }
11078 
11079     /* ":s?pat?foo?" - substitute */
11080     /* ":gs?pat?foo?" - global substitute */
11081     if (src[*usedlen] == ':'
11082 	    && (src[*usedlen + 1] == 's'
11083 		|| (src[*usedlen + 1] == 'g' && src[*usedlen + 2] == 's')))
11084     {
11085 	char_u	    *str;
11086 	char_u	    *pat;
11087 	char_u	    *sub;
11088 	int	    sep;
11089 	char_u	    *flags;
11090 	int	    didit = FALSE;
11091 
11092 	flags = (char_u *)"";
11093 	s = src + *usedlen + 2;
11094 	if (src[*usedlen + 1] == 'g')
11095 	{
11096 	    flags = (char_u *)"g";
11097 	    ++s;
11098 	}
11099 
11100 	sep = *s++;
11101 	if (sep)
11102 	{
11103 	    /* find end of pattern */
11104 	    p = vim_strchr(s, sep);
11105 	    if (p != NULL)
11106 	    {
11107 		pat = vim_strnsave(s, (int)(p - s));
11108 		if (pat != NULL)
11109 		{
11110 		    s = p + 1;
11111 		    /* find end of substitution */
11112 		    p = vim_strchr(s, sep);
11113 		    if (p != NULL)
11114 		    {
11115 			sub = vim_strnsave(s, (int)(p - s));
11116 			str = vim_strnsave(*fnamep, *fnamelen);
11117 			if (sub != NULL && str != NULL)
11118 			{
11119 			    *usedlen = (int)(p + 1 - src);
11120 			    s = do_string_sub(str, pat, sub, flags);
11121 			    if (s != NULL)
11122 			    {
11123 				*fnamep = s;
11124 				*fnamelen = (int)STRLEN(s);
11125 				vim_free(*bufp);
11126 				*bufp = s;
11127 				didit = TRUE;
11128 			    }
11129 			}
11130 			vim_free(sub);
11131 			vim_free(str);
11132 		    }
11133 		    vim_free(pat);
11134 		}
11135 	    }
11136 	    /* after using ":s", repeat all the modifiers */
11137 	    if (didit)
11138 		goto repeat;
11139 	}
11140     }
11141 
11142     return valid;
11143 }
11144 
11145 /*
11146  * Perform a substitution on "str" with pattern "pat" and substitute "sub".
11147  * "flags" can be "g" to do a global substitute.
11148  * Returns an allocated string, NULL for error.
11149  */
11150     char_u *
11151 do_string_sub(str, pat, sub, flags)
11152     char_u	*str;
11153     char_u	*pat;
11154     char_u	*sub;
11155     char_u	*flags;
11156 {
11157     int		sublen;
11158     regmatch_T	regmatch;
11159     int		i;
11160     int		do_all;
11161     char_u	*tail;
11162     garray_T	ga;
11163     char_u	*ret;
11164     char_u	*save_cpo;
11165 
11166     /* Make 'cpoptions' empty, so that the 'l' flag doesn't work here */
11167     save_cpo = p_cpo;
11168     p_cpo = (char_u *)"";
11169 
11170     ga_init2(&ga, 1, 200);
11171 
11172     do_all = (flags[0] == 'g');
11173 
11174     regmatch.rm_ic = p_ic;
11175     regmatch.regprog = vim_regcomp(pat, RE_MAGIC + RE_STRING);
11176     if (regmatch.regprog != NULL)
11177     {
11178 	tail = str;
11179 	while (vim_regexec_nl(&regmatch, str, (colnr_T)(tail - str)))
11180 	{
11181 	    /*
11182 	     * Get some space for a temporary buffer to do the substitution
11183 	     * into.  It will contain:
11184 	     * - The text up to where the match is.
11185 	     * - The substituted text.
11186 	     * - The text after the match.
11187 	     */
11188 	    sublen = vim_regsub(&regmatch, sub, tail, FALSE, TRUE, FALSE);
11189 	    if (ga_grow(&ga, (int)(STRLEN(tail) + sublen -
11190 			    (regmatch.endp[0] - regmatch.startp[0]))) == FAIL)
11191 	    {
11192 		ga_clear(&ga);
11193 		break;
11194 	    }
11195 
11196 	    /* copy the text up to where the match is */
11197 	    i = (int)(regmatch.startp[0] - tail);
11198 	    mch_memmove((char_u *)ga.ga_data + ga.ga_len, tail, (size_t)i);
11199 	    /* add the substituted text */
11200 	    (void)vim_regsub(&regmatch, sub, (char_u *)ga.ga_data
11201 					  + ga.ga_len + i, TRUE, TRUE, FALSE);
11202 	    ga.ga_len += i + sublen - 1;
11203 	    ga.ga_room -= i + sublen - 1;
11204 	    /* avoid getting stuck on a match with an empty string */
11205 	    if (tail == regmatch.endp[0])
11206 	    {
11207 		if (*tail == NUL)
11208 		    break;
11209 		*((char_u *)ga.ga_data + ga.ga_len) = *tail++;
11210 		++ga.ga_len;
11211 		--ga.ga_room;
11212 	    }
11213 	    else
11214 	    {
11215 		tail = regmatch.endp[0];
11216 		if (*tail == NUL)
11217 		    break;
11218 	    }
11219 	    if (!do_all)
11220 		break;
11221 	}
11222 
11223 	if (ga.ga_data != NULL)
11224 	    STRCPY((char *)ga.ga_data + ga.ga_len, tail);
11225 
11226 	vim_free(regmatch.regprog);
11227     }
11228 
11229     ret = vim_strsave(ga.ga_data == NULL ? str : (char_u *)ga.ga_data);
11230     ga_clear(&ga);
11231     p_cpo = save_cpo;
11232 
11233     return ret;
11234 }
11235 
11236 #endif /* defined(FEAT_MODIFY_FNAME) || defined(FEAT_EVAL) */
11237