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