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