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