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