blob: faa097229c4d312b7207d9418fcf8f9c1315413d [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
Bram Moolenaar325b7a22004-07-05 15:58:32 +00004990#ifdef FEAT_MZSCHEME
4991 "mzscheme",
4992#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004993#ifdef FEAT_OLE
4994 "ole",
4995#endif
4996#ifdef FEAT_OSFILETYPE
4997 "osfiletype",
4998#endif
4999#ifdef FEAT_PATH_EXTRA
5000 "path_extra",
5001#endif
5002#ifdef FEAT_PERL
5003#ifndef DYNAMIC_PERL
5004 "perl",
5005#endif
5006#endif
5007#ifdef FEAT_PYTHON
5008#ifndef DYNAMIC_PYTHON
5009 "python",
5010#endif
5011#endif
5012#ifdef FEAT_POSTSCRIPT
5013 "postscript",
5014#endif
5015#ifdef FEAT_PRINTER
5016 "printer",
5017#endif
5018#ifdef FEAT_QUICKFIX
5019 "quickfix",
5020#endif
5021#ifdef FEAT_RIGHTLEFT
5022 "rightleft",
5023#endif
5024#if defined(FEAT_RUBY) && !defined(DYNAMIC_RUBY)
5025 "ruby",
5026#endif
5027#ifdef FEAT_SCROLLBIND
5028 "scrollbind",
5029#endif
5030#ifdef FEAT_CMDL_INFO
5031 "showcmd",
5032 "cmdline_info",
5033#endif
5034#ifdef FEAT_SIGNS
5035 "signs",
5036#endif
5037#ifdef FEAT_SMARTINDENT
5038 "smartindent",
5039#endif
5040#ifdef FEAT_SNIFF
5041 "sniff",
5042#endif
5043#ifdef FEAT_STL_OPT
5044 "statusline",
5045#endif
5046#ifdef FEAT_SUN_WORKSHOP
5047 "sun_workshop",
5048#endif
5049#ifdef FEAT_NETBEANS_INTG
5050 "netbeans_intg",
5051#endif
5052#ifdef FEAT_SYN_HL
5053 "syntax",
5054#endif
5055#if defined(USE_SYSTEM) || !defined(UNIX)
5056 "system",
5057#endif
5058#ifdef FEAT_TAG_BINS
5059 "tag_binary",
5060#endif
5061#ifdef FEAT_TAG_OLDSTATIC
5062 "tag_old_static",
5063#endif
5064#ifdef FEAT_TAG_ANYWHITE
5065 "tag_any_white",
5066#endif
5067#ifdef FEAT_TCL
5068# ifndef DYNAMIC_TCL
5069 "tcl",
5070# endif
5071#endif
5072#ifdef TERMINFO
5073 "terminfo",
5074#endif
5075#ifdef FEAT_TERMRESPONSE
5076 "termresponse",
5077#endif
5078#ifdef FEAT_TEXTOBJ
5079 "textobjects",
5080#endif
5081#ifdef HAVE_TGETENT
5082 "tgetent",
5083#endif
5084#ifdef FEAT_TITLE
5085 "title",
5086#endif
5087#ifdef FEAT_TOOLBAR
5088 "toolbar",
5089#endif
5090#ifdef FEAT_USR_CMDS
5091 "user-commands", /* was accidentally included in 5.4 */
5092 "user_commands",
5093#endif
5094#ifdef FEAT_VIMINFO
5095 "viminfo",
5096#endif
5097#ifdef FEAT_VERTSPLIT
5098 "vertsplit",
5099#endif
5100#ifdef FEAT_VIRTUALEDIT
5101 "virtualedit",
5102#endif
5103#ifdef FEAT_VISUAL
5104 "visual",
5105#endif
5106#ifdef FEAT_VISUALEXTRA
5107 "visualextra",
5108#endif
5109#ifdef FEAT_VREPLACE
5110 "vreplace",
5111#endif
5112#ifdef FEAT_WILDIGN
5113 "wildignore",
5114#endif
5115#ifdef FEAT_WILDMENU
5116 "wildmenu",
5117#endif
5118#ifdef FEAT_WINDOWS
5119 "windows",
5120#endif
5121#ifdef FEAT_WAK
5122 "winaltkeys",
5123#endif
5124#ifdef FEAT_WRITEBACKUP
5125 "writebackup",
5126#endif
5127#ifdef FEAT_XIM
5128 "xim",
5129#endif
5130#ifdef FEAT_XFONTSET
5131 "xfontset",
5132#endif
5133#ifdef USE_XSMP
5134 "xsmp",
5135#endif
5136#ifdef USE_XSMP_INTERACT
5137 "xsmp_interact",
5138#endif
5139#ifdef FEAT_XCLIPBOARD
5140 "xterm_clipboard",
5141#endif
5142#ifdef FEAT_XTERM_SAVE
5143 "xterm_save",
5144#endif
5145#if defined(UNIX) && defined(FEAT_X11)
5146 "X11",
5147#endif
5148 NULL
5149 };
5150
5151 name = get_var_string(&argvars[0]);
5152 for (i = 0; has_list[i] != NULL; ++i)
5153 if (STRICMP(name, has_list[i]) == 0)
5154 {
5155 n = TRUE;
5156 break;
5157 }
5158
5159 if (n == FALSE)
5160 {
5161 if (STRNICMP(name, "patch", 5) == 0)
5162 n = has_patch(atoi((char *)name + 5));
5163 else if (STRICMP(name, "vim_starting") == 0)
5164 n = (starting != 0);
5165#ifdef DYNAMIC_TCL
5166 else if (STRICMP(name, "tcl") == 0)
5167 n = tcl_enabled(FALSE);
5168#endif
5169#if defined(USE_ICONV) && defined(DYNAMIC_ICONV)
5170 else if (STRICMP(name, "iconv") == 0)
5171 n = iconv_enabled(FALSE);
5172#endif
5173#ifdef DYNAMIC_RUBY
5174 else if (STRICMP(name, "ruby") == 0)
5175 n = ruby_enabled(FALSE);
5176#endif
5177#ifdef DYNAMIC_PYTHON
5178 else if (STRICMP(name, "python") == 0)
5179 n = python_enabled(FALSE);
5180#endif
5181#ifdef DYNAMIC_PERL
5182 else if (STRICMP(name, "perl") == 0)
5183 n = perl_enabled(FALSE);
5184#endif
5185#ifdef FEAT_GUI
5186 else if (STRICMP(name, "gui_running") == 0)
5187 n = (gui.in_use || gui.starting);
5188# ifdef FEAT_GUI_W32
5189 else if (STRICMP(name, "gui_win32s") == 0)
5190 n = gui_is_win32s();
5191# endif
5192# ifdef FEAT_BROWSE
5193 else if (STRICMP(name, "browse") == 0)
5194 n = gui.in_use; /* gui_mch_browse() works when GUI is running */
5195# endif
5196#endif
5197#ifdef FEAT_SYN_HL
5198 else if (STRICMP(name, "syntax_items") == 0)
5199 n = syntax_present(curbuf);
5200#endif
5201#if defined(WIN3264)
5202 else if (STRICMP(name, "win95") == 0)
5203 n = mch_windows95();
5204#endif
5205 }
5206
5207 retvar->var_val.var_number = n;
5208}
5209
5210/*
5211 * "hasmapto()" function
5212 */
5213 static void
5214f_hasmapto(argvars, retvar)
5215 VAR argvars;
5216 VAR retvar;
5217{
5218 char_u *name;
5219 char_u *mode;
5220 char_u buf[NUMBUFLEN];
5221
5222 name = get_var_string(&argvars[0]);
5223 if (argvars[1].var_type == VAR_UNKNOWN)
5224 mode = (char_u *)"nvo";
5225 else
5226 mode = get_var_string_buf(&argvars[1], buf);
5227
5228 if (map_to_exists(name, mode))
5229 retvar->var_val.var_number = TRUE;
5230 else
5231 retvar->var_val.var_number = FALSE;
5232}
5233
5234/*
5235 * "histadd()" function
5236 */
5237/*ARGSUSED*/
5238 static void
5239f_histadd(argvars, retvar)
5240 VAR argvars;
5241 VAR retvar;
5242{
5243#ifdef FEAT_CMDHIST
5244 int histype;
5245 char_u *str;
5246 char_u buf[NUMBUFLEN];
5247#endif
5248
5249 retvar->var_val.var_number = FALSE;
5250 if (check_restricted() || check_secure())
5251 return;
5252#ifdef FEAT_CMDHIST
5253 histype = get_histtype(get_var_string(&argvars[0]));
5254 if (histype >= 0)
5255 {
5256 str = get_var_string_buf(&argvars[1], buf);
5257 if (*str != NUL)
5258 {
5259 add_to_history(histype, str, FALSE, NUL);
5260 retvar->var_val.var_number = TRUE;
5261 return;
5262 }
5263 }
5264#endif
5265}
5266
5267/*
5268 * "histdel()" function
5269 */
5270/*ARGSUSED*/
5271 static void
5272f_histdel(argvars, retvar)
5273 VAR argvars;
5274 VAR retvar;
5275{
5276#ifdef FEAT_CMDHIST
5277 int n;
5278 char_u buf[NUMBUFLEN];
5279
5280 if (argvars[1].var_type == VAR_UNKNOWN)
5281 /* only one argument: clear entire history */
5282 n = clr_history(get_histtype(get_var_string(&argvars[0])));
5283 else if (argvars[1].var_type == VAR_NUMBER)
5284 /* index given: remove that entry */
5285 n = del_history_idx(get_histtype(get_var_string(&argvars[0])),
5286 (int)get_var_number(&argvars[1]));
5287 else
5288 /* string given: remove all matching entries */
5289 n = del_history_entry(get_histtype(get_var_string(&argvars[0])),
5290 get_var_string_buf(&argvars[1], buf));
5291 retvar->var_val.var_number = n;
5292#else
5293 retvar->var_val.var_number = 0;
5294#endif
5295}
5296
5297/*
5298 * "histget()" function
5299 */
5300/*ARGSUSED*/
5301 static void
5302f_histget(argvars, retvar)
5303 VAR argvars;
5304 VAR retvar;
5305{
5306#ifdef FEAT_CMDHIST
5307 int type;
5308 int idx;
5309
5310 type = get_histtype(get_var_string(&argvars[0]));
5311 if (argvars[1].var_type == VAR_UNKNOWN)
5312 idx = get_history_idx(type);
5313 else
5314 idx = (int)get_var_number(&argvars[1]);
5315 retvar->var_val.var_string = vim_strsave(get_history_entry(type, idx));
5316#else
5317 retvar->var_val.var_string = NULL;
5318#endif
5319 retvar->var_type = VAR_STRING;
5320}
5321
5322/*
5323 * "histnr()" function
5324 */
5325/*ARGSUSED*/
5326 static void
5327f_histnr(argvars, retvar)
5328 VAR argvars;
5329 VAR retvar;
5330{
5331 int i;
5332
5333#ifdef FEAT_CMDHIST
5334 i = get_histtype(get_var_string(&argvars[0]));
5335 if (i >= HIST_CMD && i < HIST_COUNT)
5336 i = get_history_idx(i);
5337 else
5338#endif
5339 i = -1;
5340 retvar->var_val.var_number = i;
5341}
5342
5343/*
5344 * "highlight_exists()" function
5345 */
5346 static void
5347f_hlexists(argvars, retvar)
5348 VAR argvars;
5349 VAR retvar;
5350{
5351 retvar->var_val.var_number = highlight_exists(get_var_string(&argvars[0]));
5352}
5353
5354/*
5355 * "highlightID(name)" function
5356 */
5357 static void
5358f_hlID(argvars, retvar)
5359 VAR argvars;
5360 VAR retvar;
5361{
5362 retvar->var_val.var_number = syn_name2id(get_var_string(&argvars[0]));
5363}
5364
5365/*
5366 * "hostname()" function
5367 */
5368/*ARGSUSED*/
5369 static void
5370f_hostname(argvars, retvar)
5371 VAR argvars;
5372 VAR retvar;
5373{
5374 char_u hostname[256];
5375
5376 mch_get_host_name(hostname, 256);
5377 retvar->var_type = VAR_STRING;
5378 retvar->var_val.var_string = vim_strsave(hostname);
5379}
5380
5381/*
5382 * iconv() function
5383 */
5384/*ARGSUSED*/
5385 static void
5386f_iconv(argvars, retvar)
5387 VAR argvars;
5388 VAR retvar;
5389{
5390#ifdef FEAT_MBYTE
5391 char_u buf1[NUMBUFLEN];
5392 char_u buf2[NUMBUFLEN];
5393 char_u *from, *to, *str;
5394 vimconv_T vimconv;
5395#endif
5396
5397 retvar->var_type = VAR_STRING;
5398 retvar->var_val.var_string = NULL;
5399
5400#ifdef FEAT_MBYTE
5401 str = get_var_string(&argvars[0]);
5402 from = enc_canonize(enc_skip(get_var_string_buf(&argvars[1], buf1)));
5403 to = enc_canonize(enc_skip(get_var_string_buf(&argvars[2], buf2)));
5404 vimconv.vc_type = CONV_NONE;
5405 convert_setup(&vimconv, from, to);
5406
5407 /* If the encodings are equal, no conversion needed. */
5408 if (vimconv.vc_type == CONV_NONE)
5409 retvar->var_val.var_string = vim_strsave(str);
5410 else
5411 retvar->var_val.var_string = string_convert(&vimconv, str, NULL);
5412
5413 convert_setup(&vimconv, NULL, NULL);
5414 vim_free(from);
5415 vim_free(to);
5416#endif
5417}
5418
5419/*
5420 * "indent()" function
5421 */
5422 static void
5423f_indent(argvars, retvar)
5424 VAR argvars;
5425 VAR retvar;
5426{
5427 linenr_T lnum;
5428
5429 lnum = get_var_lnum(argvars);
5430 if (lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count)
5431 retvar->var_val.var_number = get_indent_lnum(lnum);
5432 else
5433 retvar->var_val.var_number = -1;
5434}
5435
5436static int inputsecret_flag = 0;
5437
5438/*
5439 * "input()" function
5440 * Also handles inputsecret() when inputsecret is set.
5441 */
5442 static void
5443f_input(argvars, retvar)
5444 VAR argvars;
5445 VAR retvar;
5446{
5447 char_u *prompt = get_var_string(&argvars[0]);
5448 char_u *p = NULL;
5449 int c;
5450 char_u buf[NUMBUFLEN];
5451 int cmd_silent_save = cmd_silent;
5452
5453 retvar->var_type = VAR_STRING;
5454
5455#ifdef NO_CONSOLE_INPUT
5456 /* While starting up, there is no place to enter text. */
5457 if (no_console_input())
5458 {
5459 retvar->var_val.var_string = NULL;
5460 return;
5461 }
5462#endif
5463
5464 cmd_silent = FALSE; /* Want to see the prompt. */
5465 if (prompt != NULL)
5466 {
5467 /* Only the part of the message after the last NL is considered as
5468 * prompt for the command line */
5469 p = vim_strrchr(prompt, '\n');
5470 if (p == NULL)
5471 p = prompt;
5472 else
5473 {
5474 ++p;
5475 c = *p;
5476 *p = NUL;
5477 msg_start();
5478 msg_clr_eos();
5479 msg_puts_attr(prompt, echo_attr);
5480 msg_didout = FALSE;
5481 msg_starthere();
5482 *p = c;
5483 }
5484 cmdline_row = msg_row;
5485 }
5486
5487 if (argvars[1].var_type != VAR_UNKNOWN)
5488 stuffReadbuffSpec(get_var_string_buf(&argvars[1], buf));
5489
5490 retvar->var_val.var_string =
5491 getcmdline_prompt(inputsecret_flag ? NUL : '@', p, echo_attr);
5492
5493 /* since the user typed this, no need to wait for return */
5494 need_wait_return = FALSE;
5495 msg_didout = FALSE;
5496 cmd_silent = cmd_silent_save;
5497}
5498
5499/*
5500 * "inputdialog()" function
5501 */
5502 static void
5503f_inputdialog(argvars, retvar)
5504 VAR argvars;
5505 VAR retvar;
5506{
5507#if defined(FEAT_GUI_TEXTDIALOG)
5508 /* Use a GUI dialog if the GUI is running and 'c' is not in 'guioptions' */
5509 if (gui.in_use && vim_strchr(p_go, GO_CONDIALOG) == NULL)
5510 {
5511 char_u *message;
5512 char_u buf[NUMBUFLEN];
5513
5514 message = get_var_string(&argvars[0]);
5515 if (argvars[1].var_type != VAR_UNKNOWN)
5516 {
5517 STRNCPY(IObuff, get_var_string_buf(&argvars[1], buf), IOSIZE);
5518 IObuff[IOSIZE - 1] = NUL;
5519 }
5520 else
5521 IObuff[0] = NUL;
5522 if (do_dialog(VIM_QUESTION, NULL, message, (char_u *)_("&OK\n&Cancel"),
5523 1, IObuff) == 1)
5524 retvar->var_val.var_string = vim_strsave(IObuff);
5525 else
5526 {
5527 if (argvars[1].var_type != VAR_UNKNOWN
5528 && argvars[2].var_type != VAR_UNKNOWN)
5529 retvar->var_val.var_string = vim_strsave(
5530 get_var_string_buf(&argvars[2], buf));
5531 else
5532 retvar->var_val.var_string = NULL;
5533 }
5534 retvar->var_type = VAR_STRING;
5535 }
5536 else
5537#endif
5538 f_input(argvars, retvar);
5539}
5540
5541static garray_T ga_userinput = {0, 0, sizeof(tasave_T), 4, NULL};
5542
5543/*
5544 * "inputrestore()" function
5545 */
5546/*ARGSUSED*/
5547 static void
5548f_inputrestore(argvars, retvar)
5549 VAR argvars;
5550 VAR retvar;
5551{
5552 if (ga_userinput.ga_len > 0)
5553 {
5554 --ga_userinput.ga_len;
5555 ++ga_userinput.ga_room;
5556 restore_typeahead((tasave_T *)(ga_userinput.ga_data)
5557 + ga_userinput.ga_len);
5558 retvar->var_val.var_number = 0; /* OK */
5559 }
5560 else if (p_verbose > 1)
5561 {
5562 msg((char_u *)_("called inputrestore() more often than inputsave()"));
5563 retvar->var_val.var_number = 1; /* Failed */
5564 }
5565}
5566
5567/*
5568 * "inputsave()" function
5569 */
5570/*ARGSUSED*/
5571 static void
5572f_inputsave(argvars, retvar)
5573 VAR argvars;
5574 VAR retvar;
5575{
5576 /* Add an entry to the stack of typehead storage. */
5577 if (ga_grow(&ga_userinput, 1) == OK)
5578 {
5579 save_typeahead((tasave_T *)(ga_userinput.ga_data)
5580 + ga_userinput.ga_len);
5581 ++ga_userinput.ga_len;
5582 --ga_userinput.ga_room;
5583 retvar->var_val.var_number = 0; /* OK */
5584 }
5585 else
5586 retvar->var_val.var_number = 1; /* Failed */
5587}
5588
5589/*
5590 * "inputsecret()" function
5591 */
5592 static void
5593f_inputsecret(argvars, retvar)
5594 VAR argvars;
5595 VAR retvar;
5596{
5597 ++cmdline_star;
5598 ++inputsecret_flag;
5599 f_input(argvars, retvar);
5600 --cmdline_star;
5601 --inputsecret_flag;
5602}
5603
5604/*
5605 * "isdirectory()" function
5606 */
5607 static void
5608f_isdirectory(argvars, retvar)
5609 VAR argvars;
5610 VAR retvar;
5611{
5612 retvar->var_val.var_number = mch_isdir(get_var_string(&argvars[0]));
5613}
5614
5615/*
5616 * "last_buffer_nr()" function.
5617 */
5618/*ARGSUSED*/
5619 static void
5620f_last_buffer_nr(argvars, retvar)
5621 VAR argvars;
5622 VAR retvar;
5623{
5624 int n = 0;
5625 buf_T *buf;
5626
5627 for (buf = firstbuf; buf != NULL; buf = buf->b_next)
5628 if (n < buf->b_fnum)
5629 n = buf->b_fnum;
5630
5631 retvar->var_val.var_number = n;
5632}
5633
5634/*
5635 * "line(string)" function
5636 */
5637 static void
5638f_line(argvars, retvar)
5639 VAR argvars;
5640 VAR retvar;
5641{
5642 linenr_T lnum = 0;
5643 pos_T *fp;
5644
5645 fp = var2fpos(&argvars[0], TRUE);
5646 if (fp != NULL)
5647 lnum = fp->lnum;
5648 retvar->var_val.var_number = lnum;
5649}
5650
5651/*
5652 * "line2byte(lnum)" function
5653 */
5654/*ARGSUSED*/
5655 static void
5656f_line2byte(argvars, retvar)
5657 VAR argvars;
5658 VAR retvar;
5659{
5660#ifndef FEAT_BYTEOFF
5661 retvar->var_val.var_number = -1;
5662#else
5663 linenr_T lnum;
5664
5665 lnum = get_var_lnum(argvars);
5666 if (lnum < 1 || lnum > curbuf->b_ml.ml_line_count + 1)
5667 retvar->var_val.var_number = -1;
5668 else
5669 retvar->var_val.var_number = ml_find_line_or_offset(curbuf, lnum, NULL);
5670 if (retvar->var_val.var_number >= 0)
5671 ++retvar->var_val.var_number;
5672#endif
5673}
5674
5675/*
5676 * "lispindent(lnum)" function
5677 */
5678 static void
5679f_lispindent(argvars, retvar)
5680 VAR argvars;
5681 VAR retvar;
5682{
5683#ifdef FEAT_LISP
5684 pos_T pos;
5685 linenr_T lnum;
5686
5687 pos = curwin->w_cursor;
5688 lnum = get_var_lnum(argvars);
5689 if (lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count)
5690 {
5691 curwin->w_cursor.lnum = lnum;
5692 retvar->var_val.var_number = get_lisp_indent();
5693 curwin->w_cursor = pos;
5694 }
5695 else
5696#endif
5697 retvar->var_val.var_number = -1;
5698}
5699
5700/*
5701 * "localtime()" function
5702 */
5703/*ARGSUSED*/
5704 static void
5705f_localtime(argvars, retvar)
5706 VAR argvars;
5707 VAR retvar;
5708{
5709 retvar->var_val.var_number = (varnumber_T)time(NULL);
5710}
5711
5712/*
5713 * "maparg()" function
5714 */
5715 static void
5716f_maparg(argvars, retvar)
5717 VAR argvars;
5718 VAR retvar;
5719{
5720 get_maparg(argvars, retvar, TRUE);
5721}
5722
5723/*
5724 * "mapcheck()" function
5725 */
5726 static void
5727f_mapcheck(argvars, retvar)
5728 VAR argvars;
5729 VAR retvar;
5730{
5731 get_maparg(argvars, retvar, FALSE);
5732}
5733
5734 static void
5735get_maparg(argvars, retvar, exact)
5736 VAR argvars;
5737 VAR retvar;
5738 int exact;
5739{
5740 char_u *keys;
5741 char_u *which;
5742 char_u buf[NUMBUFLEN];
5743 char_u *keys_buf = NULL;
5744 char_u *rhs;
5745 int mode;
5746 garray_T ga;
5747
5748 /* return empty string for failure */
5749 retvar->var_type = VAR_STRING;
5750 retvar->var_val.var_string = NULL;
5751
5752 keys = get_var_string(&argvars[0]);
5753 if (*keys == NUL)
5754 return;
5755
5756 if (argvars[1].var_type != VAR_UNKNOWN)
5757 which = get_var_string_buf(&argvars[1], buf);
5758 else
5759 which = (char_u *)"";
5760 mode = get_map_mode(&which, 0);
5761
5762 keys = replace_termcodes(keys, &keys_buf, TRUE, TRUE);
5763 rhs = check_map(keys, mode, exact);
5764 vim_free(keys_buf);
5765 if (rhs != NULL)
5766 {
5767 ga_init(&ga);
5768 ga.ga_itemsize = 1;
5769 ga.ga_growsize = 40;
5770
5771 while (*rhs != NUL)
5772 ga_concat(&ga, str2special(&rhs, FALSE));
5773
5774 ga_append(&ga, NUL);
5775 retvar->var_val.var_string = (char_u *)ga.ga_data;
5776 }
5777}
5778
5779/*
5780 * "match()" function
5781 */
5782 static void
5783f_match(argvars, retvar)
5784 VAR argvars;
5785 VAR retvar;
5786{
5787 find_some_match(argvars, retvar, 1);
5788}
5789
5790/*
5791 * "matchend()" function
5792 */
5793 static void
5794f_matchend(argvars, retvar)
5795 VAR argvars;
5796 VAR retvar;
5797{
5798 find_some_match(argvars, retvar, 0);
5799}
5800
5801/*
5802 * "matchstr()" function
5803 */
5804 static void
5805f_matchstr(argvars, retvar)
5806 VAR argvars;
5807 VAR retvar;
5808{
5809 find_some_match(argvars, retvar, 2);
5810}
5811
5812 static void
5813find_some_match(argvars, retvar, type)
5814 VAR argvars;
5815 VAR retvar;
5816 int type;
5817{
5818 char_u *str;
5819 char_u *pat;
5820 regmatch_T regmatch;
5821 char_u patbuf[NUMBUFLEN];
5822 char_u *save_cpo;
5823 long start = 0;
5824
5825 /* Make 'cpoptions' empty, the 'l' flag should not be used here. */
5826 save_cpo = p_cpo;
5827 p_cpo = (char_u *)"";
5828
5829 str = get_var_string(&argvars[0]);
5830 pat = get_var_string_buf(&argvars[1], patbuf);
5831
5832 if (type == 2)
5833 {
5834 retvar->var_type = VAR_STRING;
5835 retvar->var_val.var_string = NULL;
5836 }
5837 else
5838 retvar->var_val.var_number = -1;
5839
5840 if (argvars[2].var_type != VAR_UNKNOWN)
5841 {
5842 start = get_var_number(&argvars[2]);
5843 if (start < 0)
5844 start = 0;
5845 if (start > (long)STRLEN(str))
5846 goto theend;
5847 str += start;
5848 }
5849
5850 regmatch.regprog = vim_regcomp(pat, RE_MAGIC + RE_STRING);
5851 if (regmatch.regprog != NULL)
5852 {
5853 regmatch.rm_ic = p_ic;
5854 if (vim_regexec_nl(&regmatch, str, (colnr_T)0))
5855 {
5856 if (type == 2)
5857 retvar->var_val.var_string = vim_strnsave(regmatch.startp[0],
5858 (int)(regmatch.endp[0] - regmatch.startp[0]));
5859 else
5860 {
5861 if (type != 0)
5862 retvar->var_val.var_number =
5863 (varnumber_T)(regmatch.startp[0] - str);
5864 else
5865 retvar->var_val.var_number =
5866 (varnumber_T)(regmatch.endp[0] - str);
5867 retvar->var_val.var_number += start;
5868 }
5869 }
5870 vim_free(regmatch.regprog);
5871 }
5872
5873theend:
5874 p_cpo = save_cpo;
5875}
5876
5877/*
5878 * "mode()" function
5879 */
5880/*ARGSUSED*/
5881 static void
5882f_mode(argvars, retvar)
5883 VAR argvars;
5884 VAR retvar;
5885{
5886 char_u buf[2];
5887
5888#ifdef FEAT_VISUAL
5889 if (VIsual_active)
5890 {
5891 if (VIsual_select)
5892 buf[0] = VIsual_mode + 's' - 'v';
5893 else
5894 buf[0] = VIsual_mode;
5895 }
5896 else
5897#endif
5898 if (State == HITRETURN || State == ASKMORE || State == SETWSIZE)
5899 buf[0] = 'r';
5900 else if (State & INSERT)
5901 {
5902 if (State & REPLACE_FLAG)
5903 buf[0] = 'R';
5904 else
5905 buf[0] = 'i';
5906 }
5907 else if (State & CMDLINE)
5908 buf[0] = 'c';
5909 else
5910 buf[0] = 'n';
5911
5912 buf[1] = NUL;
5913 retvar->var_val.var_string = vim_strsave(buf);
5914 retvar->var_type = VAR_STRING;
5915}
5916
5917/*
5918 * "nr2char()" function
5919 */
5920 static void
5921f_nr2char(argvars, retvar)
5922 VAR argvars;
5923 VAR retvar;
5924{
5925 char_u buf[NUMBUFLEN];
5926
5927#ifdef FEAT_MBYTE
5928 if (has_mbyte)
5929 buf[(*mb_char2bytes)((int)get_var_number(&argvars[0]), buf)] = NUL;
5930 else
5931#endif
5932 {
5933 buf[0] = (char_u)get_var_number(&argvars[0]);
5934 buf[1] = NUL;
5935 }
5936 retvar->var_type = VAR_STRING;
5937 retvar->var_val.var_string = vim_strsave(buf);
5938}
5939
5940/*
5941 * "rename({from}, {to})" function
5942 */
5943 static void
5944f_rename(argvars, retvar)
5945 VAR argvars;
5946 VAR retvar;
5947{
5948 char_u buf[NUMBUFLEN];
5949
5950 if (check_restricted() || check_secure())
5951 retvar->var_val.var_number = -1;
5952 else
5953 retvar->var_val.var_number = vim_rename(get_var_string(&argvars[0]),
5954 get_var_string_buf(&argvars[1], buf));
5955}
5956
5957/*
5958 * "resolve()" function
5959 */
5960 static void
5961f_resolve(argvars, retvar)
5962 VAR argvars;
5963 VAR retvar;
5964{
5965 char_u *p;
5966
5967 p = get_var_string(&argvars[0]);
5968#ifdef FEAT_SHORTCUT
5969 {
5970 char_u *v = NULL;
5971
5972 v = mch_resolve_shortcut(p);
5973 if (v != NULL)
5974 retvar->var_val.var_string = v;
5975 else
5976 retvar->var_val.var_string = vim_strsave(p);
5977 }
5978#else
5979# ifdef HAVE_READLINK
5980 {
5981 char_u buf[MAXPATHL + 1];
5982 char_u *cpy;
5983 int len;
5984 char_u *remain = NULL;
5985 char_u *q;
5986 int is_relative_to_current = FALSE;
5987 int has_trailing_pathsep = FALSE;
5988 int limit = 100;
5989
5990 p = vim_strsave(p);
5991
5992 if (p[0] == '.' && (vim_ispathsep(p[1])
5993 || (p[1] == '.' && (vim_ispathsep(p[2])))))
5994 is_relative_to_current = TRUE;
5995
5996 len = STRLEN(p);
5997 if (len > 0 && vim_ispathsep(p[len-1]))
5998 has_trailing_pathsep = TRUE;
5999
6000 q = getnextcomp(p);
6001 if (*q != NUL)
6002 {
6003 /* Separate the first path component in "p", and keep the
6004 * remainder (beginning with the path separator). */
6005 remain = vim_strsave(q - 1);
6006 q[-1] = NUL;
6007 }
6008
6009 for (;;)
6010 {
6011 for (;;)
6012 {
6013 len = readlink((char *)p, (char *)buf, MAXPATHL);
6014 if (len <= 0)
6015 break;
6016 buf[len] = NUL;
6017
6018 if (limit-- == 0)
6019 {
6020 vim_free(p);
6021 vim_free(remain);
6022 EMSG(_("E655: Too many symbolic links (cycle?)"));
6023 retvar->var_val.var_string = NULL;
6024 goto fail;
6025 }
6026
6027 /* Ensure that the result will have a trailing path separator
6028 * if the argument has one. */
6029 if (remain == NULL && has_trailing_pathsep)
6030 add_pathsep(buf);
6031
6032 /* Separate the first path component in the link value and
6033 * concatenate the remainders. */
6034 q = getnextcomp(vim_ispathsep(*buf) ? buf + 1 : buf);
6035 if (*q != NUL)
6036 {
6037 if (remain == NULL)
6038 remain = vim_strsave(q - 1);
6039 else
6040 {
6041 cpy = vim_strnsave(q-1, STRLEN(q-1)+STRLEN(remain));
6042 if (cpy != NULL)
6043 {
6044 STRCAT(cpy, remain);
6045 vim_free(remain);
6046 remain = cpy;
6047 }
6048 }
6049 q[-1] = NUL;
6050 }
6051
6052 q = gettail(p);
6053 if (q > p && *q == NUL)
6054 {
6055 /* Ignore trailing path separator. */
6056 q[-1] = NUL;
6057 q = gettail(p);
6058 }
6059 if (q > p && !mch_isFullName(buf))
6060 {
6061 /* symlink is relative to directory of argument */
6062 cpy = alloc((unsigned)(STRLEN(p) + STRLEN(buf) + 1));
6063 if (cpy != NULL)
6064 {
6065 STRCPY(cpy, p);
6066 STRCPY(gettail(cpy), buf);
6067 vim_free(p);
6068 p = cpy;
6069 }
6070 }
6071 else
6072 {
6073 vim_free(p);
6074 p = vim_strsave(buf);
6075 }
6076 }
6077
6078 if (remain == NULL)
6079 break;
6080
6081 /* Append the first path component of "remain" to "p". */
6082 q = getnextcomp(remain + 1);
6083 len = q - remain - (*q != NUL);
6084 cpy = vim_strnsave(p, STRLEN(p) + len);
6085 if (cpy != NULL)
6086 {
6087 STRNCAT(cpy, remain, len);
6088 vim_free(p);
6089 p = cpy;
6090 }
6091 /* Shorten "remain". */
6092 if (*q != NUL)
6093 STRCPY(remain, q - 1);
6094 else
6095 {
6096 vim_free(remain);
6097 remain = NULL;
6098 }
6099 }
6100
6101 /* If the result is a relative path name, make it explicitly relative to
6102 * the current directory if and only if the argument had this form. */
6103 if (!vim_ispathsep(*p))
6104 {
6105 if (is_relative_to_current
6106 && *p != NUL
6107 && !(p[0] == '.'
6108 && (p[1] == NUL
6109 || vim_ispathsep(p[1])
6110 || (p[1] == '.'
6111 && (p[2] == NUL
6112 || vim_ispathsep(p[2]))))))
6113 {
6114 /* Prepend "./". */
6115 cpy = vim_strnsave((char_u *)"./", 2 + STRLEN(p));
6116 if (cpy != NULL)
6117 {
6118 STRCAT(cpy, p);
6119 vim_free(p);
6120 p = cpy;
6121 }
6122 }
6123 else if (!is_relative_to_current)
6124 {
6125 /* Strip leading "./". */
6126 q = p;
6127 while (q[0] == '.' && vim_ispathsep(q[1]))
6128 q += 2;
6129 if (q > p)
6130 mch_memmove(p, p + 2, STRLEN(p + 2) + (size_t)1);
6131 }
6132 }
6133
6134 /* Ensure that the result will have no trailing path separator
6135 * if the argument had none. But keep "/" or "//". */
6136 if (!has_trailing_pathsep)
6137 {
6138 q = p + STRLEN(p);
6139 while ((q > p + 2 || (q == p + 2 && !vim_ispathsep(*p)))
6140 && vim_ispathsep(q[-1]))
6141 --q;
6142 *q = NUL;
6143 }
6144
6145 retvar->var_val.var_string = p;
6146 }
6147# else
6148 retvar->var_val.var_string = vim_strsave(p);
6149# endif
6150#endif
6151
6152 simplify_filename(retvar->var_val.var_string);
6153
6154#ifdef HAVE_READLINK
6155fail:
6156#endif
6157 retvar->var_type = VAR_STRING;
6158}
6159
6160/*
6161 * "simplify()" function
6162 */
6163 static void
6164f_simplify(argvars, retvar)
6165 VAR argvars;
6166 VAR retvar;
6167{
6168 char_u *p;
6169
6170 p = get_var_string(&argvars[0]);
6171 retvar->var_val.var_string = vim_strsave(p);
6172 simplify_filename(retvar->var_val.var_string); /* simplify in place */
6173 retvar->var_type = VAR_STRING;
6174}
6175
6176/*
6177 * "search()" function
6178 */
6179 static void
6180f_search(argvars, retvar)
6181 VAR argvars;
6182 VAR retvar;
6183{
6184 char_u *pat;
6185 pos_T pos;
6186 int save_p_ws = p_ws;
6187 int dir;
6188
6189 pat = get_var_string(&argvars[0]);
6190 dir = get_search_arg(&argvars[1], NULL); /* may set p_ws */
6191
6192 pos = curwin->w_cursor;
6193 if (searchit(curwin, curbuf, &pos, dir, pat, 1L,
6194 SEARCH_KEEP, RE_SEARCH) != FAIL)
6195 {
6196 retvar->var_val.var_number = pos.lnum;
6197 curwin->w_cursor = pos;
6198 /* "/$" will put the cursor after the end of the line, may need to
6199 * correct that here */
6200 check_cursor();
6201 }
6202 else
6203 retvar->var_val.var_number = 0;
6204 p_ws = save_p_ws;
6205}
6206
6207#define SP_NOMOVE 1 /* don't move cursor */
6208#define SP_REPEAT 2 /* repeat to find outer pair */
6209#define SP_RETCOUNT 4 /* return matchcount */
6210
6211/*
6212 * "searchpair()" function
6213 */
6214 static void
6215f_searchpair(argvars, retvar)
6216 VAR argvars;
6217 VAR retvar;
6218{
6219 char_u *spat, *mpat, *epat;
6220 char_u *skip;
6221 char_u *pat, *pat2, *pat3;
6222 pos_T pos;
6223 pos_T firstpos;
6224 pos_T save_cursor;
6225 pos_T save_pos;
6226 int save_p_ws = p_ws;
6227 char_u *save_cpo;
6228 int dir;
6229 int flags = 0;
6230 char_u nbuf1[NUMBUFLEN];
6231 char_u nbuf2[NUMBUFLEN];
6232 char_u nbuf3[NUMBUFLEN];
6233 int n;
6234 int r;
6235 int nest = 1;
6236 int err;
6237
6238 retvar->var_val.var_number = 0; /* default: FAIL */
6239
6240 /* Make 'cpoptions' empty, the 'l' flag should not be used here. */
6241 save_cpo = p_cpo;
6242 p_cpo = (char_u *)"";
6243
6244 /* Get the three pattern arguments: start, middle, end. */
6245 spat = get_var_string(&argvars[0]);
6246 mpat = get_var_string_buf(&argvars[1], nbuf1);
6247 epat = get_var_string_buf(&argvars[2], nbuf2);
6248
6249 /* Make two search patterns: start/end (pat2, for in nested pairs) and
6250 * start/middle/end (pat3, for the top pair). */
6251 pat2 = alloc((unsigned)(STRLEN(spat) + STRLEN(epat) + 15));
6252 pat3 = alloc((unsigned)(STRLEN(spat) + STRLEN(mpat) + STRLEN(epat) + 23));
6253 if (pat2 == NULL || pat3 == NULL)
6254 goto theend;
6255 sprintf((char *)pat2, "\\(%s\\m\\)\\|\\(%s\\m\\)", spat, epat);
6256 if (*mpat == NUL)
6257 STRCPY(pat3, pat2);
6258 else
6259 sprintf((char *)pat3, "\\(%s\\m\\)\\|\\(%s\\m\\)\\|\\(%s\\m\\)",
6260 spat, epat, mpat);
6261
6262 /* Handle the optional fourth argument: flags */
6263 dir = get_search_arg(&argvars[3], &flags); /* may set p_ws */
6264
6265 /* Optional fifth argument: skip expresion */
6266 if (argvars[3].var_type == VAR_UNKNOWN
6267 || argvars[4].var_type == VAR_UNKNOWN)
6268 skip = (char_u *)"";
6269 else
6270 skip = get_var_string_buf(&argvars[4], nbuf3);
6271
6272 save_cursor = curwin->w_cursor;
6273 pos = curwin->w_cursor;
6274 firstpos.lnum = 0;
6275 pat = pat3;
6276 for (;;)
6277 {
6278 n = searchit(curwin, curbuf, &pos, dir, pat, 1L,
6279 SEARCH_KEEP, RE_SEARCH);
6280 if (n == FAIL || (firstpos.lnum != 0 && equalpos(pos, firstpos)))
6281 /* didn't find it or found the first match again: FAIL */
6282 break;
6283
6284 if (firstpos.lnum == 0)
6285 firstpos = pos;
6286
6287 /* If the skip pattern matches, ignore this match. */
6288 if (*skip != NUL)
6289 {
6290 save_pos = curwin->w_cursor;
6291 curwin->w_cursor = pos;
6292 r = eval_to_bool(skip, &err, NULL, FALSE);
6293 curwin->w_cursor = save_pos;
6294 if (err)
6295 {
6296 /* Evaluating {skip} caused an error, break here. */
6297 curwin->w_cursor = save_cursor;
6298 retvar->var_val.var_number = -1;
6299 break;
6300 }
6301 if (r)
6302 continue;
6303 }
6304
6305 if ((dir == BACKWARD && n == 3) || (dir == FORWARD && n == 2))
6306 {
6307 /* Found end when searching backwards or start when searching
6308 * forward: nested pair. */
6309 ++nest;
6310 pat = pat2; /* nested, don't search for middle */
6311 }
6312 else
6313 {
6314 /* Found end when searching forward or start when searching
6315 * backward: end of (nested) pair; or found middle in outer pair. */
6316 if (--nest == 1)
6317 pat = pat3; /* outer level, search for middle */
6318 }
6319
6320 if (nest == 0)
6321 {
6322 /* Found the match: return matchcount or line number. */
6323 if (flags & SP_RETCOUNT)
6324 ++retvar->var_val.var_number;
6325 else
6326 retvar->var_val.var_number = pos.lnum;
6327 curwin->w_cursor = pos;
6328 if (!(flags & SP_REPEAT))
6329 break;
6330 nest = 1; /* search for next unmatched */
6331 }
6332 }
6333
6334 /* If 'n' flag is used or search failed: restore cursor position. */
6335 if ((flags & SP_NOMOVE) || retvar->var_val.var_number == 0)
6336 curwin->w_cursor = save_cursor;
6337
6338theend:
6339 vim_free(pat2);
6340 vim_free(pat3);
6341 p_ws = save_p_ws;
6342 p_cpo = save_cpo;
6343}
6344
6345 static int
6346get_search_arg(varp, flagsp)
6347 VAR varp;
6348 int *flagsp;
6349{
6350 int dir = FORWARD;
6351 char_u *flags;
6352 char_u nbuf[NUMBUFLEN];
6353
6354 if (varp->var_type != VAR_UNKNOWN)
6355 {
6356 flags = get_var_string_buf(varp, nbuf);
6357 if (vim_strchr(flags, 'b') != NULL)
6358 dir = BACKWARD;
6359 if (vim_strchr(flags, 'w') != NULL)
6360 p_ws = TRUE;
6361 if (vim_strchr(flags, 'W') != NULL)
6362 p_ws = FALSE;
6363 if (flagsp != NULL)
6364 {
6365 if (vim_strchr(flags, 'n') != NULL)
6366 *flagsp |= SP_NOMOVE;
6367 if (vim_strchr(flags, 'r') != NULL)
6368 *flagsp |= SP_REPEAT;
6369 if (vim_strchr(flags, 'm') != NULL)
6370 *flagsp |= SP_RETCOUNT;
6371 }
6372 }
6373 return dir;
6374}
6375
6376/*
6377 * "setbufvar()" function
6378 */
6379/*ARGSUSED*/
6380 static void
6381f_setbufvar(argvars, retvar)
6382 VAR argvars;
6383 VAR retvar;
6384{
6385 buf_T *buf;
6386#ifdef FEAT_AUTOCMD
6387 aco_save_T aco;
6388#else
6389 buf_T *save_curbuf;
6390#endif
6391 char_u *varname, *bufvarname;
6392 VAR varp;
6393 char_u nbuf[NUMBUFLEN];
6394
6395 if (check_restricted() || check_secure())
6396 return;
6397 ++emsg_off;
6398 buf = get_buf_var(&argvars[0]);
6399 varname = get_var_string(&argvars[1]);
6400 varp = &argvars[2];
6401
6402 if (buf != NULL && varname != NULL && varp != NULL)
6403 {
6404 /* set curbuf to be our buf, temporarily */
6405#ifdef FEAT_AUTOCMD
6406 aucmd_prepbuf(&aco, buf);
6407#else
6408 save_curbuf = curbuf;
6409 curbuf = buf;
6410#endif
6411
6412 if (*varname == '&')
6413 {
6414 ++varname;
6415 set_option_value(varname, get_var_number(varp),
6416 get_var_string_buf(varp, nbuf), OPT_LOCAL);
6417 }
6418 else
6419 {
6420 bufvarname = alloc((unsigned)STRLEN(varname) + 3);
6421 if (bufvarname != NULL)
6422 {
6423 STRCPY(bufvarname, "b:");
6424 STRCPY(bufvarname + 2, varname);
6425 set_var(bufvarname, varp);
6426 vim_free(bufvarname);
6427 }
6428 }
6429
6430 /* reset notion of buffer */
6431#ifdef FEAT_AUTOCMD
6432 aucmd_restbuf(&aco);
6433#else
6434 curbuf = save_curbuf;
6435#endif
6436 }
6437 --emsg_off;
6438}
6439
6440/*
6441 * "setcmdpos()" function
6442 */
6443 static void
6444f_setcmdpos(argvars, retvar)
6445 VAR argvars;
6446 VAR retvar;
6447{
6448 retvar->var_val.var_number = set_cmdline_pos(
6449 (int)get_var_number(&argvars[0]) - 1);
6450}
6451
6452/*
6453 * "setline()" function
6454 */
6455 static void
6456f_setline(argvars, retvar)
6457 VAR argvars;
6458 VAR retvar;
6459{
6460 linenr_T lnum;
6461 char_u *line;
6462
6463 lnum = get_var_lnum(argvars);
6464 line = get_var_string(&argvars[1]);
6465 retvar->var_val.var_number = 1; /* FAIL is default */
6466
6467 if (lnum >= 1
6468 && lnum <= curbuf->b_ml.ml_line_count
6469 && u_savesub(lnum) == OK
6470 && ml_replace(lnum, line, TRUE) == OK)
6471 {
6472 changed_bytes(lnum, 0);
6473 check_cursor_col();
6474 retvar->var_val.var_number = 0;
6475 }
6476}
6477
6478/*
6479 * "setreg()" function
6480 */
6481 static void
6482f_setreg(argvars, retvar)
6483 VAR argvars;
6484 VAR retvar;
6485{
6486 int regname;
6487 char_u *strregname;
6488 char_u *stropt;
6489 int append;
6490 char_u yank_type;
6491 long block_len;
6492
6493 block_len = -1;
6494 yank_type = MAUTO;
6495 append = FALSE;
6496
6497 strregname = get_var_string(argvars);
6498 retvar->var_val.var_number = 1; /* FAIL is default */
6499
6500 regname = (strregname == NULL ? '"' : *strregname);
6501 if (regname == 0 || regname == '@')
6502 regname = '"';
6503 else if (regname == '=')
6504 return;
6505
6506 if (argvars[2].var_type != VAR_UNKNOWN)
6507 {
6508 for (stropt = get_var_string(&argvars[2]); *stropt != NUL; ++stropt)
6509 switch (*stropt)
6510 {
6511 case 'a': case 'A': /* append */
6512 append = TRUE;
6513 break;
6514 case 'v': case 'c': /* character-wise selection */
6515 yank_type = MCHAR;
6516 break;
6517 case 'V': case 'l': /* line-wise selection */
6518 yank_type = MLINE;
6519 break;
6520#ifdef FEAT_VISUAL
6521 case 'b': case Ctrl_V: /* block-wise selection */
6522 yank_type = MBLOCK;
6523 if (VIM_ISDIGIT(stropt[1]))
6524 {
6525 ++stropt;
6526 block_len = getdigits(&stropt) - 1;
6527 --stropt;
6528 }
6529 break;
6530#endif
6531 }
6532 }
6533
6534 write_reg_contents_ex(regname, get_var_string(&argvars[1]), -1,
6535 append, yank_type, block_len);
6536 retvar->var_val.var_number = 0;
6537}
6538
6539
6540/*
6541 * "setwinvar(expr)" function
6542 */
6543/*ARGSUSED*/
6544 static void
6545f_setwinvar(argvars, retvar)
6546 VAR argvars;
6547 VAR retvar;
6548{
6549 win_T *win;
6550#ifdef FEAT_WINDOWS
6551 win_T *save_curwin;
6552#endif
6553 char_u *varname, *winvarname;
6554 VAR varp;
6555 char_u nbuf[NUMBUFLEN];
6556
6557 if (check_restricted() || check_secure())
6558 return;
6559 ++emsg_off;
6560 win = find_win_by_nr(&argvars[0]);
6561 varname = get_var_string(&argvars[1]);
6562 varp = &argvars[2];
6563
6564 if (win != NULL && varname != NULL && varp != NULL)
6565 {
6566#ifdef FEAT_WINDOWS
6567 /* set curwin to be our win, temporarily */
6568 save_curwin = curwin;
6569 curwin = win;
6570 curbuf = curwin->w_buffer;
6571#endif
6572
6573 if (*varname == '&')
6574 {
6575 ++varname;
6576 set_option_value(varname, get_var_number(varp),
6577 get_var_string_buf(varp, nbuf), OPT_LOCAL);
6578 }
6579 else
6580 {
6581 winvarname = alloc((unsigned)STRLEN(varname) + 3);
6582 if (winvarname != NULL)
6583 {
6584 STRCPY(winvarname, "w:");
6585 STRCPY(winvarname + 2, varname);
6586 set_var(winvarname, varp);
6587 vim_free(winvarname);
6588 }
6589 }
6590
6591#ifdef FEAT_WINDOWS
6592 /* Restore current window, if it's still valid (autocomands can make
6593 * it invalid). */
6594 if (win_valid(save_curwin))
6595 {
6596 curwin = save_curwin;
6597 curbuf = curwin->w_buffer;
6598 }
6599#endif
6600 }
6601 --emsg_off;
6602}
6603
6604/*
6605 * "nextnonblank()" function
6606 */
6607 static void
6608f_nextnonblank(argvars, retvar)
6609 VAR argvars;
6610 VAR retvar;
6611{
6612 linenr_T lnum;
6613
6614 for (lnum = get_var_lnum(argvars); ; ++lnum)
6615 {
6616 if (lnum > curbuf->b_ml.ml_line_count)
6617 {
6618 lnum = 0;
6619 break;
6620 }
6621 if (*skipwhite(ml_get(lnum)) != NUL)
6622 break;
6623 }
6624 retvar->var_val.var_number = lnum;
6625}
6626
6627/*
6628 * "prevnonblank()" function
6629 */
6630 static void
6631f_prevnonblank(argvars, retvar)
6632 VAR argvars;
6633 VAR retvar;
6634{
6635 linenr_T lnum;
6636
6637 lnum = get_var_lnum(argvars);
6638 if (lnum < 1 || lnum > curbuf->b_ml.ml_line_count)
6639 lnum = 0;
6640 else
6641 while (lnum >= 1 && *skipwhite(ml_get(lnum)) == NUL)
6642 --lnum;
6643 retvar->var_val.var_number = lnum;
6644}
6645
6646#if defined(FEAT_CLIENTSERVER) && defined(FEAT_X11)
6647static void make_connection __ARGS((void));
6648static int check_connection __ARGS((void));
6649
6650 static void
6651make_connection()
6652{
6653 if (X_DISPLAY == NULL
6654# ifdef FEAT_GUI
6655 && !gui.in_use
6656# endif
6657 )
6658 {
6659 x_force_connect = TRUE;
6660 setup_term_clip();
6661 x_force_connect = FALSE;
6662 }
6663}
6664
6665 static int
6666check_connection()
6667{
6668 make_connection();
6669 if (X_DISPLAY == NULL)
6670 {
6671 EMSG(_("E240: No connection to Vim server"));
6672 return FAIL;
6673 }
6674 return OK;
6675}
6676#endif
6677
6678/*ARGSUSED*/
6679 static void
6680f_serverlist(argvars, retvar)
6681 VAR argvars;
6682 VAR retvar;
6683{
6684 char_u *r = NULL;
6685
6686#ifdef FEAT_CLIENTSERVER
6687# ifdef WIN32
6688 r = serverGetVimNames();
6689# else
6690 make_connection();
6691 if (X_DISPLAY != NULL)
6692 r = serverGetVimNames(X_DISPLAY);
6693# endif
6694#endif
6695 retvar->var_type = VAR_STRING;
6696 retvar->var_val.var_string = r;
6697}
6698
6699/*ARGSUSED*/
6700 static void
6701f_remote_peek(argvars, retvar)
6702 VAR argvars;
6703 VAR retvar;
6704{
6705#ifdef FEAT_CLIENTSERVER
6706 var v;
6707 char_u *s = NULL;
6708# ifdef WIN32
6709 int n = 0;
6710# endif
6711
6712 if (check_restricted() || check_secure())
6713 {
6714 retvar->var_val.var_number = -1;
6715 return;
6716 }
6717# ifdef WIN32
6718 sscanf(get_var_string(&argvars[0]), "%x", &n);
6719 if (n == 0)
6720 retvar->var_val.var_number = -1;
6721 else
6722 {
6723 s = serverGetReply((HWND)n, FALSE, FALSE, FALSE);
6724 retvar->var_val.var_number = (s != NULL);
6725 }
6726# else
6727 retvar->var_val.var_number = 0;
6728 if (check_connection() == FAIL)
6729 return;
6730
6731 retvar->var_val.var_number = serverPeekReply(X_DISPLAY,
6732 serverStrToWin(get_var_string(&argvars[0])), &s);
6733# endif
6734
6735 if (argvars[1].var_type != VAR_UNKNOWN && retvar->var_val.var_number > 0)
6736 {
6737 v.var_type = VAR_STRING;
6738 v.var_val.var_string = vim_strsave(s);
6739 set_var(get_var_string(&argvars[1]), &v);
6740 }
6741#else
6742 retvar->var_val.var_number = -1;
6743#endif
6744}
6745
6746/*ARGSUSED*/
6747 static void
6748f_remote_read(argvars, retvar)
6749 VAR argvars;
6750 VAR retvar;
6751{
6752 char_u *r = NULL;
6753
6754#ifdef FEAT_CLIENTSERVER
6755 if (!check_restricted() && !check_secure())
6756 {
6757# ifdef WIN32
6758 /* The server's HWND is encoded in the 'id' parameter */
6759 int n = 0;
6760
6761 sscanf(get_var_string(&argvars[0]), "%x", &n);
6762 if (n != 0)
6763 r = serverGetReply((HWND)n, FALSE, TRUE, TRUE);
6764 if (r == NULL)
6765# else
6766 if (check_connection() == FAIL || serverReadReply(X_DISPLAY,
6767 serverStrToWin(get_var_string(&argvars[0])), &r, FALSE) < 0)
6768# endif
6769 EMSG(_("E277: Unable to read a server reply"));
6770 }
6771#endif
6772 retvar->var_type = VAR_STRING;
6773 retvar->var_val.var_string = r;
6774}
6775
6776/*ARGSUSED*/
6777 static void
6778f_server2client(argvars, retvar)
6779 VAR argvars;
6780 VAR retvar;
6781{
6782#ifdef FEAT_CLIENTSERVER
6783 char_u buf[NUMBUFLEN];
6784 char_u *server = get_var_string(&argvars[0]);
6785 char_u *reply = get_var_string_buf(&argvars[1], buf);
6786
6787 retvar->var_val.var_number = -1;
6788 if (check_restricted() || check_secure())
6789 return;
6790# ifdef FEAT_X11
6791 if (check_connection() == FAIL)
6792 return;
6793# endif
6794
6795 if (serverSendReply(server, reply) < 0)
6796 {
6797 EMSG(_("E258: Unable to send to client"));
6798 return;
6799 }
6800 retvar->var_val.var_number = 0;
6801#else
6802 retvar->var_val.var_number = -1;
6803#endif
6804}
6805
6806#ifdef FEAT_CLIENTSERVER
6807static void remote_common __ARGS((VAR argvars, VAR retvar, int expr));
6808
6809 static void
6810remote_common(argvars, retvar, expr)
6811 VAR argvars;
6812 VAR retvar;
6813 int expr;
6814{
6815 char_u *server_name;
6816 char_u *keys;
6817 char_u *r = NULL;
6818 char_u buf[NUMBUFLEN];
6819# ifdef WIN32
6820 HWND w;
6821# else
6822 Window w;
6823# endif
6824
6825 if (check_restricted() || check_secure())
6826 return;
6827
6828# ifdef FEAT_X11
6829 if (check_connection() == FAIL)
6830 return;
6831# endif
6832
6833 server_name = get_var_string(&argvars[0]);
6834 keys = get_var_string_buf(&argvars[1], buf);
6835# ifdef WIN32
6836 if (serverSendToVim(server_name, keys, &r, &w, expr, TRUE) < 0)
6837# else
6838 if (serverSendToVim(X_DISPLAY, server_name, keys, &r, &w, expr, 0, TRUE)
6839 < 0)
6840# endif
6841 {
6842 if (r != NULL)
6843 EMSG(r); /* sending worked but evaluation failed */
6844 else
6845 EMSG2(_("E241: Unable to send to %s"), server_name);
6846 return;
6847 }
6848
6849 retvar->var_val.var_string = r;
6850
6851 if (argvars[2].var_type != VAR_UNKNOWN)
6852 {
6853 var v;
6854 char_u str[30];
6855
6856 sprintf((char *)str, "0x%x", (unsigned int)w);
6857 v.var_type = VAR_STRING;
6858 v.var_val.var_string = vim_strsave(str);
6859 set_var(get_var_string(&argvars[2]), &v);
6860 }
6861}
6862#endif
6863
6864/*
6865 * "remote_expr()" function
6866 */
6867/*ARGSUSED*/
6868 static void
6869f_remote_expr(argvars, retvar)
6870 VAR argvars;
6871 VAR retvar;
6872{
6873 retvar->var_type = VAR_STRING;
6874 retvar->var_val.var_string = NULL;
6875#ifdef FEAT_CLIENTSERVER
6876 remote_common(argvars, retvar, TRUE);
6877#endif
6878}
6879
6880/*
6881 * "remote_send()" function
6882 */
6883/*ARGSUSED*/
6884 static void
6885f_remote_send(argvars, retvar)
6886 VAR argvars;
6887 VAR retvar;
6888{
6889 retvar->var_type = VAR_STRING;
6890 retvar->var_val.var_string = NULL;
6891#ifdef FEAT_CLIENTSERVER
6892 remote_common(argvars, retvar, FALSE);
6893#endif
6894}
6895
6896/*
6897 * "remote_foreground()" function
6898 */
6899/*ARGSUSED*/
6900 static void
6901f_remote_foreground(argvars, retvar)
6902 VAR argvars;
6903 VAR retvar;
6904{
6905 retvar->var_val.var_number = 0;
6906#ifdef FEAT_CLIENTSERVER
6907# ifdef WIN32
6908 /* On Win32 it's done in this application. */
6909 serverForeground(get_var_string(&argvars[0]));
6910# else
6911 /* Send a foreground() expression to the server. */
6912 argvars[1].var_type = VAR_STRING;
6913 argvars[1].var_val.var_string = vim_strsave((char_u *)"foreground()");
6914 argvars[2].var_type = VAR_UNKNOWN;
6915 remote_common(argvars, retvar, TRUE);
6916 vim_free(argvars[1].var_val.var_string);
6917# endif
6918#endif
6919}
6920
6921#ifdef HAVE_STRFTIME
6922/*
6923 * "strftime({format}[, {time}])" function
6924 */
6925 static void
6926f_strftime(argvars, retvar)
6927 VAR argvars;
6928 VAR retvar;
6929{
6930 char_u result_buf[256];
6931 struct tm *curtime;
6932 time_t seconds;
6933 char_u *p;
6934
6935 retvar->var_type = VAR_STRING;
6936
6937 p = get_var_string(&argvars[0]);
6938 if (argvars[1].var_type == VAR_UNKNOWN)
6939 seconds = time(NULL);
6940 else
6941 seconds = (time_t)get_var_number(&argvars[1]);
6942 curtime = localtime(&seconds);
6943 /* MSVC returns NULL for an invalid value of seconds. */
6944 if (curtime == NULL)
6945 retvar->var_val.var_string = vim_strsave((char_u *)_("(Invalid)"));
6946 else
6947 {
6948# ifdef FEAT_MBYTE
6949 vimconv_T conv;
6950 char_u *enc;
6951
6952 conv.vc_type = CONV_NONE;
6953 enc = enc_locale();
6954 convert_setup(&conv, p_enc, enc);
6955 if (conv.vc_type != CONV_NONE)
6956 p = string_convert(&conv, p, NULL);
6957# endif
6958 if (p != NULL)
6959 (void)strftime((char *)result_buf, sizeof(result_buf),
6960 (char *)p, curtime);
6961 else
6962 result_buf[0] = NUL;
6963
6964# ifdef FEAT_MBYTE
6965 if (conv.vc_type != CONV_NONE)
6966 vim_free(p);
6967 convert_setup(&conv, enc, p_enc);
6968 if (conv.vc_type != CONV_NONE)
6969 retvar->var_val.var_string =
6970 string_convert(&conv, result_buf, NULL);
6971 else
6972# endif
6973 retvar->var_val.var_string = vim_strsave(result_buf);
6974
6975# ifdef FEAT_MBYTE
6976 /* Release conversion descriptors */
6977 convert_setup(&conv, NULL, NULL);
6978 vim_free(enc);
6979# endif
6980 }
6981}
6982#endif
6983
6984/*
6985 * "stridx()" function
6986 */
6987 static void
6988f_stridx(argvars, retvar)
6989 VAR argvars;
6990 VAR retvar;
6991{
6992 char_u buf[NUMBUFLEN];
6993 char_u *needle;
6994 char_u *haystack;
6995 char_u *pos;
6996
6997 needle = get_var_string(&argvars[1]);
6998 haystack = get_var_string_buf(&argvars[0], buf);
6999 pos = (char_u *)strstr((char *)haystack, (char *)needle);
7000
7001 if (pos == NULL)
7002 retvar->var_val.var_number = -1;
7003 else
7004 retvar->var_val.var_number = (varnumber_T) (pos - haystack);
7005}
7006
7007/*
7008 * "strridx()" function
7009 */
7010 static void
7011f_strridx(argvars, retvar)
7012 VAR argvars;
7013 VAR retvar;
7014{
7015 char_u buf[NUMBUFLEN];
7016 char_u *needle;
7017 char_u *haystack;
7018 char_u *rest;
7019 char_u *lastmatch = NULL;
7020
7021 needle = get_var_string(&argvars[1]);
7022 haystack = get_var_string_buf(&argvars[0], buf);
7023 rest = haystack;
7024 while (*haystack != '\0')
7025 {
7026 rest = (char_u *)strstr((char *)rest, (char *)needle);
7027 if (rest == NULL)
7028 break;
7029 lastmatch = rest++;
7030 }
7031
7032 if (lastmatch == NULL)
7033 retvar->var_val.var_number = -1;
7034 else
7035 retvar->var_val.var_number = (varnumber_T) (lastmatch - haystack);
7036}
7037
7038/*
7039 * "strlen()" function
7040 */
7041 static void
7042f_strlen(argvars, retvar)
7043 VAR argvars;
7044 VAR retvar;
7045{
7046 retvar->var_val.var_number = (varnumber_T) (STRLEN(get_var_string(&argvars[0])));
7047}
7048
7049/*
7050 * "strpart()" function
7051 */
7052 static void
7053f_strpart(argvars, retvar)
7054 VAR argvars;
7055 VAR retvar;
7056{
7057 char_u *p;
7058 int n;
7059 int len;
7060 int slen;
7061
7062 p = get_var_string(&argvars[0]);
7063 slen = (int)STRLEN(p);
7064
7065 n = get_var_number(&argvars[1]);
7066 if (argvars[2].var_type != VAR_UNKNOWN)
7067 len = get_var_number(&argvars[2]);
7068 else
7069 len = slen - n; /* default len: all bytes that are available. */
7070
7071 /*
7072 * Only return the overlap between the specified part and the actual
7073 * string.
7074 */
7075 if (n < 0)
7076 {
7077 len += n;
7078 n = 0;
7079 }
7080 else if (n > slen)
7081 n = slen;
7082 if (len < 0)
7083 len = 0;
7084 else if (n + len > slen)
7085 len = slen - n;
7086
7087 retvar->var_type = VAR_STRING;
7088 retvar->var_val.var_string = vim_strnsave(p + n, len);
7089}
7090
7091/*
7092 * "strtrans()" function
7093 */
7094 static void
7095f_strtrans(argvars, retvar)
7096 VAR argvars;
7097 VAR retvar;
7098{
7099 retvar->var_type = VAR_STRING;
7100 retvar->var_val.var_string = transstr(get_var_string(&argvars[0]));
7101}
7102
7103/*
7104 * "synID(line, col, trans)" function
7105 */
7106/*ARGSUSED*/
7107 static void
7108f_synID(argvars, retvar)
7109 VAR argvars;
7110 VAR retvar;
7111{
7112 int id = 0;
7113#ifdef FEAT_SYN_HL
7114 long line;
7115 long col;
7116 int trans;
7117
7118 line = get_var_lnum(argvars);
7119 col = get_var_number(&argvars[1]) - 1;
7120 trans = get_var_number(&argvars[2]);
7121
7122 if (line >= 1 && line <= curbuf->b_ml.ml_line_count
7123 && col >= 0 && col < (long)STRLEN(ml_get(line)))
7124 id = syn_get_id(line, col, trans);
7125#endif
7126
7127 retvar->var_val.var_number = id;
7128}
7129
7130/*
7131 * "synIDattr(id, what [, mode])" function
7132 */
7133/*ARGSUSED*/
7134 static void
7135f_synIDattr(argvars, retvar)
7136 VAR argvars;
7137 VAR retvar;
7138{
7139 char_u *p = NULL;
7140#ifdef FEAT_SYN_HL
7141 int id;
7142 char_u *what;
7143 char_u *mode;
7144 char_u modebuf[NUMBUFLEN];
7145 int modec;
7146
7147 id = get_var_number(&argvars[0]);
7148 what = get_var_string(&argvars[1]);
7149 if (argvars[2].var_type != VAR_UNKNOWN)
7150 {
7151 mode = get_var_string_buf(&argvars[2], modebuf);
7152 modec = TOLOWER_ASC(mode[0]);
7153 if (modec != 't' && modec != 'c'
7154#ifdef FEAT_GUI
7155 && modec != 'g'
7156#endif
7157 )
7158 modec = 0; /* replace invalid with current */
7159 }
7160 else
7161 {
7162#ifdef FEAT_GUI
7163 if (gui.in_use)
7164 modec = 'g';
7165 else
7166#endif
7167 if (t_colors > 1)
7168 modec = 'c';
7169 else
7170 modec = 't';
7171 }
7172
7173
7174 switch (TOLOWER_ASC(what[0]))
7175 {
7176 case 'b':
7177 if (TOLOWER_ASC(what[1]) == 'g') /* bg[#] */
7178 p = highlight_color(id, what, modec);
7179 else /* bold */
7180 p = highlight_has_attr(id, HL_BOLD, modec);
7181 break;
7182
7183 case 'f': /* fg[#] */
7184 p = highlight_color(id, what, modec);
7185 break;
7186
7187 case 'i':
7188 if (TOLOWER_ASC(what[1]) == 'n') /* inverse */
7189 p = highlight_has_attr(id, HL_INVERSE, modec);
7190 else /* italic */
7191 p = highlight_has_attr(id, HL_ITALIC, modec);
7192 break;
7193
7194 case 'n': /* name */
7195 p = get_highlight_name(NULL, id - 1);
7196 break;
7197
7198 case 'r': /* reverse */
7199 p = highlight_has_attr(id, HL_INVERSE, modec);
7200 break;
7201
7202 case 's': /* standout */
7203 p = highlight_has_attr(id, HL_STANDOUT, modec);
7204 break;
7205
7206 case 'u': /* underline */
7207 p = highlight_has_attr(id, HL_UNDERLINE, modec);
7208 break;
7209 }
7210
7211 if (p != NULL)
7212 p = vim_strsave(p);
7213#endif
7214 retvar->var_type = VAR_STRING;
7215 retvar->var_val.var_string = p;
7216}
7217
7218/*
7219 * "synIDtrans(id)" function
7220 */
7221/*ARGSUSED*/
7222 static void
7223f_synIDtrans(argvars, retvar)
7224 VAR argvars;
7225 VAR retvar;
7226{
7227 int id;
7228
7229#ifdef FEAT_SYN_HL
7230 id = get_var_number(&argvars[0]);
7231
7232 if (id > 0)
7233 id = syn_get_final_id(id);
7234 else
7235#endif
7236 id = 0;
7237
7238 retvar->var_val.var_number = id;
7239}
7240
7241/*
7242 * "system()" function
7243 */
7244 static void
7245f_system(argvars, retvar)
7246 VAR argvars;
7247 VAR retvar;
7248{
7249 char_u *p;
7250
7251 p = get_cmd_output(get_var_string(&argvars[0]), SHELL_SILENT);
7252#ifdef USE_CR
7253 /* translate <CR> into <NL> */
7254 if (p != NULL)
7255 {
7256 char_u *s;
7257
7258 for (s = p; *s; ++s)
7259 {
7260 if (*s == CAR)
7261 *s = NL;
7262 }
7263 }
7264#else
7265# ifdef USE_CRNL
7266 /* translate <CR><NL> into <NL> */
7267 if (p != NULL)
7268 {
7269 char_u *s, *d;
7270
7271 d = p;
7272 for (s = p; *s; ++s)
7273 {
7274 if (s[0] == CAR && s[1] == NL)
7275 ++s;
7276 *d++ = *s;
7277 }
7278 *d = NUL;
7279 }
7280# endif
7281#endif
7282 retvar->var_type = VAR_STRING;
7283 retvar->var_val.var_string = p;
7284}
7285
7286/*
7287 * "submatch()" function
7288 */
7289 static void
7290f_submatch(argvars, retvar)
7291 VAR argvars;
7292 VAR retvar;
7293{
7294 retvar->var_type = VAR_STRING;
7295 retvar->var_val.var_string = reg_submatch((int)get_var_number(&argvars[0]));
7296}
7297
7298/*
7299 * "substitute()" function
7300 */
7301 static void
7302f_substitute(argvars, retvar)
7303 VAR argvars;
7304 VAR retvar;
7305{
7306 char_u patbuf[NUMBUFLEN];
7307 char_u subbuf[NUMBUFLEN];
7308 char_u flagsbuf[NUMBUFLEN];
7309
7310 retvar->var_type = VAR_STRING;
7311 retvar->var_val.var_string = do_string_sub(
7312 get_var_string(&argvars[0]),
7313 get_var_string_buf(&argvars[1], patbuf),
7314 get_var_string_buf(&argvars[2], subbuf),
7315 get_var_string_buf(&argvars[3], flagsbuf));
7316}
7317
7318/*
7319 * "tempname()" function
7320 */
7321/*ARGSUSED*/
7322 static void
7323f_tempname(argvars, retvar)
7324 VAR argvars;
7325 VAR retvar;
7326{
7327 static int x = 'A';
7328
7329 retvar->var_type = VAR_STRING;
7330 retvar->var_val.var_string = vim_tempname(x);
7331
7332 /* Advance 'x' to use A-Z and 0-9, so that there are at least 34 different
7333 * names. Skip 'I' and 'O', they are used for shell redirection. */
7334 do
7335 {
7336 if (x == 'Z')
7337 x = '0';
7338 else if (x == '9')
7339 x = 'A';
7340 else
7341 {
7342#ifdef EBCDIC
7343 if (x == 'I')
7344 x = 'J';
7345 else if (x == 'R')
7346 x = 'S';
7347 else
7348#endif
7349 ++x;
7350 }
7351 } while (x == 'I' || x == 'O');
7352}
7353
7354/*
7355 * "tolower(string)" function
7356 */
7357 static void
7358f_tolower(argvars, retvar)
7359 VAR argvars;
7360 VAR retvar;
7361{
7362 char_u *p;
7363
7364 p = vim_strsave(get_var_string(&argvars[0]));
7365 retvar->var_type = VAR_STRING;
7366 retvar->var_val.var_string = p;
7367
7368 if (p != NULL)
7369 while (*p != NUL)
7370 {
7371#ifdef FEAT_MBYTE
7372 int l;
7373
7374 if (enc_utf8)
7375 {
7376 int c, lc;
7377
7378 c = utf_ptr2char(p);
7379 lc = utf_tolower(c);
7380 l = utf_ptr2len_check(p);
7381 /* TODO: reallocate string when byte count changes. */
7382 if (utf_char2len(lc) == l)
7383 utf_char2bytes(lc, p);
7384 p += l;
7385 }
7386 else if (has_mbyte && (l = (*mb_ptr2len_check)(p)) > 1)
7387 p += l; /* skip multi-byte character */
7388 else
7389#endif
7390 {
7391 *p = TOLOWER_LOC(*p); /* note that tolower() can be a macro */
7392 ++p;
7393 }
7394 }
7395}
7396
7397/*
7398 * "toupper(string)" function
7399 */
7400 static void
7401f_toupper(argvars, retvar)
7402 VAR argvars;
7403 VAR retvar;
7404{
7405 char_u *p;
7406
7407 p = vim_strsave(get_var_string(&argvars[0]));
7408 retvar->var_type = VAR_STRING;
7409 retvar->var_val.var_string = p;
7410
7411 if (p != NULL)
7412 while (*p != NUL)
7413 {
7414#ifdef FEAT_MBYTE
7415 int l;
7416
7417 if (enc_utf8)
7418 {
7419 int c, uc;
7420
7421 c = utf_ptr2char(p);
7422 uc = utf_toupper(c);
7423 l = utf_ptr2len_check(p);
7424 /* TODO: reallocate string when byte count changes. */
7425 if (utf_char2len(uc) == l)
7426 utf_char2bytes(uc, p);
7427 p += l;
7428 }
7429 else if (has_mbyte && (l = (*mb_ptr2len_check)(p)) > 1)
7430 p += l; /* skip multi-byte character */
7431 else
7432#endif
7433 {
7434 *p = TOUPPER_LOC(*p); /* note that toupper() can be a macro */
7435 p++;
7436 }
7437 }
7438}
7439
7440/*
7441 * "type(expr)" function
7442 */
7443 static void
7444f_type(argvars, retvar)
7445 VAR argvars;
7446 VAR retvar;
7447{
7448 if (argvars[0].var_type == VAR_NUMBER)
7449 retvar->var_val.var_number = 0;
7450 else
7451 retvar->var_val.var_number = 1;
7452}
7453
7454/*
7455 * "virtcol(string)" function
7456 */
7457 static void
7458f_virtcol(argvars, retvar)
7459 VAR argvars;
7460 VAR retvar;
7461{
7462 colnr_T vcol = 0;
7463 pos_T *fp;
7464
7465 fp = var2fpos(&argvars[0], FALSE);
7466 if (fp != NULL && fp->lnum <= curbuf->b_ml.ml_line_count)
7467 {
7468 getvvcol(curwin, fp, NULL, NULL, &vcol);
7469 ++vcol;
7470 }
7471
7472 retvar->var_val.var_number = vcol;
7473}
7474
7475/*
7476 * "visualmode()" function
7477 */
7478/*ARGSUSED*/
7479 static void
7480f_visualmode(argvars, retvar)
7481 VAR argvars;
7482 VAR retvar;
7483{
7484#ifdef FEAT_VISUAL
7485 char_u str[2];
7486
7487 retvar->var_type = VAR_STRING;
7488 str[0] = curbuf->b_visual_mode_eval;
7489 str[1] = NUL;
7490 retvar->var_val.var_string = vim_strsave(str);
7491
7492 /* A non-zero number or non-empty string argument: reset mode. */
7493 if ((argvars[0].var_type == VAR_NUMBER
7494 && argvars[0].var_val.var_number != 0)
7495 || (argvars[0].var_type == VAR_STRING
7496 && *get_var_string(&argvars[0]) != NUL))
7497 curbuf->b_visual_mode_eval = NUL;
7498#else
7499 retvar->var_val.var_number = 0; /* return anything, it won't work anyway */
7500#endif
7501}
7502
7503/*
7504 * "winbufnr(nr)" function
7505 */
7506 static void
7507f_winbufnr(argvars, retvar)
7508 VAR argvars;
7509 VAR retvar;
7510{
7511 win_T *wp;
7512
7513 wp = find_win_by_nr(&argvars[0]);
7514 if (wp == NULL)
7515 retvar->var_val.var_number = -1;
7516 else
7517 retvar->var_val.var_number = wp->w_buffer->b_fnum;
7518}
7519
7520/*
7521 * "wincol()" function
7522 */
7523/*ARGSUSED*/
7524 static void
7525f_wincol(argvars, retvar)
7526 VAR argvars;
7527 VAR retvar;
7528{
7529 validate_cursor();
7530 retvar->var_val.var_number = curwin->w_wcol + 1;
7531}
7532
7533/*
7534 * "winheight(nr)" function
7535 */
7536 static void
7537f_winheight(argvars, retvar)
7538 VAR argvars;
7539 VAR retvar;
7540{
7541 win_T *wp;
7542
7543 wp = find_win_by_nr(&argvars[0]);
7544 if (wp == NULL)
7545 retvar->var_val.var_number = -1;
7546 else
7547 retvar->var_val.var_number = wp->w_height;
7548}
7549
7550/*
7551 * "winline()" function
7552 */
7553/*ARGSUSED*/
7554 static void
7555f_winline(argvars, retvar)
7556 VAR argvars;
7557 VAR retvar;
7558{
7559 validate_cursor();
7560 retvar->var_val.var_number = curwin->w_wrow + 1;
7561}
7562
7563/*
7564 * "winnr()" function
7565 */
7566/* ARGSUSED */
7567 static void
7568f_winnr(argvars, retvar)
7569 VAR argvars;
7570 VAR retvar;
7571{
7572 int nr = 1;
7573#ifdef FEAT_WINDOWS
7574 win_T *wp;
7575
7576 for (wp = firstwin; wp != curwin; wp = wp->w_next)
7577 ++nr;
7578#endif
7579 retvar->var_val.var_number = nr;
7580}
7581
7582/*
7583 * "winrestcmd()" function
7584 */
7585/* ARGSUSED */
7586 static void
7587f_winrestcmd(argvars, retvar)
7588 VAR argvars;
7589 VAR retvar;
7590{
7591#ifdef FEAT_WINDOWS
7592 win_T *wp;
7593 int winnr = 1;
7594 garray_T ga;
7595 char_u buf[50];
7596
7597 ga_init2(&ga, (int)sizeof(char), 70);
7598 for (wp = firstwin; wp != NULL; wp = wp->w_next)
7599 {
7600 sprintf((char *)buf, "%dresize %d|", winnr, wp->w_height);
7601 ga_concat(&ga, buf);
7602# ifdef FEAT_VERTSPLIT
7603 sprintf((char *)buf, "vert %dresize %d|", winnr, wp->w_width);
7604 ga_concat(&ga, buf);
7605# endif
7606 ++winnr;
7607 }
7608
7609 retvar->var_val.var_string = ga.ga_data;
7610#else
7611 retvar->var_val.var_string = NULL;
7612#endif
7613 retvar->var_type = VAR_STRING;
7614}
7615
7616/*
7617 * "winwidth(nr)" function
7618 */
7619 static void
7620f_winwidth(argvars, retvar)
7621 VAR argvars;
7622 VAR retvar;
7623{
7624 win_T *wp;
7625
7626 wp = find_win_by_nr(&argvars[0]);
7627 if (wp == NULL)
7628 retvar->var_val.var_number = -1;
7629 else
7630#ifdef FEAT_VERTSPLIT
7631 retvar->var_val.var_number = wp->w_width;
7632#else
7633 retvar->var_val.var_number = Columns;
7634#endif
7635}
7636
7637 static win_T *
7638find_win_by_nr(vp)
7639 VAR vp;
7640{
7641#ifdef FEAT_WINDOWS
7642 win_T *wp;
7643#endif
7644 int nr;
7645
7646 nr = get_var_number(vp);
7647
7648#ifdef FEAT_WINDOWS
7649 if (nr == 0)
7650 return curwin;
7651
7652 for (wp = firstwin; wp != NULL; wp = wp->w_next)
7653 if (--nr <= 0)
7654 break;
7655 return wp;
7656#else
7657 if (nr == 0 || nr == 1)
7658 return curwin;
7659 return NULL;
7660#endif
7661}
7662
7663/*
7664 * Translate a String variable into a position.
7665 */
7666 static pos_T *
7667var2fpos(varp, lnum)
7668 VAR varp;
7669 int lnum; /* TRUE when $ is last line */
7670{
7671 char_u *name;
7672 static pos_T pos;
7673 pos_T *pp;
7674
7675 name = get_var_string(varp);
7676 if (name[0] == '.') /* cursor */
7677 return &curwin->w_cursor;
7678 if (name[0] == '\'') /* mark */
7679 {
7680 pp = getmark(name[1], FALSE);
7681 if (pp == NULL || pp == (pos_T *)-1 || pp->lnum <= 0)
7682 return NULL;
7683 return pp;
7684 }
7685 if (name[0] == '$') /* last column or line */
7686 {
7687 if (lnum)
7688 {
7689 pos.lnum = curbuf->b_ml.ml_line_count;
7690 pos.col = 0;
7691 }
7692 else
7693 {
7694 pos.lnum = curwin->w_cursor.lnum;
7695 pos.col = (colnr_T)STRLEN(ml_get_curline());
7696 }
7697 return &pos;
7698 }
7699 return NULL;
7700}
7701
7702/*
7703 * Get the length of an environment variable name.
7704 * Advance "arg" to the first character after the name.
7705 * Return 0 for error.
7706 */
7707 static int
7708get_env_len(arg)
7709 char_u **arg;
7710{
7711 char_u *p;
7712 int len;
7713
7714 for (p = *arg; vim_isIDc(*p); ++p)
7715 ;
7716 if (p == *arg) /* no name found */
7717 return 0;
7718
7719 len = (int)(p - *arg);
7720 *arg = p;
7721 return len;
7722}
7723
7724/*
7725 * Get the length of the name of a function or internal variable.
7726 * "arg" is advanced to the first non-white character after the name.
7727 * Return 0 if something is wrong.
7728 */
7729 static int
7730get_id_len(arg)
7731 char_u **arg;
7732{
7733 char_u *p;
7734 int len;
7735
7736 /* Find the end of the name. */
7737 for (p = *arg; eval_isnamec(*p); ++p)
7738 ;
7739 if (p == *arg) /* no name found */
7740 return 0;
7741
7742 len = (int)(p - *arg);
7743 *arg = skipwhite(p);
7744
7745 return len;
7746}
7747
7748/*
7749 * Get the length of the name of a function.
7750 * "arg" is advanced to the first non-white character after the name.
7751 * Return 0 if something is wrong.
7752 * If the name contains 'magic' {}'s, expand them and return the
7753 * expanded name in an allocated string via 'alias' - caller must free.
7754 */
7755 static int
7756get_func_len(arg, alias, evaluate)
7757 char_u **arg;
7758 char_u **alias;
7759 int evaluate;
7760{
7761 int len;
7762#ifdef FEAT_MAGIC_BRACES
7763 char_u *p;
7764 char_u *expr_start;
7765 char_u *expr_end;
7766#endif
7767
7768 *alias = NULL; /* default to no alias */
7769
7770 if ((*arg)[0] == K_SPECIAL && (*arg)[1] == KS_EXTRA
7771 && (*arg)[2] == (int)KE_SNR)
7772 {
7773 /* hard coded <SNR>, already translated */
7774 *arg += 3;
7775 return get_id_len(arg) + 3;
7776 }
7777 len = eval_fname_script(*arg);
7778 if (len > 0)
7779 {
7780 /* literal "<SID>", "s:" or "<SNR>" */
7781 *arg += len;
7782 }
7783
7784#ifdef FEAT_MAGIC_BRACES
7785 /*
7786 * Find the end of the name;
7787 */
7788 p = find_name_end(*arg, &expr_start, &expr_end);
7789 /* check for {} construction */
7790 if (expr_start != NULL)
7791 {
7792 char_u *temp_string;
7793
7794 if (!evaluate)
7795 {
7796 len += (int)(p - *arg);
7797 *arg = skipwhite(p);
7798 return len;
7799 }
7800
7801 /*
7802 * Include any <SID> etc in the expanded string:
7803 * Thus the -len here.
7804 */
7805 temp_string = make_expanded_name(*arg - len, expr_start, expr_end, p);
7806 if (temp_string == NULL)
7807 return 0;
7808 *alias = temp_string;
7809 *arg = skipwhite(p);
7810 return (int)STRLEN(temp_string);
7811 }
7812#endif
7813
7814 len += get_id_len(arg);
7815 if (len == 0)
7816 EMSG2(_(e_invexpr2), *arg);
7817
7818 return len;
7819}
7820
7821 static char_u *
7822find_name_end(arg, expr_start, expr_end)
7823 char_u *arg;
7824 char_u **expr_start;
7825 char_u **expr_end;
7826{
7827 int nesting = 0;
7828 char_u *p;
7829
7830 *expr_start = NULL;
7831 *expr_end = NULL;
7832
7833 for (p = arg; (*p != NUL && (eval_isnamec(*p) || nesting != 0)); ++p)
7834 {
7835#ifdef FEAT_MAGIC_BRACES
7836 if (*p == '{')
7837 {
7838 nesting++;
7839 if (*expr_start == NULL)
7840 *expr_start = p;
7841 }
7842 else if (*p == '}')
7843 {
7844 nesting--;
7845 if (nesting == 0 && *expr_end == NULL)
7846 *expr_end = p;
7847 }
7848#endif
7849 }
7850
7851 return p;
7852}
7853
7854/*
7855 * Return TRUE if character "c" can be used in a variable or function name.
7856 */
7857 static int
7858eval_isnamec(c)
7859 int c;
7860{
7861 return (ASCII_ISALNUM(c) || c == '_' || c == ':'
7862#ifdef FEAT_MAGIC_BRACES
7863 || c == '{' || c == '}'
7864#endif
7865 );
7866}
7867
7868/*
7869 * Find a v: variable.
7870 * Return it's index, or -1 if not found.
7871 */
7872 static int
7873find_vim_var(name, len)
7874 char_u *name;
7875 int len; /* length of "name" */
7876{
7877 char_u *vname;
7878 int vlen;
7879 int i;
7880
7881 /*
7882 * Ignore "v:" for old built-in variables, require it for new ones.
7883 */
7884 if (name[0] == 'v' && name[1] == ':')
7885 {
7886 vname = name + 2;
7887 vlen = len - 2;
7888 }
7889 else
7890 {
7891 vname = name;
7892 vlen = len;
7893 }
7894 for (i = 0; i < VV_LEN; ++i)
7895 if (vlen == vimvars[i].len && STRCMP(vname, vimvars[i].name) == 0
7896 && ((vimvars[i].flags & VV_COMPAT) || vname != name))
7897 return i;
7898 return -1;
7899}
7900
7901/*
7902 * Set number v: variable to "val".
7903 */
7904 void
7905set_vim_var_nr(idx, val)
7906 int idx;
7907 long val;
7908{
7909 vimvars[idx].val = (char_u *)val;
7910}
7911
7912/*
7913 * Get number v: variable value;
7914 */
7915 long
7916get_vim_var_nr(idx)
7917 int idx;
7918{
7919 return (long)vimvars[idx].val;
7920}
7921
7922/*
7923 * Set v:count, v:count1 and v:prevcount.
7924 */
7925 void
7926set_vcount(count, count1)
7927 long count;
7928 long count1;
7929{
7930 vimvars[VV_PREVCOUNT].val = vimvars[VV_COUNT].val;
7931 vimvars[VV_COUNT].val = (char_u *)count;
7932 vimvars[VV_COUNT1].val = (char_u *)count1;
7933}
7934
7935/*
7936 * Set string v: variable to a copy of "val".
7937 */
7938 void
7939set_vim_var_string(idx, val, len)
7940 int idx;
7941 char_u *val;
7942 int len; /* length of "val" to use or -1 (whole string) */
7943{
7944 vim_free(vimvars[idx].val);
7945 if (val == NULL)
7946 vimvars[idx].val = NULL;
7947 else if (len == -1)
7948 vimvars[idx].val = vim_strsave(val);
7949 else
7950 vimvars[idx].val = vim_strnsave(val, len);
7951}
7952
7953/*
7954 * Set v:register if needed.
7955 */
7956 void
7957set_reg_var(c)
7958 int c;
7959{
7960 char_u regname;
7961
7962 if (c == 0 || c == ' ')
7963 regname = '"';
7964 else
7965 regname = c;
7966 /* Avoid free/alloc when the value is already right. */
7967 if (vimvars[VV_REG].val == NULL || vimvars[VV_REG].val[0] != c)
7968 set_vim_var_string(VV_REG, &regname, 1);
7969}
7970
7971/*
7972 * Get or set v:exception. If "oldval" == NULL, return the current value.
7973 * Otherwise, restore the value to "oldval" and return NULL.
7974 * Must always be called in pairs to save and restore v:exception! Does not
7975 * take care of memory allocations.
7976 */
7977 char_u *
7978v_exception(oldval)
7979 char_u *oldval;
7980{
7981 if (oldval == NULL)
7982 return vimvars[VV_EXCEPTION].val;
7983
7984 vimvars[VV_EXCEPTION].val = oldval;
7985 return NULL;
7986}
7987
7988/*
7989 * Get or set v:throwpoint. If "oldval" == NULL, return the current value.
7990 * Otherwise, restore the value to "oldval" and return NULL.
7991 * Must always be called in pairs to save and restore v:throwpoint! Does not
7992 * take care of memory allocations.
7993 */
7994 char_u *
7995v_throwpoint(oldval)
7996 char_u *oldval;
7997{
7998 if (oldval == NULL)
7999 return vimvars[VV_THROWPOINT].val;
8000
8001 vimvars[VV_THROWPOINT].val = oldval;
8002 return NULL;
8003}
8004
8005#if defined(FEAT_AUTOCMD) || defined(PROTO)
8006/*
8007 * Set v:cmdarg.
8008 * If "eap" != NULL, use "eap" to generate the value and return the old value.
8009 * If "oldarg" != NULL, restore the value to "oldarg" and return NULL.
8010 * Must always be called in pairs!
8011 */
8012 char_u *
8013set_cmdarg(eap, oldarg)
8014 exarg_T *eap;
8015 char_u *oldarg;
8016{
8017 char_u *oldval;
8018 char_u *newval;
8019 unsigned len;
8020
8021 oldval = vimvars[VV_CMDARG].val;
8022 if (eap != NULL)
8023 {
8024 if (eap->force_bin == FORCE_BIN)
8025 len = 6;
8026 else if (eap->force_bin == FORCE_NOBIN)
8027 len = 8;
8028 else
8029 len = 0;
8030 if (eap->force_ff != 0)
8031 len += (unsigned)STRLEN(eap->cmd + eap->force_ff) + 6;
8032# ifdef FEAT_MBYTE
8033 if (eap->force_enc != 0)
8034 len += (unsigned)STRLEN(eap->cmd + eap->force_enc) + 7;
8035# endif
8036
8037 newval = alloc(len + 1);
8038 if (newval == NULL)
8039 return NULL;
8040
8041 if (eap->force_bin == FORCE_BIN)
8042 sprintf((char *)newval, " ++bin");
8043 else if (eap->force_bin == FORCE_NOBIN)
8044 sprintf((char *)newval, " ++nobin");
8045 else
8046 *newval = NUL;
8047 if (eap->force_ff != 0)
8048 sprintf((char *)newval + STRLEN(newval), " ++ff=%s",
8049 eap->cmd + eap->force_ff);
8050# ifdef FEAT_MBYTE
8051 if (eap->force_enc != 0)
8052 sprintf((char *)newval + STRLEN(newval), " ++enc=%s",
8053 eap->cmd + eap->force_enc);
8054# endif
8055 vimvars[VV_CMDARG].val = newval;
8056 return oldval;
8057 }
8058
8059 vim_free(oldval);
8060 vimvars[VV_CMDARG].val = oldarg;
8061 return NULL;
8062}
8063#endif
8064
8065/*
8066 * Get the value of internal variable "name".
8067 * Return OK or FAIL.
8068 */
8069 static int
8070get_var_var(name, len, retvar)
8071 char_u *name;
8072 int len; /* length of "name" */
8073 VAR retvar; /* NULL when only checking existence */
8074{
8075 int ret = OK;
8076 int type = VAR_UNKNOWN;
8077 long number = 1;
8078 char_u *string = NULL;
8079 VAR v;
8080 int cc;
8081 int i;
8082
8083 /* truncate the name, so that we can use strcmp() */
8084 cc = name[len];
8085 name[len] = NUL;
8086
8087 /*
8088 * Check for "b:changedtick".
8089 */
8090 if (STRCMP(name, "b:changedtick") == 0)
8091 {
8092 type = VAR_NUMBER;
8093 number = curbuf->b_changedtick;
8094 }
8095
8096 /*
8097 * Check for built-in v: variables.
8098 */
8099 else if ((i = find_vim_var(name, len)) >= 0)
8100 {
8101 type = vimvars[i].type;
8102 number = (long)vimvars[i].val;
8103 string = vimvars[i].val;
8104 }
8105
8106 /*
8107 * Check for user-defined variables.
8108 */
8109 else
8110 {
8111 v = find_var(name, FALSE);
8112 if (v != NULL)
8113 {
8114 type = v->var_type;
8115 number = v->var_val.var_number;
8116 string = v->var_val.var_string;
8117 }
8118 }
8119
8120 if (type == VAR_UNKNOWN)
8121 {
8122 if (retvar != NULL)
8123 EMSG2(_("E121: Undefined variable: %s"), name);
8124 ret = FAIL;
8125 }
8126 else if (retvar != NULL)
8127 {
8128 retvar->var_type = type;
8129 if (type == VAR_NUMBER)
8130 retvar->var_val.var_number = number;
8131 else if (type == VAR_STRING)
8132 {
8133 if (string != NULL)
8134 string = vim_strsave(string);
8135 retvar->var_val.var_string = string;
8136 }
8137 }
8138
8139 name[len] = cc;
8140
8141 return ret;
8142}
8143
8144/*
8145 * Allocate memory for a variable, and make it emtpy (0 or NULL value).
8146 */
8147 static VAR
8148alloc_var()
8149{
8150 return (VAR)alloc_clear((unsigned)sizeof(var));
8151}
8152
8153/*
8154 * Allocate memory for a variable, and assign a string to it.
8155 * The string "s" must have been allocated, it is consumed.
8156 * Return NULL for out of memory, the variable otherwise.
8157 */
8158 static VAR
8159alloc_string_var(s)
8160 char_u *s;
8161{
8162 VAR retvar;
8163
8164 retvar = alloc_var();
8165 if (retvar != NULL)
8166 {
8167 retvar->var_type = VAR_STRING;
8168 retvar->var_val.var_string = s;
8169 }
8170 else
8171 vim_free(s);
8172 return retvar;
8173}
8174
8175/*
8176 * Free the memory for a variable.
8177 */
8178 static void
8179free_var(varp)
8180 VAR varp;
8181{
8182 if (varp != NULL)
8183 {
8184 if (varp->var_type == VAR_STRING)
8185 vim_free(varp->var_val.var_string);
8186 vim_free(varp->var_name);
8187 vim_free(varp);
8188 }
8189}
8190
8191/*
8192 * Free the memory for a variable value and set the value to NULL or 0.
8193 */
8194 static void
8195clear_var(varp)
8196 VAR varp;
8197{
8198 if (varp != NULL)
8199 {
8200 if (varp->var_type == VAR_STRING)
8201 {
8202 vim_free(varp->var_val.var_string);
8203 varp->var_val.var_string = NULL;
8204 }
8205 else
8206 varp->var_val.var_number = 0;
8207 }
8208}
8209
8210/*
8211 * Get the number value of a variable.
8212 * If it is a String variable, uses vim_str2nr().
8213 */
8214 static long
8215get_var_number(varp)
8216 VAR varp;
8217{
8218 long n;
8219
8220 if (varp->var_type == VAR_NUMBER)
8221 return (long)(varp->var_val.var_number);
8222 else if (varp->var_type == VAR_UNKNOWN || varp->var_val.var_string == NULL)
8223 return 0L;
8224 else
8225 {
8226 vim_str2nr(varp->var_val.var_string, NULL, NULL, TRUE, TRUE, &n, NULL);
8227 return n;
8228 }
8229}
8230
8231/*
8232 * Get the lnum from the first argument. Also accepts ".", "$", etc.
8233 */
8234 static linenr_T
8235get_var_lnum(argvars)
8236 VAR argvars;
8237{
8238 var retvar;
8239 linenr_T lnum;
8240
8241 lnum = get_var_number(&argvars[0]);
8242 if (lnum == 0) /* no valid number, try using line() */
8243 {
8244 retvar.var_type = VAR_NUMBER;
8245 f_line(argvars, &retvar);
8246 lnum = retvar.var_val.var_number;
8247 clear_var(&retvar);
8248 }
8249 return lnum;
8250}
8251
8252/*
8253 * Get the string value of a variable.
8254 * If it is a Number variable, the number is converted into a string.
8255 * get_var_string() uses a single, static buffer. YOU CAN ONLY USE IT ONCE!
8256 * get_var_string_buf() uses a given buffer.
8257 * If the String variable has never been set, return an empty string.
8258 * Never returns NULL;
8259 */
8260 static char_u *
8261get_var_string(varp)
8262 VAR varp;
8263{
8264 static char_u mybuf[NUMBUFLEN];
8265
8266 return get_var_string_buf(varp, mybuf);
8267}
8268
8269 static char_u *
8270get_var_string_buf(varp, buf)
8271 VAR varp;
8272 char_u *buf;
8273{
8274 if (varp->var_type == VAR_NUMBER)
8275 {
8276 sprintf((char *)buf, "%ld", (long)varp->var_val.var_number);
8277 return buf;
8278 }
8279 else if (varp->var_val.var_string == NULL)
8280 return (char_u *)"";
8281 else
8282 return varp->var_val.var_string;
8283}
8284
8285/*
8286 * Find variable "name" in the list of variables.
8287 * Return a pointer to it if found, NULL if not found.
8288 */
8289 static VAR
8290find_var(name, writing)
8291 char_u *name;
8292 int writing;
8293{
8294 int i;
8295 char_u *varname;
8296 garray_T *gap;
8297
8298 /* Check for function arguments "a:" */
8299 if (name[0] == 'a' && name[1] == ':')
8300 {
8301 if (writing)
8302 {
8303 EMSG2(_(e_readonlyvar), name);
8304 return NULL;
8305 }
8306 name += 2;
8307 if (current_funccal == NULL)
8308 return NULL;
8309 if (VIM_ISDIGIT(*name))
8310 {
8311 i = atol((char *)name);
8312 if (i == 0) /* a:0 */
8313 return &current_funccal->a0_var;
8314 i += current_funccal->func->args.ga_len;
8315 if (i > current_funccal->argcount) /* a:999 */
8316 return NULL;
8317 return &(current_funccal->argvars[i - 1]); /* a:1, a:2, etc. */
8318 }
8319 if (STRCMP(name, "firstline") == 0)
8320 return &(current_funccal->firstline);
8321 if (STRCMP(name, "lastline") == 0)
8322 return &(current_funccal->lastline);
8323 for (i = 0; i < current_funccal->func->args.ga_len; ++i)
8324 if (STRCMP(name, ((char_u **)
8325 (current_funccal->func->args.ga_data))[i]) == 0)
8326 return &(current_funccal->argvars[i]); /* a:name */
8327 return NULL;
8328 }
8329
8330 gap = find_var_ga(name, &varname);
8331 if (gap == NULL)
8332 return NULL;
8333 return find_var_in_ga(gap, varname);
8334}
8335
8336 static VAR
8337find_var_in_ga(gap, varname)
8338 garray_T *gap;
8339 char_u *varname;
8340{
8341 int i;
8342
8343 for (i = gap->ga_len; --i >= 0; )
8344 if (VAR_GAP_ENTRY(i, gap).var_name != NULL
8345 && STRCMP(VAR_GAP_ENTRY(i, gap).var_name, varname) == 0)
8346 break;
8347 if (i < 0)
8348 return NULL;
8349 return &VAR_GAP_ENTRY(i, gap);
8350}
8351
8352/*
8353 * Find the growarray and start of name without ':' for a variable name.
8354 */
8355 static garray_T *
8356find_var_ga(name, varname)
8357 char_u *name;
8358 char_u **varname;
8359{
8360 if (name[1] != ':')
8361 {
8362 /* If not "x:name" there must not be any ":" in the name. */
8363 if (vim_strchr(name, ':') != NULL)
8364 return NULL;
8365 *varname = name;
8366 if (current_funccal == NULL)
8367 return &variables; /* global variable */
8368 return &current_funccal->l_vars; /* local function variable */
8369 }
8370 *varname = name + 2;
8371 if (*name == 'b') /* buffer variable */
8372 return &curbuf->b_vars;
8373 if (*name == 'w') /* window variable */
8374 return &curwin->w_vars;
8375 if (*name == 'g') /* global variable */
8376 return &variables;
8377 if (*name == 'l' && current_funccal != NULL)/* local function variable */
8378 return &current_funccal->l_vars;
8379 if (*name == 's' /* script variable */
8380 && current_SID > 0 && current_SID <= ga_scripts.ga_len)
8381 return &SCRIPT_VARS(current_SID);
8382 return NULL;
8383}
8384
8385/*
8386 * Get the string value of a (global/local) variable.
8387 * Returns NULL when it doesn't exist.
8388 */
8389 char_u *
8390get_var_value(name)
8391 char_u *name;
8392{
8393 VAR v;
8394
8395 v = find_var(name, FALSE);
8396 if (v == NULL)
8397 return NULL;
8398 return get_var_string(v);
8399}
8400
8401/*
8402 * Allocate a new growarry for a sourced script. It will be used while
8403 * sourcing this script and when executing functions defined in the script.
8404 */
8405 void
8406new_script_vars(id)
8407 scid_T id;
8408{
8409 if (ga_grow(&ga_scripts, (int)(id - ga_scripts.ga_len)) == OK)
8410 {
8411 while (ga_scripts.ga_len < id)
8412 {
8413 var_init(&SCRIPT_VARS(ga_scripts.ga_len + 1));
8414 ++ga_scripts.ga_len;
8415 --ga_scripts.ga_room;
8416 }
8417 }
8418}
8419
8420/*
8421 * Initialize internal variables for use.
8422 */
8423 void
8424var_init(gap)
8425 garray_T *gap;
8426{
8427 ga_init2(gap, (int)sizeof(var), 4);
8428}
8429
8430/*
8431 * Clean up a list of internal variables.
8432 */
8433 void
8434var_clear(gap)
8435 garray_T *gap;
8436{
8437 int i;
8438
8439 for (i = gap->ga_len; --i >= 0; )
8440 var_free_one(&VAR_GAP_ENTRY(i, gap));
8441 ga_clear(gap);
8442}
8443
8444 static void
8445var_free_one(v)
8446 VAR v;
8447{
8448 vim_free(v->var_name);
8449 v->var_name = NULL;
8450 if (v->var_type == VAR_STRING)
8451 vim_free(v->var_val.var_string);
8452 v->var_val.var_string = NULL;
8453}
8454
8455/*
8456 * List the value of one internal variable.
8457 */
8458 static void
8459list_one_var(v, prefix)
8460 VAR v;
8461 char_u *prefix;
8462{
8463 list_one_var_a(prefix, v->var_name, v->var_type, get_var_string(v));
8464}
8465
8466/*
8467 * List the value of one "v:" variable.
8468 */
8469 static void
8470list_vim_var(i)
8471 int i; /* index in vimvars[] */
8472{
8473 char_u *p;
8474 char_u numbuf[NUMBUFLEN];
8475
8476 if (vimvars[i].type == VAR_NUMBER)
8477 {
8478 p = numbuf;
8479 sprintf((char *)p, "%ld", (long)vimvars[i].val);
8480 }
8481 else if (vimvars[i].val == NULL)
8482 p = (char_u *)"";
8483 else
8484 p = vimvars[i].val;
8485 list_one_var_a((char_u *)"v:", (char_u *)vimvars[i].name,
8486 vimvars[i].type, p);
8487}
8488
8489 static void
8490list_one_var_a(prefix, name, type, string)
8491 char_u *prefix;
8492 char_u *name;
8493 int type;
8494 char_u *string;
8495{
8496 msg_attr(prefix, 0); /* don't use msg(), it overwrites "v:statusmsg" */
8497 if (name != NULL) /* "a:" vars don't have a name stored */
8498 msg_puts(name);
8499 msg_putchar(' ');
8500 msg_advance(22);
8501 if (type == VAR_NUMBER)
8502 msg_putchar('#');
8503 else
8504 msg_putchar(' ');
8505 msg_outtrans(string);
8506}
8507
8508/*
8509 * Set variable "name" to value in "varp".
8510 * If the variable already exists, the value is updated.
8511 * Otherwise the variable is created.
8512 */
8513 static void
8514set_var(name, varp)
8515 char_u *name;
8516 VAR varp;
8517{
8518 int i;
8519 VAR v;
8520 char_u *varname;
8521 garray_T *gap;
8522
8523 /*
8524 * Handle setting internal v: variables.
8525 */
8526 i = find_vim_var(name, (int)STRLEN(name));
8527 if (i >= 0)
8528 {
8529 if (vimvars[i].flags & VV_RO)
8530 EMSG2(_(e_readonlyvar), name);
8531 else
8532 {
8533 if (vimvars[i].type == VAR_STRING)
8534 {
8535 vim_free(vimvars[i].val);
8536 vimvars[i].val = vim_strsave(get_var_string(varp));
8537 }
8538 else
8539 vimvars[i].val = (char_u *)(long)varp->var_val.var_number;
8540 }
8541 return;
8542 }
8543
8544 v = find_var(name, TRUE);
8545 if (v != NULL) /* existing variable, only need to free string */
8546 {
8547 if (v->var_type == VAR_STRING)
8548 vim_free(v->var_val.var_string);
8549 }
8550 else /* add a new variable */
8551 {
8552 gap = find_var_ga(name, &varname);
8553 if (gap == NULL) /* illegal name */
8554 {
8555 EMSG2(_("E461: Illegal variable name: %s"), name);
8556 return;
8557 }
8558
8559 /* Try to use an empty entry */
8560 for (i = gap->ga_len; --i >= 0; )
8561 if (VAR_GAP_ENTRY(i, gap).var_name == NULL)
8562 break;
8563 if (i < 0) /* need to allocate more room */
8564 {
8565 if (ga_grow(gap, 1) == FAIL)
8566 return;
8567 i = gap->ga_len;
8568 }
8569 v = &VAR_GAP_ENTRY(i, gap);
8570 if ((v->var_name = vim_strsave(varname)) == NULL)
8571 return;
8572 if (i == gap->ga_len)
8573 {
8574 ++gap->ga_len;
8575 --gap->ga_room;
8576 }
8577 }
8578 copy_var(varp, v);
8579}
8580
8581 static void
8582copy_var(from, to)
8583 VAR from;
8584 VAR to;
8585{
8586 to->var_type = from->var_type;
8587 if (from->var_type == VAR_STRING)
8588 to->var_val.var_string = vim_strsave(get_var_string(from));
8589 else
8590 to->var_val.var_number = from->var_val.var_number;
8591}
8592
8593/*
8594 * ":echo expr1 ..." print each argument separated with a space, add a
8595 * newline at the end.
8596 * ":echon expr1 ..." print each argument plain.
8597 */
8598 void
8599ex_echo(eap)
8600 exarg_T *eap;
8601{
8602 char_u *arg = eap->arg;
8603 var retvar;
8604 char_u *p;
8605 int needclr = TRUE;
8606 int atstart = TRUE;
8607
8608 if (eap->skip)
8609 ++emsg_skip;
8610 while (*arg != NUL && *arg != '|' && *arg != '\n' && !got_int)
8611 {
8612 p = arg;
8613 if (eval1(&arg, &retvar, !eap->skip) == FAIL)
8614 {
8615 /*
8616 * Report the invalid expression unless the expression evaluation
8617 * has been cancelled due to an aborting error, an interrupt, or an
8618 * exception.
8619 */
8620 if (!aborting())
8621 EMSG2(_(e_invexpr2), p);
8622 break;
8623 }
8624 if (!eap->skip)
8625 {
8626 if (atstart)
8627 {
8628 atstart = FALSE;
8629 /* Call msg_start() after eval1(), evaluating the expression
8630 * may cause a message to appear. */
8631 if (eap->cmdidx == CMD_echo)
8632 msg_start();
8633 }
8634 else if (eap->cmdidx == CMD_echo)
8635 msg_puts_attr((char_u *)" ", echo_attr);
8636 for (p = get_var_string(&retvar); *p != NUL && !got_int; ++p)
8637 if (*p == '\n' || *p == '\r' || *p == TAB)
8638 {
8639 if (*p != TAB && needclr)
8640 {
8641 /* remove any text still there from the command */
8642 msg_clr_eos();
8643 needclr = FALSE;
8644 }
8645 msg_putchar_attr(*p, echo_attr);
8646 }
8647 else
8648 {
8649#ifdef FEAT_MBYTE
8650 if (has_mbyte)
8651 {
8652 int i = (*mb_ptr2len_check)(p);
8653
8654 (void)msg_outtrans_len_attr(p, i, echo_attr);
8655 p += i - 1;
8656 }
8657 else
8658#endif
8659 (void)msg_outtrans_len_attr(p, 1, echo_attr);
8660 }
8661 }
8662 clear_var(&retvar);
8663 arg = skipwhite(arg);
8664 }
8665 eap->nextcmd = check_nextcmd(arg);
8666
8667 if (eap->skip)
8668 --emsg_skip;
8669 else
8670 {
8671 /* remove text that may still be there from the command */
8672 if (needclr)
8673 msg_clr_eos();
8674 if (eap->cmdidx == CMD_echo)
8675 msg_end();
8676 }
8677}
8678
8679/*
8680 * ":echohl {name}".
8681 */
8682 void
8683ex_echohl(eap)
8684 exarg_T *eap;
8685{
8686 int id;
8687
8688 id = syn_name2id(eap->arg);
8689 if (id == 0)
8690 echo_attr = 0;
8691 else
8692 echo_attr = syn_id2attr(id);
8693}
8694
8695/*
8696 * ":execute expr1 ..." execute the result of an expression.
8697 * ":echomsg expr1 ..." Print a message
8698 * ":echoerr expr1 ..." Print an error
8699 * Each gets spaces around each argument and a newline at the end for
8700 * echo commands
8701 */
8702 void
8703ex_execute(eap)
8704 exarg_T *eap;
8705{
8706 char_u *arg = eap->arg;
8707 var retvar;
8708 int ret = OK;
8709 char_u *p;
8710 garray_T ga;
8711 int len;
8712 int save_did_emsg;
8713
8714 ga_init2(&ga, 1, 80);
8715
8716 if (eap->skip)
8717 ++emsg_skip;
8718 while (*arg != NUL && *arg != '|' && *arg != '\n')
8719 {
8720 p = arg;
8721 if (eval1(&arg, &retvar, !eap->skip) == FAIL)
8722 {
8723 /*
8724 * Report the invalid expression unless the expression evaluation
8725 * has been cancelled due to an aborting error, an interrupt, or an
8726 * exception.
8727 */
8728 if (!aborting())
8729 EMSG2(_(e_invexpr2), p);
8730 ret = FAIL;
8731 break;
8732 }
8733
8734 if (!eap->skip)
8735 {
8736 p = get_var_string(&retvar);
8737 len = (int)STRLEN(p);
8738 if (ga_grow(&ga, len + 2) == FAIL)
8739 {
8740 clear_var(&retvar);
8741 ret = FAIL;
8742 break;
8743 }
8744 if (ga.ga_len)
8745 {
8746 ((char_u *)(ga.ga_data))[ga.ga_len++] = ' ';
8747 --ga.ga_room;
8748 }
8749 STRCPY((char_u *)(ga.ga_data) + ga.ga_len, p);
8750 ga.ga_room -= len;
8751 ga.ga_len += len;
8752 }
8753
8754 clear_var(&retvar);
8755 arg = skipwhite(arg);
8756 }
8757
8758 if (ret != FAIL && ga.ga_data != NULL)
8759 {
8760 if (eap->cmdidx == CMD_echomsg)
8761 MSG_ATTR(ga.ga_data, echo_attr);
8762 else if (eap->cmdidx == CMD_echoerr)
8763 {
8764 /* We don't want to abort following commands, restore did_emsg. */
8765 save_did_emsg = did_emsg;
8766 EMSG((char_u *)ga.ga_data);
8767 if (!force_abort)
8768 did_emsg = save_did_emsg;
8769 }
8770 else if (eap->cmdidx == CMD_execute)
8771 do_cmdline((char_u *)ga.ga_data,
8772 eap->getline, eap->cookie, DOCMD_NOWAIT|DOCMD_VERBOSE);
8773 }
8774
8775 ga_clear(&ga);
8776
8777 if (eap->skip)
8778 --emsg_skip;
8779
8780 eap->nextcmd = check_nextcmd(arg);
8781}
8782
8783/*
8784 * Skip over the name of an option: "&option", "&g:option" or "&l:option".
8785 * "arg" points to the "&" or '+' when called, to "option" when returning.
8786 * Returns NULL when no option name found. Otherwise pointer to the char
8787 * after the option name.
8788 */
8789 static char_u *
8790find_option_end(arg, opt_flags)
8791 char_u **arg;
8792 int *opt_flags;
8793{
8794 char_u *p = *arg;
8795
8796 ++p;
8797 if (*p == 'g' && p[1] == ':')
8798 {
8799 *opt_flags = OPT_GLOBAL;
8800 p += 2;
8801 }
8802 else if (*p == 'l' && p[1] == ':')
8803 {
8804 *opt_flags = OPT_LOCAL;
8805 p += 2;
8806 }
8807 else
8808 *opt_flags = 0;
8809
8810 if (!ASCII_ISALPHA(*p))
8811 return NULL;
8812 *arg = p;
8813
8814 if (p[0] == 't' && p[1] == '_' && p[2] != NUL && p[3] != NUL)
8815 p += 4; /* termcap option */
8816 else
8817 while (ASCII_ISALPHA(*p))
8818 ++p;
8819 return p;
8820}
8821
8822/*
8823 * ":function"
8824 */
8825 void
8826ex_function(eap)
8827 exarg_T *eap;
8828{
8829 char_u *theline;
8830 int j;
8831 int c;
8832#ifdef FEAT_MAGIC_BRACES
8833 int saved_did_emsg;
8834#endif
8835 char_u *name = NULL;
8836 char_u *p;
8837 char_u *arg;
8838 garray_T newargs;
8839 garray_T newlines;
8840 int varargs = FALSE;
8841 int mustend = FALSE;
8842 int flags = 0;
8843 ufunc_T *fp;
8844 int indent;
8845 int nesting;
8846 char_u *skip_until = NULL;
8847 static char_u e_funcexts[] = N_("E122: Function %s already exists, add ! to replace it");
8848
8849 /*
8850 * ":function" without argument: list functions.
8851 */
8852 if (ends_excmd(*eap->arg))
8853 {
8854 if (!eap->skip)
8855 for (fp = firstfunc; fp != NULL && !got_int; fp = fp->next)
8856 list_func_head(fp, FALSE);
8857 eap->nextcmd = check_nextcmd(eap->arg);
8858 return;
8859 }
8860
8861 p = eap->arg;
8862 name = trans_function_name(&p, eap->skip, FALSE);
8863 if (name == NULL && !eap->skip)
8864 {
8865 /*
8866 * Return on an invalid expression in braces, unless the expression
8867 * evaluation has been cancelled due to an aborting error, an
8868 * interrupt, or an exception.
8869 */
8870 if (!aborting())
8871 return;
8872 else
8873 eap->skip = TRUE;
8874 }
8875#ifdef FEAT_MAGIC_BRACES
8876 /* An error in a function call during evaluation of an expression in magic
8877 * braces should not cause the function not to be defined. */
8878 saved_did_emsg = did_emsg;
8879 did_emsg = FALSE;
8880#endif
8881
8882 /*
8883 * ":function func" with only function name: list function.
8884 */
8885 if (vim_strchr(p, '(') == NULL)
8886 {
8887 if (!ends_excmd(*skipwhite(p)))
8888 {
8889 EMSG(_(e_trailing));
8890 goto erret_name;
8891 }
8892 eap->nextcmd = check_nextcmd(p);
8893 if (eap->nextcmd != NULL)
8894 *p = NUL;
8895 if (!eap->skip && !got_int)
8896 {
8897 fp = find_func(name);
8898 if (fp != NULL)
8899 {
8900 list_func_head(fp, TRUE);
8901 for (j = 0; j < fp->lines.ga_len && !got_int; ++j)
8902 {
8903 msg_putchar('\n');
8904 msg_outnum((long)(j + 1));
8905 if (j < 9)
8906 msg_putchar(' ');
8907 if (j < 99)
8908 msg_putchar(' ');
8909 msg_prt_line(FUNCLINE(fp, j));
8910 out_flush(); /* show a line at a time */
8911 ui_breakcheck();
8912 }
8913 if (!got_int)
8914 {
8915 msg_putchar('\n');
8916 msg_puts((char_u *)" endfunction");
8917 }
8918 }
8919 else
8920 EMSG2(_("E123: Undefined function: %s"), eap->arg);
8921 }
8922 goto erret_name;
8923 }
8924
8925 /*
8926 * ":function name(arg1, arg2)" Define function.
8927 */
8928 p = skipwhite(p);
8929 if (*p != '(')
8930 {
8931 if (!eap->skip)
8932 {
8933 EMSG2(_("E124: Missing '(': %s"), eap->arg);
8934 goto erret_name;
8935 }
8936 /* attempt to continue by skipping some text */
8937 if (vim_strchr(p, '(') != NULL)
8938 p = vim_strchr(p, '(');
8939 }
8940 p = skipwhite(p + 1);
8941
8942 ga_init2(&newargs, (int)sizeof(char_u *), 3);
8943 ga_init2(&newlines, (int)sizeof(char_u *), 3);
8944
8945 /*
8946 * Isolate the arguments: "arg1, arg2, ...)"
8947 */
8948 while (*p != ')')
8949 {
8950 if (p[0] == '.' && p[1] == '.' && p[2] == '.')
8951 {
8952 varargs = TRUE;
8953 p += 3;
8954 mustend = TRUE;
8955 }
8956 else
8957 {
8958 arg = p;
8959 while (ASCII_ISALNUM(*p) || *p == '_')
8960 ++p;
8961 if (arg == p || isdigit(*arg)
8962 || (p - arg == 9 && STRNCMP(arg, "firstline", 9) == 0)
8963 || (p - arg == 8 && STRNCMP(arg, "lastline", 8) == 0))
8964 {
8965 if (!eap->skip)
8966 EMSG2(_("E125: Illegal argument: %s"), arg);
8967 break;
8968 }
8969 if (ga_grow(&newargs, 1) == FAIL)
8970 goto erret;
8971 c = *p;
8972 *p = NUL;
8973 arg = vim_strsave(arg);
8974 if (arg == NULL)
8975 goto erret;
8976 ((char_u **)(newargs.ga_data))[newargs.ga_len] = arg;
8977 *p = c;
8978 newargs.ga_len++;
8979 newargs.ga_room--;
8980 if (*p == ',')
8981 ++p;
8982 else
8983 mustend = TRUE;
8984 }
8985 p = skipwhite(p);
8986 if (mustend && *p != ')')
8987 {
8988 if (!eap->skip)
8989 EMSG2(_(e_invarg2), eap->arg);
8990 break;
8991 }
8992 }
8993 ++p; /* skip the ')' */
8994
8995 /* find extra arguments "range" and "abort" */
8996 for (;;)
8997 {
8998 p = skipwhite(p);
8999 if (STRNCMP(p, "range", 5) == 0)
9000 {
9001 flags |= FC_RANGE;
9002 p += 5;
9003 }
9004 else if (STRNCMP(p, "abort", 5) == 0)
9005 {
9006 flags |= FC_ABORT;
9007 p += 5;
9008 }
9009 else
9010 break;
9011 }
9012
9013 if (*p != NUL && *p != '"' && *p != '\n' && !eap->skip && !did_emsg)
9014 EMSG(_(e_trailing));
9015
9016 /*
9017 * Read the body of the function, until ":endfunction" is found.
9018 */
9019 if (KeyTyped)
9020 {
9021 /* Check if the function already exists, don't let the user type the
9022 * whole function before telling him it doesn't work! For a script we
9023 * need to skip the body to be able to find what follows. */
9024 if (!eap->skip && !eap->forceit && find_func(name) != NULL)
9025 EMSG2(_(e_funcexts), name);
9026
9027 msg_putchar('\n'); /* don't overwrite the function name */
9028 cmdline_row = msg_row;
9029 }
9030
9031 indent = 2;
9032 nesting = 0;
9033 for (;;)
9034 {
9035 msg_scroll = TRUE;
9036 need_wait_return = FALSE;
9037 if (eap->getline == NULL)
9038 theline = getcmdline(':', 0L, indent);
9039 else
9040 theline = eap->getline(':', eap->cookie, indent);
9041 if (KeyTyped)
9042 lines_left = Rows - 1;
9043 if (theline == NULL)
9044 {
9045 EMSG(_("E126: Missing :endfunction"));
9046 goto erret;
9047 }
9048
9049 if (skip_until != NULL)
9050 {
9051 /* between ":append" and "." and between ":python <<EOF" and "EOF"
9052 * don't check for ":endfunc". */
9053 if (STRCMP(theline, skip_until) == 0)
9054 {
9055 vim_free(skip_until);
9056 skip_until = NULL;
9057 }
9058 }
9059 else
9060 {
9061 /* skip ':' and blanks*/
9062 for (p = theline; vim_iswhite(*p) || *p == ':'; ++p)
9063 ;
9064
9065 /* Check for "endfunction" (should be more strict...). */
9066 if (STRNCMP(p, "endf", 4) == 0 && nesting-- == 0)
9067 {
9068 vim_free(theline);
9069 break;
9070 }
9071
9072 /* Increase indent inside "if", "while", and "try", decrease
9073 * at "end". */
9074 if (indent > 2 && STRNCMP(p, "end", 3) == 0)
9075 indent -= 2;
9076 else if (STRNCMP(p, "if", 2) == 0 || STRNCMP(p, "wh", 2) == 0
9077 || STRNCMP(p, "try", 3) == 0)
9078 indent += 2;
9079
9080 /* Check for defining a function inside this function. */
9081 if (STRNCMP(p, "fu", 2) == 0)
9082 {
9083 p = skipwhite(skiptowhite(p));
9084 p += eval_fname_script(p);
9085 if (ASCII_ISALPHA(*p))
9086 {
9087 vim_free(trans_function_name(&p, TRUE, FALSE));
9088 if (*skipwhite(p) == '(')
9089 {
9090 ++nesting;
9091 indent += 2;
9092 }
9093 }
9094 }
9095
9096 /* Check for ":append" or ":insert". */
9097 p = skip_range(p, NULL);
9098 if ((p[0] == 'a' && (!ASCII_ISALPHA(p[1]) || p[1] == 'p'))
9099 || (p[0] == 'i'
9100 && (!ASCII_ISALPHA(p[1]) || (p[1] == 'n'
9101 && (!ASCII_ISALPHA(p[2]) || (p[2] == 's'))))))
9102 skip_until = vim_strsave((char_u *)".");
9103
9104 /* Check for ":python <<EOF", ":tcl <<EOF", etc. */
9105 arg = skipwhite(skiptowhite(p));
9106 if (arg[0] == '<' && arg[1] =='<'
9107 && ((p[0] == 'p' && p[1] == 'y'
9108 && (!ASCII_ISALPHA(p[2]) || p[2] == 't'))
9109 || (p[0] == 'p' && p[1] == 'e'
9110 && (!ASCII_ISALPHA(p[2]) || p[2] == 'r'))
9111 || (p[0] == 't' && p[1] == 'c'
9112 && (!ASCII_ISALPHA(p[2]) || p[2] == 'l'))
9113 || (p[0] == 'r' && p[1] == 'u' && p[2] == 'b'
9114 && (!ASCII_ISALPHA(p[3]) || p[3] == 'y'))
Bram Moolenaar325b7a22004-07-05 15:58:32 +00009115 || (p[0] == 'm' && p[1] == 'z'
9116 && (!ASCII_ISALPHA(p[2]) || p[2] == 's'))
Bram Moolenaar071d4272004-06-13 20:20:40 +00009117 ))
9118 {
9119 /* ":python <<" continues until a dot, like ":append" */
9120 p = skipwhite(arg + 2);
9121 if (*p == NUL)
9122 skip_until = vim_strsave((char_u *)".");
9123 else
9124 skip_until = vim_strsave(p);
9125 }
9126 }
9127
9128 /* Add the line to the function. */
9129 if (ga_grow(&newlines, 1) == FAIL)
9130 goto erret;
9131 ((char_u **)(newlines.ga_data))[newlines.ga_len] = theline;
9132 newlines.ga_len++;
9133 newlines.ga_room--;
9134 }
9135
9136 /* Don't define the function when skipping commands or when an error was
9137 * detected. */
9138 if (eap->skip || did_emsg)
9139 goto erret;
9140
9141 /*
9142 * If there are no errors, add the function
9143 */
9144 fp = find_func(name);
9145 if (fp != NULL)
9146 {
9147 if (!eap->forceit)
9148 {
9149 EMSG2(_(e_funcexts), name);
9150 goto erret;
9151 }
9152 if (fp->calls)
9153 {
9154 EMSG2(_("E127: Cannot redefine function %s: It is in use"), name);
9155 goto erret;
9156 }
9157 /* redefine existing function */
9158 ga_clear_strings(&(fp->args));
9159 ga_clear_strings(&(fp->lines));
9160 vim_free(name);
9161 }
9162 else
9163 {
9164 fp = (ufunc_T *)alloc((unsigned)sizeof(ufunc_T));
9165 if (fp == NULL)
9166 goto erret;
9167 /* insert the new function in the function list */
9168 fp->next = firstfunc;
9169 firstfunc = fp;
9170 fp->name = name;
9171 }
9172 fp->args = newargs;
9173 fp->lines = newlines;
9174 fp->varargs = varargs;
9175 fp->flags = flags;
9176 fp->calls = 0;
9177 fp->script_ID = current_SID;
9178#ifdef FEAT_MAGIC_BRACES
9179 did_emsg |= saved_did_emsg;
9180#endif
9181 vim_free(skip_until);
9182 return;
9183
9184erret:
9185 vim_free(skip_until);
9186 ga_clear_strings(&newargs);
9187 ga_clear_strings(&newlines);
9188erret_name:
9189 vim_free(name);
9190#ifdef FEAT_MAGIC_BRACES
9191 did_emsg |= saved_did_emsg;
9192#endif
9193}
9194
9195/*
9196 * Get a function name, translating "<SID>" and "<SNR>".
9197 * Returns the function name in allocated memory, or NULL for failure.
9198 * Advances "pp" to just after the function name (if no error).
9199 */
9200 static char_u *
9201trans_function_name(pp, skip, internal)
9202 char_u **pp;
9203 int skip; /* only find the end, don't evaluate */
9204 int internal; /* TRUE if internal function name OK */
9205{
9206 char_u *name;
9207 char_u *start;
9208 char_u *end;
9209 int lead;
9210 char_u sid_buf[20];
9211 char_u *temp_string = NULL;
9212 char_u *expr_start, *expr_end;
9213 int len;
9214
9215 /* A name starting with "<SID>" or "<SNR>" is local to a script. */
9216 start = *pp;
9217 lead = eval_fname_script(start);
9218 if (lead > 0)
9219 start += lead;
9220 end = find_name_end(start, &expr_start, &expr_end);
9221 if (end == start)
9222 {
9223 if (!skip)
9224 EMSG(_("E129: Function name required"));
9225 return NULL;
9226 }
9227#ifdef FEAT_MAGIC_BRACES
9228 if (expr_start != NULL && !skip)
9229 {
9230 /* expand magic curlies */
9231 temp_string = make_expanded_name(start, expr_start, expr_end, end);
9232 if (temp_string == NULL)
9233 {
9234 /*
9235 * Report an invalid expression in braces, unless the expression
9236 * evaluation has been cancelled due to an aborting error, an
9237 * interrupt, or an exception.
9238 */
9239 if (!aborting())
9240 EMSG2(_(e_invarg2), start);
9241 else
9242 *pp = end;
9243 return NULL;
9244 }
9245 start = temp_string;
9246 len = (int)STRLEN(temp_string);
9247 }
9248 else
9249#endif
9250 len = (int)(end - start);
9251
9252 /*
9253 * Copy the function name to allocated memory.
9254 * Accept <SID>name() inside a script, translate into <SNR>123_name().
9255 * Accept <SNR>123_name() outside a script.
9256 */
9257 if (skip)
9258 lead = 0; /* do nothing */
9259 else if (lead > 0)
9260 {
9261 lead = 3;
9262 if (eval_fname_sid(*pp)) /* If it's "<SID>" */
9263 {
9264 if (current_SID <= 0)
9265 {
9266 EMSG(_(e_usingsid));
9267 return NULL;
9268 }
9269 sprintf((char *)sid_buf, "%ld_", (long)current_SID);
9270 lead += (int)STRLEN(sid_buf);
9271 }
9272 }
9273 else if (!internal && !ASCII_ISUPPER(*start))
9274 {
9275 EMSG2(_("E128: Function name must start with a capital: %s"), start);
9276 return NULL;
9277 }
9278 name = alloc((unsigned)(len + lead + 1));
9279 if (name != NULL)
9280 {
9281 if (lead > 0)
9282 {
9283 name[0] = K_SPECIAL;
9284 name[1] = KS_EXTRA;
9285 name[2] = (int)KE_SNR;
9286 if (eval_fname_sid(*pp)) /* If it's "<SID>" */
9287 STRCPY(name + 3, sid_buf);
9288 }
9289 mch_memmove(name + lead, start, (size_t)len);
9290 name[len + lead] = NUL;
9291 }
9292 *pp = end;
9293
9294 vim_free(temp_string);
9295 return name;
9296}
9297
9298/*
9299 * Return 5 if "p" starts with "<SID>" or "<SNR>" (ignoring case).
9300 * Return 2 if "p" starts with "s:".
9301 * Return 0 otherwise.
9302 */
9303 static int
9304eval_fname_script(p)
9305 char_u *p;
9306{
9307 if (p[0] == '<' && (STRNICMP(p + 1, "SID>", 4) == 0
9308 || STRNICMP(p + 1, "SNR>", 4) == 0))
9309 return 5;
9310 if (p[0] == 's' && p[1] == ':')
9311 return 2;
9312 return 0;
9313}
9314
9315/*
9316 * Return TRUE if "p" starts with "<SID>" or "s:".
9317 * Only works if eval_fname_script() returned non-zero for "p"!
9318 */
9319 static int
9320eval_fname_sid(p)
9321 char_u *p;
9322{
9323 return (*p == 's' || TOUPPER_ASC(p[2]) == 'I');
9324}
9325
9326/*
9327 * List the head of the function: "name(arg1, arg2)".
9328 */
9329 static void
9330list_func_head(fp, indent)
9331 ufunc_T *fp;
9332 int indent;
9333{
9334 int j;
9335
9336 msg_start();
9337 if (indent)
9338 MSG_PUTS(" ");
9339 MSG_PUTS("function ");
9340 if (fp->name[0] == K_SPECIAL)
9341 {
9342 MSG_PUTS_ATTR("<SNR>", hl_attr(HLF_8));
9343 msg_puts(fp->name + 3);
9344 }
9345 else
9346 msg_puts(fp->name);
9347 msg_putchar('(');
9348 for (j = 0; j < fp->args.ga_len; ++j)
9349 {
9350 if (j)
9351 MSG_PUTS(", ");
9352 msg_puts(FUNCARG(fp, j));
9353 }
9354 if (fp->varargs)
9355 {
9356 if (j)
9357 MSG_PUTS(", ");
9358 MSG_PUTS("...");
9359 }
9360 msg_putchar(')');
9361}
9362
9363/*
9364 * Find a function by name, return pointer to it in ufuncs.
9365 * Return NULL for unknown function.
9366 */
9367 static ufunc_T *
9368find_func(name)
9369 char_u *name;
9370{
9371 ufunc_T *fp;
9372
9373 for (fp = firstfunc; fp != NULL; fp = fp->next)
9374 if (STRCMP(name, fp->name) == 0)
9375 break;
9376 return fp;
9377}
9378
9379#if defined(FEAT_CMDL_COMPL) || defined(PROTO)
9380
9381/*
9382 * Function given to ExpandGeneric() to obtain the list of user defined
9383 * function names.
9384 */
9385 char_u *
9386get_user_func_name(xp, idx)
9387 expand_T *xp;
9388 int idx;
9389{
9390 static ufunc_T *fp = NULL;
9391
9392 if (idx == 0)
9393 fp = firstfunc;
9394 if (fp != NULL)
9395 {
9396 if (STRLEN(fp->name) + 4 >= IOSIZE)
9397 return fp->name; /* prevents overflow */
9398
9399 cat_func_name(IObuff, fp);
9400 if (xp->xp_context != EXPAND_USER_FUNC)
9401 {
9402 STRCAT(IObuff, "(");
9403 if (!fp->varargs && fp->args.ga_len == 0)
9404 STRCAT(IObuff, ")");
9405 }
9406
9407 fp = fp->next;
9408 return IObuff;
9409 }
9410 return NULL;
9411}
9412
9413#endif /* FEAT_CMDL_COMPL */
9414
9415/*
9416 * Copy the function name of "fp" to buffer "buf".
9417 * "buf" must be able to hold the function name plus three bytes.
9418 * Takes care of script-local function names.
9419 */
9420 static void
9421cat_func_name(buf, fp)
9422 char_u *buf;
9423 ufunc_T *fp;
9424{
9425 if (fp->name[0] == K_SPECIAL)
9426 {
9427 STRCPY(buf, "<SNR>");
9428 STRCAT(buf, fp->name + 3);
9429 }
9430 else
9431 STRCPY(buf, fp->name);
9432}
9433
9434/*
9435 * ":delfunction {name}"
9436 */
9437 void
9438ex_delfunction(eap)
9439 exarg_T *eap;
9440{
9441 ufunc_T *fp = NULL, *pfp;
9442 char_u *p;
9443 char_u *name;
9444
9445 p = eap->arg;
9446 name = trans_function_name(&p, eap->skip, FALSE);
9447 if (name == NULL)
9448 return;
9449 if (!ends_excmd(*skipwhite(p)))
9450 {
9451 vim_free(name);
9452 EMSG(_(e_trailing));
9453 return;
9454 }
9455 eap->nextcmd = check_nextcmd(p);
9456 if (eap->nextcmd != NULL)
9457 *p = NUL;
9458
9459 if (!eap->skip)
9460 fp = find_func(name);
9461 vim_free(name);
9462
9463 if (!eap->skip)
9464 {
9465 if (fp == NULL)
9466 {
9467 EMSG2(_("E130: Undefined function: %s"), eap->arg);
9468 return;
9469 }
9470 if (fp->calls)
9471 {
9472 EMSG2(_("E131: Cannot delete function %s: It is in use"), eap->arg);
9473 return;
9474 }
9475
9476 /* clear this function */
9477 vim_free(fp->name);
9478 ga_clear_strings(&(fp->args));
9479 ga_clear_strings(&(fp->lines));
9480
9481 /* remove the function from the function list */
9482 if (firstfunc == fp)
9483 firstfunc = fp->next;
9484 else
9485 {
9486 for (pfp = firstfunc; pfp != NULL; pfp = pfp->next)
9487 if (pfp->next == fp)
9488 {
9489 pfp->next = fp->next;
9490 break;
9491 }
9492 }
9493 vim_free(fp);
9494 }
9495}
9496
9497/*
9498 * Call a user function.
9499 */
9500 static void
9501call_user_func(fp, argcount, argvars, retvar, firstline, lastline)
9502 ufunc_T *fp; /* pointer to function */
9503 int argcount; /* nr of args */
9504 VAR argvars; /* arguments */
9505 VAR retvar; /* return value */
9506 linenr_T firstline; /* first line of range */
9507 linenr_T lastline; /* last line of range */
9508{
9509 char_u *save_sourcing_name;
9510 linenr_T save_sourcing_lnum;
9511 scid_T save_current_SID;
9512 struct funccall fc;
9513 struct funccall *save_fcp = current_funccal;
9514 int save_did_emsg;
9515 static int depth = 0;
9516
9517 /* If depth of calling is getting too high, don't execute the function */
9518 if (depth >= p_mfd)
9519 {
9520 EMSG(_("E132: Function call depth is higher than 'maxfuncdepth'"));
9521 retvar->var_type = VAR_NUMBER;
9522 retvar->var_val.var_number = -1;
9523 return;
9524 }
9525 ++depth;
9526
9527 line_breakcheck(); /* check for CTRL-C hit */
9528
9529 /* set local variables */
9530 var_init(&fc.l_vars);
9531 fc.func = fp;
9532 fc.argcount = argcount;
9533 fc.argvars = argvars;
9534 fc.retvar = retvar;
9535 retvar->var_val.var_number = 0;
9536 fc.linenr = 0;
9537 fc.returned = FALSE;
9538 fc.level = ex_nesting_level;
9539 fc.a0_var.var_type = VAR_NUMBER;
9540 fc.a0_var.var_val.var_number = argcount - fp->args.ga_len;
9541 fc.a0_var.var_name = NULL;
9542 current_funccal = &fc;
9543 fc.firstline.var_type = VAR_NUMBER;
9544 fc.firstline.var_val.var_number = firstline;
9545 fc.firstline.var_name = NULL;
9546 fc.lastline.var_type = VAR_NUMBER;
9547 fc.lastline.var_val.var_number = lastline;
9548 fc.lastline.var_name = NULL;
9549 /* Check if this function has a breakpoint. */
9550 fc.breakpoint = dbg_find_breakpoint(FALSE, fp->name, (linenr_T)0);
9551 fc.dbg_tick = debug_tick;
9552
9553 /* Don't redraw while executing the function. */
9554 ++RedrawingDisabled;
9555 save_sourcing_name = sourcing_name;
9556 save_sourcing_lnum = sourcing_lnum;
9557 sourcing_lnum = 1;
9558 sourcing_name = alloc((unsigned)((save_sourcing_name == NULL ? 0
9559 : STRLEN(save_sourcing_name)) + STRLEN(fp->name) + 13));
9560 if (sourcing_name != NULL)
9561 {
9562 if (save_sourcing_name != NULL
9563 && STRNCMP(save_sourcing_name, "function ", 9) == 0)
9564 sprintf((char *)sourcing_name, "%s..", save_sourcing_name);
9565 else
9566 STRCPY(sourcing_name, "function ");
9567 cat_func_name(sourcing_name + STRLEN(sourcing_name), fp);
9568
9569 if (p_verbose >= 12)
9570 {
9571 ++no_wait_return;
9572 msg_scroll = TRUE; /* always scroll up, don't overwrite */
9573 msg_str((char_u *)_("calling %s"), sourcing_name);
9574 if (p_verbose >= 14)
9575 {
9576 int i;
9577 char_u buf[MSG_BUF_LEN];
9578
9579 msg_puts((char_u *)"(");
9580 for (i = 0; i < argcount; ++i)
9581 {
9582 if (i > 0)
9583 msg_puts((char_u *)", ");
9584 if (argvars[i].var_type == VAR_NUMBER)
9585 msg_outnum((long)argvars[i].var_val.var_number);
9586 else
9587 {
9588 trunc_string(get_var_string(&argvars[i]),
9589 buf, MSG_BUF_LEN);
9590 msg_puts((char_u *)"\"");
9591 msg_puts(buf);
9592 msg_puts((char_u *)"\"");
9593 }
9594 }
9595 msg_puts((char_u *)")");
9596 }
9597 msg_puts((char_u *)"\n"); /* don't overwrite this either */
9598 cmdline_row = msg_row;
9599 --no_wait_return;
9600 }
9601 }
9602 save_current_SID = current_SID;
9603 current_SID = fp->script_ID;
9604 save_did_emsg = did_emsg;
9605 did_emsg = FALSE;
9606
9607 /* call do_cmdline() to execute the lines */
9608 do_cmdline(NULL, get_func_line, (void *)&fc,
9609 DOCMD_NOWAIT|DOCMD_VERBOSE|DOCMD_REPEAT);
9610
9611 --RedrawingDisabled;
9612
9613 /* when the function was aborted because of an error, return -1 */
9614 if ((did_emsg && (fp->flags & FC_ABORT)) || retvar->var_type == VAR_UNKNOWN)
9615 {
9616 clear_var(retvar);
9617 retvar->var_type = VAR_NUMBER;
9618 retvar->var_val.var_number = -1;
9619 }
9620
9621 /* when being verbose, mention the return value */
9622 if (p_verbose >= 12)
9623 {
9624 char_u *sn, *val;
9625
9626 ++no_wait_return;
9627 msg_scroll = TRUE; /* always scroll up, don't overwrite */
9628
9629 /* Make sure the output fits in IObuff. */
9630 sn = sourcing_name;
9631 if (STRLEN(sourcing_name) > IOSIZE / 2 - 50)
9632 sn = sourcing_name + STRLEN(sourcing_name) - (IOSIZE / 2 - 50);
9633
9634 if (aborting())
9635 smsg((char_u *)_("%s aborted"), sn);
9636 else if (fc.retvar->var_type == VAR_NUMBER)
9637 smsg((char_u *)_("%s returning #%ld"), sn,
9638 (long)fc.retvar->var_val.var_number);
9639 else if (fc.retvar->var_type == VAR_STRING)
9640 {
9641 val = get_var_string(fc.retvar);
9642 if (STRLEN(val) > IOSIZE / 2 - 50)
9643 val = val + STRLEN(val) - (IOSIZE / 2 - 50);
9644 smsg((char_u *)_("%s returning \"%s\""), sn, val);
9645 }
9646 msg_puts((char_u *)"\n"); /* don't overwrite this either */
9647 cmdline_row = msg_row;
9648 --no_wait_return;
9649 }
9650
9651 vim_free(sourcing_name);
9652 sourcing_name = save_sourcing_name;
9653 sourcing_lnum = save_sourcing_lnum;
9654 current_SID = save_current_SID;
9655
9656 if (p_verbose >= 12 && sourcing_name != NULL)
9657 {
9658 ++no_wait_return;
9659 msg_scroll = TRUE; /* always scroll up, don't overwrite */
9660 msg_str((char_u *)_("continuing in %s"), sourcing_name);
9661 msg_puts((char_u *)"\n"); /* don't overwrite this either */
9662 cmdline_row = msg_row;
9663 --no_wait_return;
9664 }
9665
9666 did_emsg |= save_did_emsg;
9667 current_funccal = save_fcp;
9668
9669 var_clear(&fc.l_vars); /* free all local variables */
9670 --depth;
9671}
9672
9673/*
9674 * ":return [expr]"
9675 */
9676 void
9677ex_return(eap)
9678 exarg_T *eap;
9679{
9680 char_u *arg = eap->arg;
9681 var retvar;
9682 int returning = FALSE;
9683
9684 if (current_funccal == NULL)
9685 {
9686 EMSG(_("E133: :return not inside a function"));
9687 return;
9688 }
9689
9690 if (eap->skip)
9691 ++emsg_skip;
9692
9693 eap->nextcmd = NULL;
9694 if ((*arg != NUL && *arg != '|' && *arg != '\n')
9695 && eval0(arg, &retvar, &eap->nextcmd, !eap->skip) != FAIL)
9696 {
9697 if (!eap->skip)
9698 returning = do_return(eap, FALSE, TRUE, &retvar);
9699 else
9700 clear_var(&retvar);
9701 }
9702 /* It's safer to return also on error. */
9703 else if (!eap->skip)
9704 {
9705 /*
9706 * Return unless the expression evaluation has been cancelled due to an
9707 * aborting error, an interrupt, or an exception.
9708 */
9709 if (!aborting())
9710 returning = do_return(eap, FALSE, TRUE, NULL);
9711 }
9712
9713 /* When skipping or the return gets pending, advance to the next command
9714 * in this line (!returning). Otherwise, ignore the rest of the line.
9715 * Following lines will be ignored by get_func_line(). */
9716 if (returning)
9717 eap->nextcmd = NULL;
9718 else if (eap->nextcmd == NULL) /* no argument */
9719 eap->nextcmd = check_nextcmd(arg);
9720
9721 if (eap->skip)
9722 --emsg_skip;
9723}
9724
9725/*
9726 * Return from a function. Possibly makes the return pending. Also called
9727 * for a pending return at the ":endtry" or after returning from an extra
9728 * do_cmdline(). "reanimate" is used in the latter case. "is_cmd" is set
9729 * when called due to a ":return" command. "value" may point to a variable
9730 * with the return value. Returns TRUE when the return can be carried out,
9731 * FALSE when the return gets pending.
9732 */
9733 int
9734do_return(eap, reanimate, is_cmd, value)
9735 exarg_T *eap;
9736 int reanimate;
9737 int is_cmd;
9738 void *value;
9739{
9740 int idx;
9741 struct condstack *cstack = eap->cstack;
9742
9743 if (reanimate)
9744 /* Undo the return. */
9745 current_funccal->returned = FALSE;
9746
9747 /*
9748 * Cleanup (and inactivate) conditionals, but stop when a try conditional
9749 * not in its finally clause (which then is to be executed next) is found.
9750 * In this case, make the ":return" pending for execution at the ":endtry".
9751 * Otherwise, return normally.
9752 */
9753 idx = cleanup_conditionals(eap->cstack, 0, TRUE);
9754 if (idx >= 0)
9755 {
9756 cstack->cs_pending[idx] = CSTP_RETURN;
9757
9758 if (!is_cmd && !reanimate)
9759 /* A pending return again gets pending. "value" points to an
9760 * allocated variable with the value of the original ":return"'s
9761 * argument if present or is NULL else. */
9762 cstack->cs_retvar[idx] = value;
9763 else
9764 {
9765 /* When undoing a return in order to make it pending, get the stored
9766 * return value. */
9767 if (reanimate)
9768 value = current_funccal->retvar;
9769
9770 if (value != NULL)
9771 {
9772 /* Store the value of the pending return. */
9773 if ((cstack->cs_retvar[idx] = alloc_var()) != NULL)
9774 *(VAR)cstack->cs_retvar[idx] = *(VAR)value;
9775 else
9776 EMSG(_(e_outofmem));
9777 }
9778 else
9779 cstack->cs_retvar[idx] = NULL;
9780
9781 if (reanimate)
9782 {
9783 /* The pending return value could be overwritten by a ":return"
9784 * without argument in a finally clause; reset the default
9785 * return value. */
9786 current_funccal->retvar->var_type = VAR_NUMBER;
9787 current_funccal->retvar->var_val.var_number = 0;
9788 }
9789 }
9790 report_make_pending(CSTP_RETURN, value);
9791 }
9792 else
9793 {
9794 current_funccal->returned = TRUE;
9795
9796 /* If the return is carried out now, store the return value. For
9797 * a return immediately after reanimation, the value is already
9798 * there. */
9799 if (!reanimate && value != NULL)
9800 {
9801 clear_var(current_funccal->retvar);
9802 *current_funccal->retvar = *(VAR)value;
9803 if (!is_cmd)
9804 vim_free(value);
9805 }
9806 }
9807
9808 return idx < 0;
9809}
9810
9811/*
9812 * Free the variable with a pending return value.
9813 */
9814 void
9815discard_pending_return(retvar)
9816 void *retvar;
9817{
9818 /* The variable was copied from one with an undefined var_name. So we can't
9819 * use free_var() to clear and free it. */
9820 clear_var((VAR)retvar);
9821 vim_free(retvar);
9822}
9823
9824/*
9825 * Generate a return command for producing the value of "retvar". The result
9826 * is an allocated string. Used by report_pending() for verbose messages.
9827 */
9828 char_u *
9829get_return_cmd(retvar)
9830 void *retvar;
9831{
9832 char_u *s = IObuff;
9833
9834 if (retvar == NULL || ((VAR)retvar)->var_type == VAR_UNKNOWN)
9835 s = (char_u *)":return";
9836 else if (((VAR)retvar)->var_type == VAR_STRING)
9837 sprintf((char *)IObuff, ":return \"%s\"",
9838 ((VAR)retvar)->var_val.var_string);
9839 else
9840 sprintf((char *)IObuff, ":return %ld",
9841 (long)(((VAR)retvar)->var_val.var_number));
9842 return vim_strsave(s);
9843}
9844
9845/*
9846 * Get next function line.
9847 * Called by do_cmdline() to get the next line.
9848 * Returns allocated string, or NULL for end of function.
9849 */
9850/* ARGSUSED */
9851 char_u *
9852get_func_line(c, cookie, indent)
9853 int c; /* not used */
9854 void *cookie;
9855 int indent; /* not used */
9856{
9857 struct funccall *fcp = (struct funccall *)cookie;
9858 char_u *retval;
9859 garray_T *gap; /* growarray with function lines */
9860
9861 /* If breakpoints have been added/deleted need to check for it. */
9862 if (fcp->dbg_tick != debug_tick)
9863 {
9864 fcp->breakpoint = dbg_find_breakpoint(FALSE, fcp->func->name,
9865 sourcing_lnum);
9866 fcp->dbg_tick = debug_tick;
9867 }
9868
9869 gap = &fcp->func->lines;
9870 if ((fcp->func->flags & FC_ABORT) && did_emsg && !aborted_in_try())
9871 retval = NULL;
9872 else if (fcp->returned || fcp->linenr >= gap->ga_len)
9873 retval = NULL;
9874 else
9875 {
9876 retval = vim_strsave(((char_u **)(gap->ga_data))[fcp->linenr++]);
9877 sourcing_lnum = fcp->linenr;
9878 }
9879
9880 /* Did we encounter a breakpoint? */
9881 if (fcp->breakpoint != 0 && fcp->breakpoint <= sourcing_lnum)
9882 {
9883 dbg_breakpoint(fcp->func->name, sourcing_lnum);
9884 /* Find next breakpoint. */
9885 fcp->breakpoint = dbg_find_breakpoint(FALSE, fcp->func->name,
9886 sourcing_lnum);
9887 fcp->dbg_tick = debug_tick;
9888 }
9889
9890 return retval;
9891}
9892
9893/*
9894 * Return TRUE if the currently active function should be ended, because a
9895 * return was encountered or an error occured. Used inside a ":while".
9896 */
9897 int
9898func_has_ended(cookie)
9899 void *cookie;
9900{
9901 struct funccall *fcp = (struct funccall *)cookie;
9902
9903 /* Ignore the "abort" flag if the abortion behavior has been changed due to
9904 * an error inside a try conditional. */
9905 return (((fcp->func->flags & FC_ABORT) && did_emsg && !aborted_in_try())
9906 || fcp->returned);
9907}
9908
9909/*
9910 * return TRUE if cookie indicates a function which "abort"s on errors.
9911 */
9912 int
9913func_has_abort(cookie)
9914 void *cookie;
9915{
9916 return ((struct funccall *)cookie)->func->flags & FC_ABORT;
9917}
9918
9919#if defined(FEAT_VIMINFO) || defined(FEAT_SESSION)
9920typedef enum
9921{
9922 VAR_FLAVOUR_DEFAULT,
9923 VAR_FLAVOUR_SESSION,
9924 VAR_FLAVOUR_VIMINFO
9925} var_flavour_T;
9926
9927static var_flavour_T var_flavour __ARGS((char_u *varname));
9928
9929 static var_flavour_T
9930var_flavour(varname)
9931 char_u *varname;
9932{
9933 char_u *p = varname;
9934
9935 if (ASCII_ISUPPER(*p))
9936 {
9937 while (*(++p))
9938 if (ASCII_ISLOWER(*p))
9939 return VAR_FLAVOUR_SESSION;
9940 return VAR_FLAVOUR_VIMINFO;
9941 }
9942 else
9943 return VAR_FLAVOUR_DEFAULT;
9944}
9945#endif
9946
9947#if defined(FEAT_VIMINFO) || defined(PROTO)
9948/*
9949 * Restore global vars that start with a capital from the viminfo file
9950 */
9951 int
9952read_viminfo_varlist(virp, writing)
9953 vir_T *virp;
9954 int writing;
9955{
9956 char_u *tab;
9957 int is_string = FALSE;
9958 VAR varp = NULL;
9959 char_u *val;
9960
9961 if (!writing && (find_viminfo_parameter('!') != NULL))
9962 {
9963 tab = vim_strchr(virp->vir_line + 1, '\t');
9964 if (tab != NULL)
9965 {
9966 *tab++ = '\0'; /* isolate the variable name */
9967 if (*tab == 'S') /* string var */
9968 is_string = TRUE;
9969
9970 tab = vim_strchr(tab, '\t');
9971 if (tab != NULL)
9972 {
9973 /* create a nameless variable to hold the value */
9974 if (is_string)
9975 {
9976 val = viminfo_readstring(virp,
9977 (int)(tab - virp->vir_line + 1), TRUE);
9978 if (val != NULL)
9979 varp = alloc_string_var(val);
9980 }
9981 else
9982 {
9983 varp = alloc_var();
9984 if (varp != NULL)
9985 {
9986 varp->var_type = VAR_NUMBER;
9987 varp->var_val.var_number = atol((char *)tab + 1);
9988 }
9989 }
9990 /* assign the value to the variable */
9991 if (varp != NULL)
9992 {
9993 set_var(virp->vir_line + 1, varp);
9994 free_var(varp);
9995 }
9996 }
9997 }
9998 }
9999
10000 return viminfo_readline(virp);
10001}
10002
10003/*
10004 * Write global vars that start with a capital to the viminfo file
10005 */
10006 void
10007write_viminfo_varlist(fp)
10008 FILE *fp;
10009{
10010 garray_T *gap = &variables; /* global variable */
10011 VAR this_var;
10012 int i;
10013
10014 if (find_viminfo_parameter('!') == NULL)
10015 return;
10016
10017 fprintf(fp, _("\n# global variables:\n"));
10018 for (i = gap->ga_len; --i >= 0; )
10019 {
10020 this_var = &VAR_GAP_ENTRY(i, gap);
10021 if (this_var->var_name != NULL
10022 && var_flavour(this_var->var_name) == VAR_FLAVOUR_VIMINFO)
10023 {
10024 fprintf(fp, "!%s\t%s\t", this_var->var_name,
10025 (this_var->var_type == VAR_STRING) ? "STR" : "NUM");
10026 viminfo_writestring(fp, get_var_string(this_var));
10027 }
10028 }
10029}
10030#endif
10031
10032#if defined(FEAT_SESSION) || defined(PROTO)
10033 int
10034store_session_globals(fd)
10035 FILE *fd;
10036{
10037 garray_T *gap = &variables; /* global variable */
10038 VAR this_var;
10039 int i;
10040 char_u *p, *t;
10041
10042 for (i = gap->ga_len; --i >= 0; )
10043 {
10044 this_var = &VAR_GAP_ENTRY(i, gap);
10045 if (this_var->var_name != NULL)
10046 {
10047 if (var_flavour(this_var->var_name) == VAR_FLAVOUR_SESSION)
10048 {
10049 /* Escapse special characters with a backslash. Turn a LF and
10050 * CR into \n and \r. */
10051 p = vim_strsave_escaped(get_var_string(this_var),
10052 (char_u *)"\\\"\n\r");
10053 if (p == NULL) /* out of memory */
10054 continue;
10055 for (t = p; *t != NUL; ++t)
10056 if (*t == '\n')
10057 *t = 'n';
10058 else if (*t == '\r')
10059 *t = 'r';
10060 if ((fprintf(fd, "let %s = %c%s%c",
10061 this_var->var_name,
10062 (this_var->var_type == VAR_STRING) ? '"' : ' ',
10063 p,
10064 (this_var->var_type == VAR_STRING) ? '"' : ' ') < 0)
10065 || put_eol(fd) == FAIL)
10066 {
10067 vim_free(p);
10068 return FAIL;
10069 }
10070 vim_free(p);
10071 }
10072
10073 }
10074 }
10075 return OK;
10076}
10077#endif
10078
10079#endif /* FEAT_EVAL */
10080
10081#if defined(FEAT_MODIFY_FNAME) || defined(FEAT_EVAL) || defined(PROTO)
10082
10083
10084#ifdef WIN3264
10085/*
10086 * Functions for ":8" filename modifier: get 8.3 version of a filename.
10087 */
10088static int get_short_pathname __ARGS((char_u **fnamep, char_u **bufp, int *fnamelen));
10089static int shortpath_for_invalid_fname __ARGS((char_u **fname, char_u **bufp, int *fnamelen));
10090static int shortpath_for_partial __ARGS((char_u **fnamep, char_u **bufp, int *fnamelen));
10091
10092/*
10093 * Get the short pathname of a file.
10094 * Returns 1 on success. *fnamelen is 0 for nonexistant path.
10095 */
10096 static int
10097get_short_pathname(fnamep, bufp, fnamelen)
10098 char_u **fnamep;
10099 char_u **bufp;
10100 int *fnamelen;
10101{
10102 int l,len;
10103 char_u *newbuf;
10104
10105 len = *fnamelen;
10106
10107 l = GetShortPathName(*fnamep, *fnamep, len);
10108 if (l > len - 1)
10109 {
10110 /* If that doesn't work (not enough space), then save the string
10111 * and try again with a new buffer big enough
10112 */
10113 newbuf = vim_strnsave(*fnamep, l);
10114 if (newbuf == NULL)
10115 return 0;
10116
10117 vim_free(*bufp);
10118 *fnamep = *bufp = newbuf;
10119
10120 l = GetShortPathName(*fnamep,*fnamep,l+1);
10121
10122 /* Really should always succeed, as the buffer is big enough */
10123 }
10124
10125 *fnamelen = l;
10126 return 1;
10127}
10128
10129/*
10130 * Create a short path name. Returns the length of the buffer it needs.
10131 * Doesn't copy over the end of the buffer passed in.
10132 */
10133 static int
10134shortpath_for_invalid_fname(fname, bufp, fnamelen)
10135 char_u **fname;
10136 char_u **bufp;
10137 int *fnamelen;
10138{
10139 char_u *s, *p, *pbuf2, *pbuf3;
10140 char_u ch;
10141 int l,len,len2,plen,slen;
10142
10143 /* Make a copy */
10144 len2 = *fnamelen;
10145 pbuf2 = vim_strnsave(*fname, len2);
10146 pbuf3 = NULL;
10147
10148 s = pbuf2 + len2 - 1; /* Find the end */
10149 slen = 1;
10150 plen = len2;
10151
10152 l = 0;
10153 if (vim_ispathsep(*s))
10154 {
10155 --s;
10156 ++slen;
10157 --plen;
10158 }
10159
10160 do
10161 {
10162 /* Go back one path-seperator */
10163 while (s > pbuf2 && !vim_ispathsep(*s))
10164 {
10165 --s;
10166 ++slen;
10167 --plen;
10168 }
10169 if (s <= pbuf2)
10170 break;
10171
10172 /* Remeber the character that is about to be blatted */
10173 ch = *s;
10174 *s = 0; /* get_short_pathname requires a null-terminated string */
10175
10176 /* Try it in situ */
10177 p = pbuf2;
10178 if (!get_short_pathname(&p, &pbuf3, &plen))
10179 {
10180 vim_free(pbuf2);
10181 return -1;
10182 }
10183 *s = ch; /* Preserve the string */
10184 } while (plen == 0);
10185
10186 if (plen > 0)
10187 {
10188 /* Remeber the length of the new string. */
10189 *fnamelen = len = plen + slen;
10190 vim_free(*bufp);
10191 if (len > len2)
10192 {
10193 /* If there's not enough space in the currently allocated string,
10194 * then copy it to a buffer big enough.
10195 */
10196 *fname= *bufp = vim_strnsave(p, len);
10197 if (*fname == NULL)
10198 return -1;
10199 }
10200 else
10201 {
10202 /* Transfer pbuf2 to being the main buffer (it's big enough) */
10203 *fname = *bufp = pbuf2;
10204 if (p != pbuf2)
10205 strncpy(*fname, p, plen);
10206 pbuf2 = NULL;
10207 }
10208 /* Concat the next bit */
10209 strncpy(*fname + plen, s, slen);
10210 (*fname)[len] = '\0';
10211 }
10212 vim_free(pbuf3);
10213 vim_free(pbuf2);
10214 return 0;
10215}
10216
10217/*
10218 * Get a pathname for a partial path.
10219 */
10220 static int
10221shortpath_for_partial(fnamep, bufp, fnamelen)
10222 char_u **fnamep;
10223 char_u **bufp;
10224 int *fnamelen;
10225{
10226 int sepcount, len, tflen;
10227 char_u *p;
10228 char_u *pbuf, *tfname;
10229 int hasTilde;
10230
10231 /* Count up the path seperators from the RHS.. so we know which part
10232 * of the path to return.
10233 */
10234 sepcount = 0;
10235 for (p = *fnamep + *fnamelen - 1; p >= *fnamep; --p)
10236 if (vim_ispathsep(*p))
10237 ++sepcount;
10238
10239 /* Need full path first (use expand_env() to remove a "~/") */
10240 hasTilde = (**fnamep == '~');
10241 if (hasTilde)
10242 pbuf = tfname = expand_env_save(*fnamep);
10243 else
10244 pbuf = tfname = FullName_save(*fnamep, FALSE);
10245
10246 len = tflen = STRLEN(tfname);
10247
10248 if (!get_short_pathname(&tfname, &pbuf, &len))
10249 return -1;
10250
10251 if (len == 0)
10252 {
10253 /* Don't have a valid filename, so shorten the rest of the
10254 * path if we can. This CAN give us invalid 8.3 filenames, but
10255 * there's not a lot of point in guessing what it might be.
10256 */
10257 len = tflen;
10258 if (shortpath_for_invalid_fname(&tfname, &pbuf, &len) == -1)
10259 return -1;
10260 }
10261
10262 /* Count the paths backward to find the beginning of the desired string. */
10263 for (p = tfname + len - 1; p >= tfname; --p)
10264 if (vim_ispathsep(*p))
10265 {
10266 if (sepcount == 0 || (hasTilde && sepcount == 1))
10267 break;
10268 else
10269 sepcount --;
10270 }
10271 if (hasTilde)
10272 {
10273 --p;
10274 if (p >= tfname)
10275 *p = '~';
10276 else
10277 return -1;
10278 }
10279 else
10280 ++p;
10281
10282 /* Copy in the string - p indexes into tfname - allocated at pbuf */
10283 vim_free(*bufp);
10284 *fnamelen = (int)STRLEN(p);
10285 *bufp = pbuf;
10286 *fnamep = p;
10287
10288 return 0;
10289}
10290#endif /* WIN3264 */
10291
10292/*
10293 * Adjust a filename, according to a string of modifiers.
10294 * *fnamep must be NUL terminated when called. When returning, the length is
10295 * determined by *fnamelen.
10296 * Returns valid flags.
10297 * When there is an error, *fnamep is set to NULL.
10298 */
10299 int
10300modify_fname(src, usedlen, fnamep, bufp, fnamelen)
10301 char_u *src; /* string with modifiers */
10302 int *usedlen; /* characters after src that are used */
10303 char_u **fnamep; /* file name so far */
10304 char_u **bufp; /* buffer for allocated file name or NULL */
10305 int *fnamelen; /* length of fnamep */
10306{
10307 int valid = 0;
10308 char_u *tail;
10309 char_u *s, *p, *pbuf;
10310 char_u dirname[MAXPATHL];
10311 int c;
10312 int has_fullname = 0;
10313#ifdef WIN3264
10314 int has_shortname = 0;
10315#endif
10316
10317repeat:
10318 /* ":p" - full path/file_name */
10319 if (src[*usedlen] == ':' && src[*usedlen + 1] == 'p')
10320 {
10321 has_fullname = 1;
10322
10323 valid |= VALID_PATH;
10324 *usedlen += 2;
10325
10326 /* Expand "~/path" for all systems and "~user/path" for Unix and VMS */
10327 if ((*fnamep)[0] == '~'
10328#if !defined(UNIX) && !(defined(VMS) && defined(USER_HOME))
10329 && ((*fnamep)[1] == '/'
10330# ifdef BACKSLASH_IN_FILENAME
10331 || (*fnamep)[1] == '\\'
10332# endif
10333 || (*fnamep)[1] == NUL)
10334
10335#endif
10336 )
10337 {
10338 *fnamep = expand_env_save(*fnamep);
10339 vim_free(*bufp); /* free any allocated file name */
10340 *bufp = *fnamep;
10341 if (*fnamep == NULL)
10342 return -1;
10343 }
10344
10345 /* When "/." or "/.." is used: force expansion to get rid of it. */
10346 for (p = *fnamep; *p != NUL; ++p)
10347 {
10348 if (vim_ispathsep(*p)
10349 && p[1] == '.'
10350 && (p[2] == NUL
10351 || vim_ispathsep(p[2])
10352 || (p[2] == '.'
10353 && (p[3] == NUL || vim_ispathsep(p[3])))))
10354 break;
10355 }
10356
10357 /* FullName_save() is slow, don't use it when not needed. */
10358 if (*p != NUL || !vim_isAbsName(*fnamep))
10359 {
10360 *fnamep = FullName_save(*fnamep, *p != NUL);
10361 vim_free(*bufp); /* free any allocated file name */
10362 *bufp = *fnamep;
10363 if (*fnamep == NULL)
10364 return -1;
10365 }
10366
10367 /* Append a path separator to a directory. */
10368 if (mch_isdir(*fnamep))
10369 {
10370 /* Make room for one or two extra characters. */
10371 *fnamep = vim_strnsave(*fnamep, (int)STRLEN(*fnamep) + 2);
10372 vim_free(*bufp); /* free any allocated file name */
10373 *bufp = *fnamep;
10374 if (*fnamep == NULL)
10375 return -1;
10376 add_pathsep(*fnamep);
10377 }
10378 }
10379
10380 /* ":." - path relative to the current directory */
10381 /* ":~" - path relative to the home directory */
10382 /* ":8" - shortname path - postponed till after */
10383 while (src[*usedlen] == ':'
10384 && ((c = src[*usedlen + 1]) == '.' || c == '~' || c == '8'))
10385 {
10386 *usedlen += 2;
10387 if (c == '8')
10388 {
10389#ifdef WIN3264
10390 has_shortname = 1; /* Postpone this. */
10391#endif
10392 continue;
10393 }
10394 pbuf = NULL;
10395 /* Need full path first (use expand_env() to remove a "~/") */
10396 if (!has_fullname)
10397 {
10398 if (c == '.' && **fnamep == '~')
10399 p = pbuf = expand_env_save(*fnamep);
10400 else
10401 p = pbuf = FullName_save(*fnamep, FALSE);
10402 }
10403 else
10404 p = *fnamep;
10405
10406 has_fullname = 0;
10407
10408 if (p != NULL)
10409 {
10410 if (c == '.')
10411 {
10412 mch_dirname(dirname, MAXPATHL);
10413 s = shorten_fname(p, dirname);
10414 if (s != NULL)
10415 {
10416 *fnamep = s;
10417 if (pbuf != NULL)
10418 {
10419 vim_free(*bufp); /* free any allocated file name */
10420 *bufp = pbuf;
10421 pbuf = NULL;
10422 }
10423 }
10424 }
10425 else
10426 {
10427 home_replace(NULL, p, dirname, MAXPATHL, TRUE);
10428 /* Only replace it when it starts with '~' */
10429 if (*dirname == '~')
10430 {
10431 s = vim_strsave(dirname);
10432 if (s != NULL)
10433 {
10434 *fnamep = s;
10435 vim_free(*bufp);
10436 *bufp = s;
10437 }
10438 }
10439 }
10440 vim_free(pbuf);
10441 }
10442 }
10443
10444 tail = gettail(*fnamep);
10445 *fnamelen = (int)STRLEN(*fnamep);
10446
10447 /* ":h" - head, remove "/file_name", can be repeated */
10448 /* Don't remove the first "/" or "c:\" */
10449 while (src[*usedlen] == ':' && src[*usedlen + 1] == 'h')
10450 {
10451 valid |= VALID_HEAD;
10452 *usedlen += 2;
10453 s = get_past_head(*fnamep);
10454 while (tail > s && vim_ispathsep(tail[-1]))
10455 --tail;
10456 *fnamelen = (int)(tail - *fnamep);
10457#ifdef VMS
10458 if (*fnamelen > 0)
10459 *fnamelen += 1; /* the path separator is part of the path */
10460#endif
10461 while (tail > s && !vim_ispathsep(tail[-1]))
10462 --tail;
10463 }
10464
10465 /* ":8" - shortname */
10466 if (src[*usedlen] == ':' && src[*usedlen + 1] == '8')
10467 {
10468 *usedlen += 2;
10469#ifdef WIN3264
10470 has_shortname = 1;
10471#endif
10472 }
10473
10474#ifdef WIN3264
10475 /* Check shortname after we have done 'heads' and before we do 'tails'
10476 */
10477 if (has_shortname)
10478 {
10479 pbuf = NULL;
10480 /* Copy the string if it is shortened by :h */
10481 if (*fnamelen < (int)STRLEN(*fnamep))
10482 {
10483 p = vim_strnsave(*fnamep, *fnamelen);
10484 if (p == 0)
10485 return -1;
10486 vim_free(*bufp);
10487 *bufp = *fnamep = p;
10488 }
10489
10490 /* Split into two implementations - makes it easier. First is where
10491 * there isn't a full name already, second is where there is.
10492 */
10493 if (!has_fullname && !vim_isAbsName(*fnamep))
10494 {
10495 if (shortpath_for_partial(fnamep, bufp, fnamelen) == -1)
10496 return -1;
10497 }
10498 else
10499 {
10500 int l;
10501
10502 /* Simple case, already have the full-name
10503 * Nearly always shorter, so try first time. */
10504 l = *fnamelen;
10505 if (!get_short_pathname(fnamep, bufp, &l))
10506 return -1;
10507
10508 if (l == 0)
10509 {
10510 /* Couldn't find the filename.. search the paths.
10511 */
10512 l = *fnamelen;
10513 if (shortpath_for_invalid_fname(fnamep, bufp, &l ) == -1)
10514 return -1;
10515 }
10516 *fnamelen = l;
10517 }
10518 }
10519#endif /* WIN3264 */
10520
10521 /* ":t" - tail, just the basename */
10522 if (src[*usedlen] == ':' && src[*usedlen + 1] == 't')
10523 {
10524 *usedlen += 2;
10525 *fnamelen -= (int)(tail - *fnamep);
10526 *fnamep = tail;
10527 }
10528
10529 /* ":e" - extension, can be repeated */
10530 /* ":r" - root, without extension, can be repeated */
10531 while (src[*usedlen] == ':'
10532 && (src[*usedlen + 1] == 'e' || src[*usedlen + 1] == 'r'))
10533 {
10534 /* find a '.' in the tail:
10535 * - for second :e: before the current fname
10536 * - otherwise: The last '.'
10537 */
10538 if (src[*usedlen + 1] == 'e' && *fnamep > tail)
10539 s = *fnamep - 2;
10540 else
10541 s = *fnamep + *fnamelen - 1;
10542 for ( ; s > tail; --s)
10543 if (s[0] == '.')
10544 break;
10545 if (src[*usedlen + 1] == 'e') /* :e */
10546 {
10547 if (s > tail)
10548 {
10549 *fnamelen += (int)(*fnamep - (s + 1));
10550 *fnamep = s + 1;
10551#ifdef VMS
10552 /* cut version from the extension */
10553 s = *fnamep + *fnamelen - 1;
10554 for ( ; s > *fnamep; --s)
10555 if (s[0] == ';')
10556 break;
10557 if (s > *fnamep)
10558 *fnamelen = s - *fnamep;
10559#endif
10560 }
10561 else if (*fnamep <= tail)
10562 *fnamelen = 0;
10563 }
10564 else /* :r */
10565 {
10566 if (s > tail) /* remove one extension */
10567 *fnamelen = (int)(s - *fnamep);
10568 }
10569 *usedlen += 2;
10570 }
10571
10572 /* ":s?pat?foo?" - substitute */
10573 /* ":gs?pat?foo?" - global substitute */
10574 if (src[*usedlen] == ':'
10575 && (src[*usedlen + 1] == 's'
10576 || (src[*usedlen + 1] == 'g' && src[*usedlen + 2] == 's')))
10577 {
10578 char_u *str;
10579 char_u *pat;
10580 char_u *sub;
10581 int sep;
10582 char_u *flags;
10583 int didit = FALSE;
10584
10585 flags = (char_u *)"";
10586 s = src + *usedlen + 2;
10587 if (src[*usedlen + 1] == 'g')
10588 {
10589 flags = (char_u *)"g";
10590 ++s;
10591 }
10592
10593 sep = *s++;
10594 if (sep)
10595 {
10596 /* find end of pattern */
10597 p = vim_strchr(s, sep);
10598 if (p != NULL)
10599 {
10600 pat = vim_strnsave(s, (int)(p - s));
10601 if (pat != NULL)
10602 {
10603 s = p + 1;
10604 /* find end of substitution */
10605 p = vim_strchr(s, sep);
10606 if (p != NULL)
10607 {
10608 sub = vim_strnsave(s, (int)(p - s));
10609 str = vim_strnsave(*fnamep, *fnamelen);
10610 if (sub != NULL && str != NULL)
10611 {
10612 *usedlen = (int)(p + 1 - src);
10613 s = do_string_sub(str, pat, sub, flags);
10614 if (s != NULL)
10615 {
10616 *fnamep = s;
10617 *fnamelen = (int)STRLEN(s);
10618 vim_free(*bufp);
10619 *bufp = s;
10620 didit = TRUE;
10621 }
10622 }
10623 vim_free(sub);
10624 vim_free(str);
10625 }
10626 vim_free(pat);
10627 }
10628 }
10629 /* after using ":s", repeat all the modifiers */
10630 if (didit)
10631 goto repeat;
10632 }
10633 }
10634
10635 return valid;
10636}
10637
10638/*
10639 * Perform a substitution on "str" with pattern "pat" and substitute "sub".
10640 * "flags" can be "g" to do a global substitute.
10641 * Returns an allocated string, NULL for error.
10642 */
10643 char_u *
10644do_string_sub(str, pat, sub, flags)
10645 char_u *str;
10646 char_u *pat;
10647 char_u *sub;
10648 char_u *flags;
10649{
10650 int sublen;
10651 regmatch_T regmatch;
10652 int i;
10653 int do_all;
10654 char_u *tail;
10655 garray_T ga;
10656 char_u *ret;
10657 char_u *save_cpo;
10658
10659 /* Make 'cpoptions' empty, so that the 'l' flag doesn't work here */
10660 save_cpo = p_cpo;
10661 p_cpo = (char_u *)"";
10662
10663 ga_init2(&ga, 1, 200);
10664
10665 do_all = (flags[0] == 'g');
10666
10667 regmatch.rm_ic = p_ic;
10668 regmatch.regprog = vim_regcomp(pat, RE_MAGIC + RE_STRING);
10669 if (regmatch.regprog != NULL)
10670 {
10671 tail = str;
10672 while (vim_regexec_nl(&regmatch, str, (colnr_T)(tail - str)))
10673 {
10674 /*
10675 * Get some space for a temporary buffer to do the substitution
10676 * into. It will contain:
10677 * - The text up to where the match is.
10678 * - The substituted text.
10679 * - The text after the match.
10680 */
10681 sublen = vim_regsub(&regmatch, sub, tail, FALSE, TRUE, FALSE);
10682 if (ga_grow(&ga, (int)(STRLEN(tail) + sublen -
10683 (regmatch.endp[0] - regmatch.startp[0]))) == FAIL)
10684 {
10685 ga_clear(&ga);
10686 break;
10687 }
10688
10689 /* copy the text up to where the match is */
10690 i = (int)(regmatch.startp[0] - tail);
10691 mch_memmove((char_u *)ga.ga_data + ga.ga_len, tail, (size_t)i);
10692 /* add the substituted text */
10693 (void)vim_regsub(&regmatch, sub, (char_u *)ga.ga_data
10694 + ga.ga_len + i, TRUE, TRUE, FALSE);
10695 ga.ga_len += i + sublen - 1;
10696 ga.ga_room -= i + sublen - 1;
10697 /* avoid getting stuck on a match with an empty string */
10698 if (tail == regmatch.endp[0])
10699 {
10700 if (*tail == NUL)
10701 break;
10702 *((char_u *)ga.ga_data + ga.ga_len) = *tail++;
10703 ++ga.ga_len;
10704 --ga.ga_room;
10705 }
10706 else
10707 {
10708 tail = regmatch.endp[0];
10709 if (*tail == NUL)
10710 break;
10711 }
10712 if (!do_all)
10713 break;
10714 }
10715
10716 if (ga.ga_data != NULL)
10717 STRCPY((char *)ga.ga_data + ga.ga_len, tail);
10718
10719 vim_free(regmatch.regprog);
10720 }
10721
10722 ret = vim_strsave(ga.ga_data == NULL ? str : (char_u *)ga.ga_data);
10723 ga_clear(&ga);
10724 p_cpo = save_cpo;
10725
10726 return ret;
10727}
10728
10729#endif /* defined(FEAT_MODIFY_FNAME) || defined(FEAT_EVAL) */