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