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