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