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