blob: 6ed5c9fab36082d2bcd73fc682f11db6b061e7c2 [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/*
Bram Moolenaar49cd9572005-01-03 21:06:01 +000040 * Structure to hold an internal variable without a name.
Bram Moolenaar071d4272004-06-13 20:20:40 +000041 */
42typedef struct
43{
Bram Moolenaar49cd9572005-01-03 21:06:01 +000044 char v_type; /* see below: VAR_NUMBER, VAR_STRING, etc. */
Bram Moolenaar071d4272004-06-13 20:20:40 +000045 union
46 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +000047 varnumber_T v_number; /* number value */
48 char_u *v_string; /* string value (can be NULL!) */
49 struct listvar_S *v_list; /* list value (can be NULL!) */
50 } vval;
51} typeval;
52
53/* Values for "v_type". */
54#define VAR_UNKNOWN 0
55#define VAR_NUMBER 1 /* "v_number" is used */
56#define VAR_STRING 2 /* "v_string" is used */
57#define VAR_FUNC 3 /* "v_string" is function name */
58#define VAR_LIST 4 /* "v_list" is used */
59
60/*
61 * Structure to hold an internal variable with a name.
62 * The "tv" must come first, so that this can be used as a "typeval" as well.
63 */
64typedef struct
65{
66 typeval tv; /* type and value of the variable */
67 char_u *v_name; /* name of variable */
Bram Moolenaar071d4272004-06-13 20:20:40 +000068} var;
69
Bram Moolenaar071d4272004-06-13 20:20:40 +000070typedef var * VAR;
71
72/*
Bram Moolenaar49cd9572005-01-03 21:06:01 +000073 * Structure to hold an item of a list: an internal variable without a name.
74 */
75struct listitem_S
76{
77 struct listitem_S *li_next; /* next item in list */
78 struct listitem_S *li_prev; /* previous item in list */
79 typeval li_tv; /* type and value of the variable */
80};
81
82typedef struct listitem_S listitem;
83
84/*
Bram Moolenaar3d60ec22005-01-05 22:19:46 +000085 * Struct used by those that are using an item in a list.
86 */
87typedef struct listwatch_S
88{
89 listitem *lw_item; /* item being watched */
90 struct listwatch_S *lw_next; /* next watcher */
91} listwatch;
92
93/*
94 * Structure to hold info about a list.
Bram Moolenaar49cd9572005-01-03 21:06:01 +000095 */
96struct listvar_S
97{
98 int lv_refcount; /* reference count */
99 listitem *lv_first; /* first item, NULL if none */
100 listitem *lv_last; /* last item, NULL if none */
Bram Moolenaar3d60ec22005-01-05 22:19:46 +0000101 listwatch *lv_watch; /* first watcher, NULL if none */
Bram Moolenaar49cd9572005-01-03 21:06:01 +0000102};
103
104typedef struct listvar_S listvar;
105
106#define VAR_LIST_MAXNEST 100 /* maximum nesting of lists */
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000107static char *e_letunexp = N_("E18: Unexpected characters in :let");
108static char *e_listidx = N_("E999: list index out of range: %ld");
109static char *e_undefvar = N_("E121: Undefined variable: %s");
110static char *e_missbrac = N_("E111: Missing ']'");
111static char *e_intern2 = N_("E999: Internal error: %s");
Bram Moolenaar49cd9572005-01-03 21:06:01 +0000112
113/*
Bram Moolenaar071d4272004-06-13 20:20:40 +0000114 * All user-defined global variables are stored in "variables".
115 */
116garray_T variables = {0, 0, sizeof(var), 4, NULL};
117
118/*
119 * Array to hold an array with variables local to each sourced script.
120 */
121static garray_T ga_scripts = {0, 0, sizeof(garray_T), 4, NULL};
122#define SCRIPT_VARS(id) (((garray_T *)ga_scripts.ga_data)[(id) - 1])
123
124
125#define VAR_ENTRY(idx) (((VAR)(variables.ga_data))[idx])
126#define VAR_GAP_ENTRY(idx, gap) (((VAR)(gap->ga_data))[idx])
127#define BVAR_ENTRY(idx) (((VAR)(curbuf->b_vars.ga_data))[idx])
128#define WVAR_ENTRY(idx) (((VAR)(curwin->w_vars.ga_data))[idx])
129
130static int echo_attr = 0; /* attributes used for ":echo" */
131
132/*
133 * Structure to hold info for a user function.
134 */
135typedef struct ufunc ufunc_T;
136
137struct ufunc
138{
139 ufunc_T *next; /* next function in list */
140 char_u *name; /* name of function; can start with <SNR>123_
141 (<SNR> is K_SPECIAL KS_EXTRA KE_SNR) */
142 int varargs; /* variable nr of arguments */
143 int flags;
144 int calls; /* nr of active calls */
145 garray_T args; /* arguments */
146 garray_T lines; /* function lines */
147 scid_T script_ID; /* ID of script where function was defined,
148 used for s: variables */
149};
150
151/* function flags */
152#define FC_ABORT 1 /* abort function on error */
153#define FC_RANGE 2 /* function accepts range */
154
155/*
156 * All user-defined functions are found in the forward-linked function list.
157 * The first function is pointed at by firstfunc.
158 */
159ufunc_T *firstfunc = NULL;
160
161#define FUNCARG(fp, j) ((char_u **)(fp->args.ga_data))[j]
162#define FUNCLINE(fp, j) ((char_u **)(fp->lines.ga_data))[j]
163
164/* structure to hold info for a function that is currently being executed. */
165struct funccall
166{
167 ufunc_T *func; /* function being called */
168 int linenr; /* next line to be executed */
169 int returned; /* ":return" used */
170 int argcount; /* nr of arguments */
Bram Moolenaar49cd9572005-01-03 21:06:01 +0000171 typeval *argvars; /* arguments */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000172 var a0_var; /* "a:0" variable */
173 var firstline; /* "a:firstline" variable */
174 var lastline; /* "a:lastline" variable */
175 garray_T l_vars; /* local function variables */
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000176 typeval *rettv; /* return value */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000177 linenr_T breakpoint; /* next line with breakpoint or zero */
178 int dbg_tick; /* debug_tick when breakpoint was set */
179 int level; /* top nesting level of executed function */
180};
181
182/*
Bram Moolenaar3d60ec22005-01-05 22:19:46 +0000183 * Info used by a ":for" loop.
184 */
185typedef struct forinfo_S
186{
187 int fi_semicolon; /* TRUE if ending in '; var]' */
188 int fi_varcount; /* nr of variables in the list */
189 listwatch fi_lw; /* keep an eye on the item used. */
190 listvar *fi_list; /* list being used */
191} forinfo;
192
193
194/*
Bram Moolenaar071d4272004-06-13 20:20:40 +0000195 * Return the name of the executed function.
196 */
197 char_u *
198func_name(cookie)
199 void *cookie;
200{
201 return ((struct funccall *)cookie)->func->name;
202}
203
204/*
205 * Return the address holding the next breakpoint line for a funccall cookie.
206 */
207 linenr_T *
208func_breakpoint(cookie)
209 void *cookie;
210{
211 return &((struct funccall *)cookie)->breakpoint;
212}
213
214/*
215 * Return the address holding the debug tick for a funccall cookie.
216 */
217 int *
218func_dbg_tick(cookie)
219 void *cookie;
220{
221 return &((struct funccall *)cookie)->dbg_tick;
222}
223
224/*
225 * Return the nesting level for a funccall cookie.
226 */
227 int
228func_level(cookie)
229 void *cookie;
230{
231 return ((struct funccall *)cookie)->level;
232}
233
234/* pointer to funccal for currently active function */
235struct funccall *current_funccal = NULL;
236
237/*
238 * Return TRUE when a function was ended by a ":return" command.
239 */
240 int
241current_func_returned()
242{
243 return current_funccal->returned;
244}
245
246
247/*
248 * Array to hold the value of v: variables.
249 */
250#include "version.h"
251
252/* values for flags: */
Bram Moolenaar7b0294c2004-10-11 10:16:09 +0000253#define VV_COMPAT 1 /* compatible, also used without "v:" */
254#define VV_RO 2 /* read-only */
255#define VV_RO_SBX 4 /* read-only in the sandbox*/
Bram Moolenaar071d4272004-06-13 20:20:40 +0000256
257struct vimvar
258{
259 char *name; /* name of variable, without v: */
260 int len; /* length of name */
261 char_u *val; /* current value (can also be a number!) */
262 char type; /* VAR_NUMBER or VAR_STRING */
Bram Moolenaar7b0294c2004-10-11 10:16:09 +0000263 char flags; /* VV_COMPAT, VV_RO, VV_RO_SBX */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000264} vimvars[VV_LEN] =
265{ /* The order here must match the VV_ defines in vim.h! */
266 {"count", sizeof("count") - 1, NULL, VAR_NUMBER, VV_COMPAT+VV_RO},
267 {"count1", sizeof("count1") - 1, NULL, VAR_NUMBER, VV_RO},
268 {"prevcount", sizeof("prevcount") - 1, NULL, VAR_NUMBER, VV_RO},
269 {"errmsg", sizeof("errmsg") - 1, NULL, VAR_STRING, VV_COMPAT},
270 {"warningmsg", sizeof("warningmsg") - 1, NULL, VAR_STRING, 0},
271 {"statusmsg", sizeof("statusmsg") - 1, NULL, VAR_STRING, 0},
272 {"shell_error", sizeof("shell_error") - 1, NULL, VAR_NUMBER,
273 VV_COMPAT+VV_RO},
274 {"this_session", sizeof("this_session") - 1, NULL, VAR_STRING, VV_COMPAT},
275 {"version", sizeof("version") - 1, (char_u *)VIM_VERSION_100,
276 VAR_NUMBER, VV_COMPAT+VV_RO},
Bram Moolenaar7b0294c2004-10-11 10:16:09 +0000277 {"lnum", sizeof("lnum") - 1, NULL, VAR_NUMBER, VV_RO_SBX},
Bram Moolenaar071d4272004-06-13 20:20:40 +0000278 {"termresponse", sizeof("termresponse") - 1, NULL, VAR_STRING, VV_RO},
279 {"fname", sizeof("fname") - 1, NULL, VAR_STRING, VV_RO},
280 {"lang", sizeof("lang") - 1, NULL, VAR_STRING, VV_RO},
281 {"lc_time", sizeof("lc_time") - 1, NULL, VAR_STRING, VV_RO},
282 {"ctype", sizeof("ctype") - 1, NULL, VAR_STRING, VV_RO},
283 {"charconvert_from", sizeof("charconvert_from") - 1, NULL, VAR_STRING, VV_RO},
284 {"charconvert_to", sizeof("charconvert_to") - 1, NULL, VAR_STRING, VV_RO},
285 {"fname_in", sizeof("fname_in") - 1, NULL, VAR_STRING, VV_RO},
286 {"fname_out", sizeof("fname_out") - 1, NULL, VAR_STRING, VV_RO},
287 {"fname_new", sizeof("fname_new") - 1, NULL, VAR_STRING, VV_RO},
288 {"fname_diff", sizeof("fname_diff") - 1, NULL, VAR_STRING, VV_RO},
289 {"cmdarg", sizeof("cmdarg") - 1, NULL, VAR_STRING, VV_RO},
Bram Moolenaar7b0294c2004-10-11 10:16:09 +0000290 {"foldstart", sizeof("foldstart") - 1, NULL, VAR_NUMBER, VV_RO_SBX},
291 {"foldend", sizeof("foldend") - 1, NULL, VAR_NUMBER, VV_RO_SBX},
292 {"folddashes", sizeof("folddashes") - 1, NULL, VAR_STRING, VV_RO_SBX},
293 {"foldlevel", sizeof("foldlevel") - 1, NULL, VAR_NUMBER, VV_RO_SBX},
Bram Moolenaar071d4272004-06-13 20:20:40 +0000294 {"progname", sizeof("progname") - 1, NULL, VAR_STRING, VV_RO},
295 {"servername", sizeof("servername") - 1, NULL, VAR_STRING, VV_RO},
296 {"dying", sizeof("dying") - 1, NULL, VAR_NUMBER, VV_RO},
297 {"exception", sizeof("exception") - 1, NULL, VAR_STRING, VV_RO},
298 {"throwpoint", sizeof("throwpoint") - 1, NULL, VAR_STRING, VV_RO},
299 {"register", sizeof("register") - 1, NULL, VAR_STRING, VV_RO},
300 {"cmdbang", sizeof("cmdbang") - 1, NULL, VAR_NUMBER, VV_RO},
Bram Moolenaar843ee412004-06-30 16:16:41 +0000301 {"insertmode", sizeof("insertmode") - 1, NULL, VAR_STRING, VV_RO},
Bram Moolenaar071d4272004-06-13 20:20:40 +0000302};
303
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000304static int eval0 __ARGS((char_u *arg, typeval *rettv, char_u **nextcmd, int evaluate));
305static int eval1 __ARGS((char_u **arg, typeval *rettv, int evaluate));
306static int eval2 __ARGS((char_u **arg, typeval *rettv, int evaluate));
307static int eval3 __ARGS((char_u **arg, typeval *rettv, int evaluate));
308static int eval4 __ARGS((char_u **arg, typeval *rettv, int evaluate));
309static int eval5 __ARGS((char_u **arg, typeval *rettv, int evaluate));
310static int eval6 __ARGS((char_u **arg, typeval *rettv, int evaluate));
311static int eval7 __ARGS((char_u **arg, typeval *rettv, int evaluate));
312static int eval_index __ARGS((char_u **arg, typeval *rettv, int evaluate));
313static int get_option_tv __ARGS((char_u **arg, typeval *rettv, int evaluate));
314static int get_string_tv __ARGS((char_u **arg, typeval *rettv, int evaluate));
315static int get_lit_string_tv __ARGS((char_u **arg, typeval *rettv, int evaluate));
316static int get_list_tv __ARGS((char_u **arg, typeval *rettv, int evaluate));
Bram Moolenaar49cd9572005-01-03 21:06:01 +0000317static listvar *list_alloc __ARGS((void));
318static void list_unref __ARGS((listvar *l));
319static void list_free __ARGS((listvar *l));
320static listitem *listitem_alloc __ARGS((void));
321static void listitem_free __ARGS((listitem *item));
322static long list_len __ARGS((listvar *l));
323static listitem *list_find __ARGS((listvar *l, long n));
324static void list_append __ARGS((listvar *l, listitem *item));
325static int list_append_tv __ARGS((listvar *l, typeval *tv));
326static listvar *list_copy __ARGS((listvar *orig, int deep));
327static listitem *list_getrem __ARGS((listvar *l, long n));
328static char_u *list2string __ARGS((typeval *tv));
329static char_u *tv2string __ARGS((typeval *tv, char_u **tofree));
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000330static int get_env_tv __ARGS((char_u **arg, typeval *rettv, int evaluate));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000331static int find_internal_func __ARGS((char_u *name));
Bram Moolenaar49cd9572005-01-03 21:06:01 +0000332static char_u *deref_func_name __ARGS((char_u *name, int *lenp));
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000333static int get_func_tv __ARGS((char_u *name, int len, typeval *rettv, char_u **arg, linenr_T firstline, linenr_T lastline, int *doesrange, int evaluate));
334static int call_func __ARGS((char_u *name, int len, typeval *rettv, int argcount, typeval *argvars, linenr_T firstline, linenr_T lastline, int *doesrange, int evaluate));
335static void f_append __ARGS((typeval *argvars, typeval *rettv));
336static void f_argc __ARGS((typeval *argvars, typeval *rettv));
337static void f_argidx __ARGS((typeval *argvars, typeval *rettv));
338static void f_argv __ARGS((typeval *argvars, typeval *rettv));
339static void f_browse __ARGS((typeval *argvars, typeval *rettv));
340static void f_browsedir __ARGS((typeval *argvars, typeval *rettv));
Bram Moolenaar49cd9572005-01-03 21:06:01 +0000341static buf_T *find_buffer __ARGS((typeval *avar));
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000342static void f_bufexists __ARGS((typeval *argvars, typeval *rettv));
343static void f_buflisted __ARGS((typeval *argvars, typeval *rettv));
344static void f_bufloaded __ARGS((typeval *argvars, typeval *rettv));
345static buf_T *get_buf_tv __ARGS((typeval *tv));
346static void f_bufname __ARGS((typeval *argvars, typeval *rettv));
347static void f_bufnr __ARGS((typeval *argvars, typeval *rettv));
348static void f_bufwinnr __ARGS((typeval *argvars, typeval *rettv));
349static void f_byte2line __ARGS((typeval *argvars, typeval *rettv));
350static void f_byteidx __ARGS((typeval *argvars, typeval *rettv));
351static void f_char2nr __ARGS((typeval *argvars, typeval *rettv));
352static void f_cindent __ARGS((typeval *argvars, typeval *rettv));
353static void f_col __ARGS((typeval *argvars, typeval *rettv));
354static void f_confirm __ARGS((typeval *argvars, typeval *rettv));
355static void f_copy __ARGS((typeval *argvars, typeval *rettv));
356static void f_cscope_connection __ARGS((typeval *argvars, typeval *rettv));
357static void f_cursor __ARGS((typeval *argsvars, typeval *rettv));
358static void f_deepcopy __ARGS((typeval *argvars, typeval *rettv));
359static void f_delete __ARGS((typeval *argvars, typeval *rettv));
360static void f_did_filetype __ARGS((typeval *argvars, typeval *rettv));
361static void f_diff_filler __ARGS((typeval *argvars, typeval *rettv));
362static void f_diff_hlID __ARGS((typeval *argvars, typeval *rettv));
363static void f_escape __ARGS((typeval *argvars, typeval *rettv));
364static void f_eventhandler __ARGS((typeval *argvars, typeval *rettv));
365static void f_executable __ARGS((typeval *argvars, typeval *rettv));
366static void f_exists __ARGS((typeval *argvars, typeval *rettv));
367static void f_expand __ARGS((typeval *argvars, typeval *rettv));
368static void f_filereadable __ARGS((typeval *argvars, typeval *rettv));
369static void f_filewritable __ARGS((typeval *argvars, typeval *rettv));
370static void f_finddir __ARGS((typeval *argvars, typeval *rettv));
371static void f_findfile __ARGS((typeval *argvars, typeval *rettv));
372static void f_findfilendir __ARGS((typeval *argvars, typeval *rettv, int dir));
373static void f_fnamemodify __ARGS((typeval *argvars, typeval *rettv));
374static void f_foldclosed __ARGS((typeval *argvars, typeval *rettv));
375static void f_foldclosedend __ARGS((typeval *argvars, typeval *rettv));
376static void foldclosed_both __ARGS((typeval *argvars, typeval *rettv, int end));
377static void f_foldlevel __ARGS((typeval *argvars, typeval *rettv));
378static void f_foldtext __ARGS((typeval *argvars, typeval *rettv));
379static void f_foldtextresult __ARGS((typeval *argvars, typeval *rettv));
380static void f_foreground __ARGS((typeval *argvars, typeval *rettv));
381static void f_function __ARGS((typeval *argvars, typeval *rettv));
382static void f_getbufvar __ARGS((typeval *argvars, typeval *rettv));
383static void f_getchar __ARGS((typeval *argvars, typeval *rettv));
384static void f_getcharmod __ARGS((typeval *argvars, typeval *rettv));
385static void f_getcmdline __ARGS((typeval *argvars, typeval *rettv));
386static void f_getcmdpos __ARGS((typeval *argvars, typeval *rettv));
387static void f_getcwd __ARGS((typeval *argvars, typeval *rettv));
388static void f_getfontname __ARGS((typeval *argvars, typeval *rettv));
389static void f_getfperm __ARGS((typeval *argvars, typeval *rettv));
390static void f_getfsize __ARGS((typeval *argvars, typeval *rettv));
391static void f_getftime __ARGS((typeval *argvars, typeval *rettv));
392static void f_getftype __ARGS((typeval *argvars, typeval *rettv));
393static void f_getline __ARGS((typeval *argvars, typeval *rettv));
394static void f_getreg __ARGS((typeval *argvars, typeval *rettv));
395static void f_getregtype __ARGS((typeval *argvars, typeval *rettv));
396static void f_getwinposx __ARGS((typeval *argvars, typeval *rettv));
397static void f_getwinposy __ARGS((typeval *argvars, typeval *rettv));
398static void f_getwinvar __ARGS((typeval *argvars, typeval *rettv));
399static void f_glob __ARGS((typeval *argvars, typeval *rettv));
400static void f_globpath __ARGS((typeval *argvars, typeval *rettv));
401static void f_has __ARGS((typeval *argvars, typeval *rettv));
402static void f_hasmapto __ARGS((typeval *argvars, typeval *rettv));
403static void f_histadd __ARGS((typeval *argvars, typeval *rettv));
404static void f_histdel __ARGS((typeval *argvars, typeval *rettv));
405static void f_histget __ARGS((typeval *argvars, typeval *rettv));
406static void f_histnr __ARGS((typeval *argvars, typeval *rettv));
407static void f_hlexists __ARGS((typeval *argvars, typeval *rettv));
408static void f_hlID __ARGS((typeval *argvars, typeval *rettv));
409static void f_hostname __ARGS((typeval *argvars, typeval *rettv));
410static void f_iconv __ARGS((typeval *argvars, typeval *rettv));
411static void f_indent __ARGS((typeval *argvars, typeval *rettv));
412static void f_insert __ARGS((typeval *argvars, typeval *rettv));
413static void f_isdirectory __ARGS((typeval *argvars, typeval *rettv));
414static void f_input __ARGS((typeval *argvars, typeval *rettv));
415static void f_inputdialog __ARGS((typeval *argvars, typeval *rettv));
416static void f_inputrestore __ARGS((typeval *argvars, typeval *rettv));
417static void f_inputsave __ARGS((typeval *argvars, typeval *rettv));
418static void f_inputsecret __ARGS((typeval *argvars, typeval *rettv));
419static void f_last_buffer_nr __ARGS((typeval *argvars, typeval *rettv));
420static void f_len __ARGS((typeval *argvars, typeval *rettv));
421static void f_libcall __ARGS((typeval *argvars, typeval *rettv));
422static void f_libcallnr __ARGS((typeval *argvars, typeval *rettv));
423static void libcall_common __ARGS((typeval *argvars, typeval *rettv, int type));
424static void f_line __ARGS((typeval *argvars, typeval *rettv));
425static void f_line2byte __ARGS((typeval *argvars, typeval *rettv));
426static void f_lispindent __ARGS((typeval *argvars, typeval *rettv));
427static void f_localtime __ARGS((typeval *argvars, typeval *rettv));
428static void f_maparg __ARGS((typeval *argvars, typeval *rettv));
429static void f_mapcheck __ARGS((typeval *argvars, typeval *rettv));
430static void get_maparg __ARGS((typeval *argvars, typeval *rettv, int exact));
431static void f_match __ARGS((typeval *argvars, typeval *rettv));
432static void f_matchend __ARGS((typeval *argvars, typeval *rettv));
433static void f_matchstr __ARGS((typeval *argvars, typeval *rettv));
434static void f_mode __ARGS((typeval *argvars, typeval *rettv));
435static void f_nextnonblank __ARGS((typeval *argvars, typeval *rettv));
436static void f_nr2char __ARGS((typeval *argvars, typeval *rettv));
437static void f_prevnonblank __ARGS((typeval *argvars, typeval *rettv));
438static void f_setbufvar __ARGS((typeval *argvars, typeval *rettv));
439static void f_setcmdpos __ARGS((typeval *argvars, typeval *rettv));
440static void f_setwinvar __ARGS((typeval *argvars, typeval *rettv));
441static void f_remove __ARGS((typeval *argvars, typeval *rettv));
442static void f_rename __ARGS((typeval *argvars, typeval *rettv));
443static void f_resolve __ARGS((typeval *argvars, typeval *rettv));
444static void f_search __ARGS((typeval *argvars, typeval *rettv));
445static void f_searchpair __ARGS((typeval *argvars, typeval *rettv));
Bram Moolenaar49cd9572005-01-03 21:06:01 +0000446static int get_search_arg __ARGS((typeval *varp, int *flagsp));
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000447static void f_remote_expr __ARGS((typeval *argvars, typeval *rettv));
448static void f_remote_foreground __ARGS((typeval *argvars, typeval *rettv));
449static void f_remote_peek __ARGS((typeval *argvars, typeval *rettv));
450static void f_remote_read __ARGS((typeval *argvars, typeval *rettv));
451static void f_remote_send __ARGS((typeval *argvars, typeval *rettv));
452static void f_repeat __ARGS((typeval *argvars, typeval *rettv));
453static void f_server2client __ARGS((typeval *argvars, typeval *rettv));
454static void f_serverlist __ARGS((typeval *argvars, typeval *rettv));
455static void f_setline __ARGS((typeval *argvars, typeval *rettv));
456static void f_setreg __ARGS((typeval *argvars, typeval *rettv));
457static void f_simplify __ARGS((typeval *argvars, typeval *rettv));
458static void find_some_match __ARGS((typeval *argvars, typeval *rettv, int start));
459static void f_strftime __ARGS((typeval *argvars, typeval *rettv));
460static void f_stridx __ARGS((typeval *argvars, typeval *rettv));
461static void f_string __ARGS((typeval *argvars, typeval *rettv));
462static void f_strlen __ARGS((typeval *argvars, typeval *rettv));
463static void f_strpart __ARGS((typeval *argvars, typeval *rettv));
464static void f_strridx __ARGS((typeval *argvars, typeval *rettv));
465static void f_strtrans __ARGS((typeval *argvars, typeval *rettv));
466static void f_synID __ARGS((typeval *argvars, typeval *rettv));
467static void f_synIDattr __ARGS((typeval *argvars, typeval *rettv));
468static void f_synIDtrans __ARGS((typeval *argvars, typeval *rettv));
469static void f_system __ARGS((typeval *argvars, typeval *rettv));
470static void f_submatch __ARGS((typeval *argvars, typeval *rettv));
471static void f_substitute __ARGS((typeval *argvars, typeval *rettv));
472static void f_tempname __ARGS((typeval *argvars, typeval *rettv));
473static void f_tolower __ARGS((typeval *argvars, typeval *rettv));
474static void f_toupper __ARGS((typeval *argvars, typeval *rettv));
475static void f_tr __ARGS((typeval *argvars, typeval *rettv));
476static void f_type __ARGS((typeval *argvars, typeval *rettv));
477static void f_virtcol __ARGS((typeval *argvars, typeval *rettv));
478static void f_visualmode __ARGS((typeval *argvars, typeval *rettv));
479static void f_winbufnr __ARGS((typeval *argvars, typeval *rettv));
480static void f_wincol __ARGS((typeval *argvars, typeval *rettv));
481static void f_winheight __ARGS((typeval *argvars, typeval *rettv));
482static void f_winline __ARGS((typeval *argvars, typeval *rettv));
483static void f_winnr __ARGS((typeval *argvars, typeval *rettv));
484static void f_winrestcmd __ARGS((typeval *argvars, typeval *rettv));
485static void f_winwidth __ARGS((typeval *argvars, typeval *rettv));
Bram Moolenaar49cd9572005-01-03 21:06:01 +0000486static win_T *find_win_by_nr __ARGS((typeval *vp));
487static pos_T *var2fpos __ARGS((typeval *varp, int lnum));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000488static int get_env_len __ARGS((char_u **arg));
489static int get_id_len __ARGS((char_u **arg));
490static int get_func_len __ARGS((char_u **arg, char_u **alias, int evaluate));
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000491static char_u *find_name_end __ARGS((char_u *arg, char_u **expr_start, char_u **expr_end, int incl_br));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000492static int eval_isnamec __ARGS((int c));
493static int find_vim_var __ARGS((char_u *name, int len));
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000494static int get_var_tv __ARGS((char_u *name, int len, typeval *rettv));
495static typeval *alloc_tv __ARGS((void));
496static typeval *alloc_string_tv __ARGS((char_u *string));
497static void free_tv __ARGS((typeval *varp));
498static void clear_tv __ARGS((typeval *varp));
499static void init_tv __ARGS((typeval *varp));
500static long get_tv_number __ARGS((typeval *varp));
501static linenr_T get_tv_lnum __ARGS((typeval *argvars));
502static char_u *get_tv_string __ARGS((typeval *varp));
503static char_u *get_tv_string_buf __ARGS((typeval *varp, char_u *buf));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000504static VAR find_var __ARGS((char_u *name, int writing));
505static VAR find_var_in_ga __ARGS((garray_T *gap, char_u *varname));
506static garray_T *find_var_ga __ARGS((char_u *name, char_u **varname));
Bram Moolenaar49cd9572005-01-03 21:06:01 +0000507static void clear_var __ARGS((VAR v));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000508static void list_one_var __ARGS((VAR v, char_u *prefix));
509static void list_vim_var __ARGS((int i));
510static void list_one_var_a __ARGS((char_u *prefix, char_u *name, int type, char_u *string));
Bram Moolenaar49cd9572005-01-03 21:06:01 +0000511static void set_var __ARGS((char_u *name, typeval *varp, int copy));
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000512static void copy_tv __ARGS((typeval *from, typeval *to));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000513static char_u *find_option_end __ARGS((char_u **arg, int *opt_flags));
514static char_u *trans_function_name __ARGS((char_u **pp, int skip, int internal));
515static int eval_fname_script __ARGS((char_u *p));
516static int eval_fname_sid __ARGS((char_u *p));
517static void list_func_head __ARGS((ufunc_T *fp, int indent));
518static void cat_func_name __ARGS((char_u *buf, ufunc_T *fp));
519static ufunc_T *find_func __ARGS((char_u *name));
Bram Moolenaar49cd9572005-01-03 21:06:01 +0000520static int function_exists __ARGS((char_u *name));
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000521static void call_user_func __ARGS((ufunc_T *fp, int argcount, typeval *argvars, typeval *rettv, linenr_T firstline, linenr_T lastline));
Bram Moolenaar49cd9572005-01-03 21:06:01 +0000522
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000523#define get_var_string(p) get_tv_string(&(p)->tv)
524#define get_var_string_buf(p, b) get_tv_string_buf(&(p)->tv, (b))
525#define get_var_number(p) get_tv_number(&((p)->tv))
Bram Moolenaar071d4272004-06-13 20:20:40 +0000526
Bram Moolenaar071d4272004-06-13 20:20:40 +0000527static char_u * make_expanded_name __ARGS((char_u *in_start, char_u *expr_start, char_u *expr_end, char_u *in_end));
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000528
Bram Moolenaar3d60ec22005-01-05 22:19:46 +0000529static int ex_let_vars __ARGS((char_u *arg, typeval *tv, int copy, int semicolon, int var_count, char_u *nextchars));
530static char_u *skip_var_list __ARGS((char_u *arg, int *var_count, int *semicolon));
531static char_u *skip_var_one __ARGS((char_u *arg));
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000532static void list_all_vars __ARGS((void));
533static char_u *list_arg_vars __ARGS((exarg_T *eap, char_u *arg));
534static char_u *ex_let_one __ARGS((char_u *arg, typeval *tv, int copy, char_u *endchars));
535static char_u *set_var_idx __ARGS((char_u *name, char_u *ip, typeval *rettv, int copy, char_u *endchars));
Bram Moolenaar3d60ec22005-01-05 22:19:46 +0000536static void list_add_watch __ARGS((listvar *l, listwatch *lw));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000537
538/*
539 * Set an internal variable to a string value. Creates the variable if it does
540 * not already exist.
541 */
542 void
543set_internal_string_var(name, value)
544 char_u *name;
545 char_u *value;
546{
Bram Moolenaar49cd9572005-01-03 21:06:01 +0000547 char_u *val;
548 typeval *tvp;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000549
550 val = vim_strsave(value);
551 if (val != NULL)
552 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000553 tvp = alloc_string_tv(val);
Bram Moolenaar49cd9572005-01-03 21:06:01 +0000554 if (tvp != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000555 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +0000556 set_var(name, tvp, FALSE);
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000557 free_tv(tvp);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000558 }
559 }
560}
561
562# if defined(FEAT_MBYTE) || defined(PROTO)
563 int
564eval_charconvert(enc_from, enc_to, fname_from, fname_to)
565 char_u *enc_from;
566 char_u *enc_to;
567 char_u *fname_from;
568 char_u *fname_to;
569{
570 int err = FALSE;
571
572 set_vim_var_string(VV_CC_FROM, enc_from, -1);
573 set_vim_var_string(VV_CC_TO, enc_to, -1);
574 set_vim_var_string(VV_FNAME_IN, fname_from, -1);
575 set_vim_var_string(VV_FNAME_OUT, fname_to, -1);
576 if (eval_to_bool(p_ccv, &err, NULL, FALSE))
577 err = TRUE;
578 set_vim_var_string(VV_CC_FROM, NULL, -1);
579 set_vim_var_string(VV_CC_TO, NULL, -1);
580 set_vim_var_string(VV_FNAME_IN, NULL, -1);
581 set_vim_var_string(VV_FNAME_OUT, NULL, -1);
582
583 if (err)
584 return FAIL;
585 return OK;
586}
587# endif
588
589# if defined(FEAT_POSTSCRIPT) || defined(PROTO)
590 int
591eval_printexpr(fname, args)
592 char_u *fname;
593 char_u *args;
594{
595 int err = FALSE;
596
597 set_vim_var_string(VV_FNAME_IN, fname, -1);
598 set_vim_var_string(VV_CMDARG, args, -1);
599 if (eval_to_bool(p_pexpr, &err, NULL, FALSE))
600 err = TRUE;
601 set_vim_var_string(VV_FNAME_IN, NULL, -1);
602 set_vim_var_string(VV_CMDARG, NULL, -1);
603
604 if (err)
605 {
606 mch_remove(fname);
607 return FAIL;
608 }
609 return OK;
610}
611# endif
612
613# if defined(FEAT_DIFF) || defined(PROTO)
614 void
615eval_diff(origfile, newfile, outfile)
616 char_u *origfile;
617 char_u *newfile;
618 char_u *outfile;
619{
620 int err = FALSE;
621
622 set_vim_var_string(VV_FNAME_IN, origfile, -1);
623 set_vim_var_string(VV_FNAME_NEW, newfile, -1);
624 set_vim_var_string(VV_FNAME_OUT, outfile, -1);
625 (void)eval_to_bool(p_dex, &err, NULL, FALSE);
626 set_vim_var_string(VV_FNAME_IN, NULL, -1);
627 set_vim_var_string(VV_FNAME_NEW, NULL, -1);
628 set_vim_var_string(VV_FNAME_OUT, NULL, -1);
629}
630
631 void
632eval_patch(origfile, difffile, outfile)
633 char_u *origfile;
634 char_u *difffile;
635 char_u *outfile;
636{
637 int err;
638
639 set_vim_var_string(VV_FNAME_IN, origfile, -1);
640 set_vim_var_string(VV_FNAME_DIFF, difffile, -1);
641 set_vim_var_string(VV_FNAME_OUT, outfile, -1);
642 (void)eval_to_bool(p_pex, &err, NULL, FALSE);
643 set_vim_var_string(VV_FNAME_IN, NULL, -1);
644 set_vim_var_string(VV_FNAME_DIFF, NULL, -1);
645 set_vim_var_string(VV_FNAME_OUT, NULL, -1);
646}
647# endif
648
649/*
650 * Top level evaluation function, returning a boolean.
651 * Sets "error" to TRUE if there was an error.
652 * Return TRUE or FALSE.
653 */
654 int
655eval_to_bool(arg, error, nextcmd, skip)
656 char_u *arg;
657 int *error;
658 char_u **nextcmd;
659 int skip; /* only parse, don't execute */
660{
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000661 typeval tv;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000662 int retval = FALSE;
663
664 if (skip)
665 ++emsg_skip;
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000666 if (eval0(arg, &tv, nextcmd, !skip) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000667 *error = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000668 else
669 {
670 *error = FALSE;
671 if (!skip)
672 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000673 retval = (get_tv_number(&tv) != 0);
674 clear_tv(&tv);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000675 }
676 }
677 if (skip)
678 --emsg_skip;
679
680 return retval;
681}
682
683/*
684 * Top level evaluation function, returning a string. If "skip" is TRUE,
685 * only parsing to "nextcmd" is done, without reporting errors. Return
686 * pointer to allocated memory, or NULL for failure or when "skip" is TRUE.
687 */
688 char_u *
689eval_to_string_skip(arg, nextcmd, skip)
690 char_u *arg;
691 char_u **nextcmd;
692 int skip; /* only parse, don't execute */
693{
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000694 typeval tv;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000695 char_u *retval;
696
697 if (skip)
698 ++emsg_skip;
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000699 if (eval0(arg, &tv, nextcmd, !skip) == FAIL || skip)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000700 retval = NULL;
701 else
702 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000703 retval = vim_strsave(get_tv_string(&tv));
704 clear_tv(&tv);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000705 }
706 if (skip)
707 --emsg_skip;
708
709 return retval;
710}
711
712/*
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000713 * Skip over an expression at "*pp".
714 * Return FAIL for an error, OK otherwise.
715 */
716 int
717skip_expr(pp)
718 char_u **pp;
719{
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000720 typeval rettv;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000721
722 *pp = skipwhite(*pp);
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000723 return eval1(pp, &rettv, FALSE);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000724}
725
726/*
Bram Moolenaar071d4272004-06-13 20:20:40 +0000727 * Top level evaluation function, returning a string.
728 * Return pointer to allocated memory, or NULL for failure.
729 */
730 char_u *
731eval_to_string(arg, nextcmd)
732 char_u *arg;
733 char_u **nextcmd;
734{
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000735 typeval tv;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000736 char_u *retval;
737
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000738 if (eval0(arg, &tv, nextcmd, TRUE) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000739 retval = NULL;
740 else
741 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000742 retval = vim_strsave(get_tv_string(&tv));
743 clear_tv(&tv);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000744 }
745
746 return retval;
747}
748
749/*
750 * Call eval_to_string() with "sandbox" set and not using local variables.
751 */
752 char_u *
753eval_to_string_safe(arg, nextcmd)
754 char_u *arg;
755 char_u **nextcmd;
756{
757 char_u *retval;
758 void *save_funccalp;
759
760 save_funccalp = save_funccal();
761 ++sandbox;
762 retval = eval_to_string(arg, nextcmd);
763 --sandbox;
764 restore_funccal(save_funccalp);
765 return retval;
766}
767
768#if 0 /* not used */
769/*
770 * Top level evaluation function, returning a string.
771 * Advances "arg" to the first non-blank after the evaluated expression.
772 * Return pointer to allocated memory, or NULL for failure.
773 * Doesn't give error messages.
774 */
775 char_u *
776eval_arg_to_string(arg)
777 char_u **arg;
778{
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000779 typeval rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000780 char_u *retval;
781 int ret;
782
783 ++emsg_off;
784
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000785 ret = eval1(arg, &rettv, TRUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000786 if (ret == FAIL)
787 retval = NULL;
788 else
789 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000790 retval = vim_strsave(get_tv_string(&rettv));
791 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000792 }
793
794 --emsg_off;
795
796 return retval;
797}
798#endif
799
800/*
801 * Top level evaluation function, returning a number.
802 * Evaluates "expr" silently.
803 * Returns -1 for an error.
804 */
805 int
806eval_to_number(expr)
807 char_u *expr;
808{
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000809 typeval rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000810 int retval;
811 char_u *p = expr;
812
813 ++emsg_off;
814
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000815 if (eval1(&p, &rettv, TRUE) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000816 retval = -1;
817 else
818 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000819 retval = get_tv_number(&rettv);
820 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000821 }
822 --emsg_off;
823
824 return retval;
825}
826
827#if (defined(FEAT_USR_CMDS) && defined(FEAT_CMDL_COMPL)) || defined(PROTO)
828/*
829 * Call some vimL function and return the result as a string
830 * Uses argv[argc] for the function arguments.
831 */
832 char_u *
833call_vim_function(func, argc, argv, safe)
834 char_u *func;
835 int argc;
836 char_u **argv;
837 int safe; /* use the sandbox */
838{
839 char_u *retval = NULL;
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000840 typeval rettv;
Bram Moolenaar49cd9572005-01-03 21:06:01 +0000841 typeval *argvars;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000842 long n;
843 int len;
844 int i;
845 int doesrange;
846 void *save_funccalp = NULL;
847
Bram Moolenaar49cd9572005-01-03 21:06:01 +0000848 argvars = (typeval *)alloc((unsigned)(argc * sizeof(typeval)));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000849 if (argvars == NULL)
850 return NULL;
851
852 for (i = 0; i < argc; i++)
853 {
Bram Moolenaarcfbc5ee2004-07-02 15:38:35 +0000854 /* Pass a NULL or empty argument as an empty string */
855 if (argv[i] == NULL || *argv[i] == NUL)
856 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +0000857 argvars[i].v_type = VAR_STRING;
858 argvars[i].vval.v_string = (char_u *)"";
Bram Moolenaarcfbc5ee2004-07-02 15:38:35 +0000859 continue;
860 }
861
Bram Moolenaar071d4272004-06-13 20:20:40 +0000862 /* Recognize a number argument, the others must be strings. */
863 vim_str2nr(argv[i], NULL, &len, TRUE, TRUE, &n, NULL);
864 if (len != 0 && len == (int)STRLEN(argv[i]))
865 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +0000866 argvars[i].v_type = VAR_NUMBER;
867 argvars[i].vval.v_number = n;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000868 }
869 else
870 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +0000871 argvars[i].v_type = VAR_STRING;
872 argvars[i].vval.v_string = argv[i];
Bram Moolenaar071d4272004-06-13 20:20:40 +0000873 }
874 }
875
876 if (safe)
877 {
878 save_funccalp = save_funccal();
879 ++sandbox;
880 }
881
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000882 rettv.v_type = VAR_UNKNOWN; /* clear_tv() uses this */
883 if (call_func(func, (int)STRLEN(func), &rettv, argc, argvars,
Bram Moolenaar071d4272004-06-13 20:20:40 +0000884 curwin->w_cursor.lnum, curwin->w_cursor.lnum,
885 &doesrange, TRUE) == OK)
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000886 retval = vim_strsave(get_tv_string(&rettv));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000887
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000888 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000889 vim_free(argvars);
890
891 if (safe)
892 {
893 --sandbox;
894 restore_funccal(save_funccalp);
895 }
896 return retval;
897}
898#endif
899
900/*
901 * Save the current function call pointer, and set it to NULL.
902 * Used when executing autocommands and for ":source".
903 */
904 void *
905save_funccal()
906{
907 struct funccall *fc;
908
909 fc = current_funccal;
910 current_funccal = NULL;
911 return (void *)fc;
912}
913
914 void
915restore_funccal(fc)
916 void *fc;
917{
918 current_funccal = (struct funccall *)fc;
919}
920
921#ifdef FEAT_FOLDING
922/*
923 * Evaluate 'foldexpr'. Returns the foldlevel, and any character preceding
924 * it in "*cp". Doesn't give error messages.
925 */
926 int
927eval_foldexpr(arg, cp)
928 char_u *arg;
929 int *cp;
930{
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000931 typeval tv;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000932 int retval;
933 char_u *s;
934
935 ++emsg_off;
936 ++sandbox;
937 *cp = NUL;
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000938 if (eval0(arg, &tv, NULL, TRUE) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000939 retval = 0;
940 else
941 {
942 /* If the result is a number, just return the number. */
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000943 if (tv.v_type == VAR_NUMBER)
944 retval = tv.vval.v_number;
945 else if (tv.v_type == VAR_UNKNOWN
946 || tv.vval.v_string == NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000947 retval = 0;
948 else
949 {
950 /* If the result is a string, check if there is a non-digit before
951 * the number. */
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000952 s = tv.vval.v_string;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000953 if (!VIM_ISDIGIT(*s) && *s != '-')
954 *cp = *s++;
955 retval = atol((char *)s);
956 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000957 clear_tv(&tv);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000958 }
959 --emsg_off;
960 --sandbox;
961
962 return retval;
963}
964#endif
965
Bram Moolenaar071d4272004-06-13 20:20:40 +0000966/*
967 * Expands out the 'magic' {}'s in a variable/function name.
968 * Note that this can call itself recursively, to deal with
969 * constructs like foo{bar}{baz}{bam}
970 * The four pointer arguments point to "foo{expre}ss{ion}bar"
971 * "in_start" ^
972 * "expr_start" ^
973 * "expr_end" ^
974 * "in_end" ^
975 *
976 * Returns a new allocated string, which the caller must free.
977 * Returns NULL for failure.
978 */
979 static char_u *
980make_expanded_name(in_start, expr_start, expr_end, in_end)
981 char_u *in_start;
982 char_u *expr_start;
983 char_u *expr_end;
984 char_u *in_end;
985{
986 char_u c1;
987 char_u *retval = NULL;
988 char_u *temp_result;
989 char_u *nextcmd = NULL;
990
991 if (expr_end == NULL || in_end == NULL)
992 return NULL;
993 *expr_start = NUL;
994 *expr_end = NUL;
995 c1 = *in_end;
996 *in_end = NUL;
997
998 temp_result = eval_to_string(expr_start + 1, &nextcmd);
999 if (temp_result != NULL && nextcmd == NULL)
1000 {
1001 retval = alloc((unsigned)(STRLEN(temp_result) + (expr_start - in_start)
1002 + (in_end - expr_end) + 1));
1003
1004 if (retval != NULL)
1005 {
1006 STRCPY(retval, in_start);
1007 STRCAT(retval, temp_result);
1008 STRCAT(retval, expr_end + 1);
1009 }
1010 }
1011 vim_free(temp_result);
1012
1013 *in_end = c1; /* put char back for error messages */
1014 *expr_start = '{';
1015 *expr_end = '}';
1016
1017 if (retval != NULL)
1018 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001019 temp_result = find_name_end(retval, &expr_start, &expr_end, FALSE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001020 if (expr_start != NULL)
1021 {
1022 /* Further expansion! */
1023 temp_result = make_expanded_name(retval, expr_start,
1024 expr_end, temp_result);
1025 vim_free(retval);
1026 retval = temp_result;
1027 }
1028 }
1029
1030 return retval;
1031
1032}
Bram Moolenaar071d4272004-06-13 20:20:40 +00001033
1034/*
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001035 * ":let" list all variable values
1036 * ":let var1 var2" list variable values
1037 * ":let var = expr" assignment command.
1038 * ":let [var1, var2] = expr" unpack list.
Bram Moolenaar071d4272004-06-13 20:20:40 +00001039 */
1040 void
1041ex_let(eap)
1042 exarg_T *eap;
1043{
1044 char_u *arg = eap->arg;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001045 char_u *expr = NULL;
1046 typeval rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001047 int i;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001048 int var_count = 0;
1049 int semicolon = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001050
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001051 expr = skip_var_list(arg, &var_count, &semicolon);
1052 if (expr == NULL)
1053 return;
1054 expr = vim_strchr(expr, '=');
1055 if (expr == NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001056 {
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001057 if (*arg == '[')
1058 EMSG(_(e_invarg));
1059 else if (!ends_excmd(*arg))
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001060 /* ":let var1 var2" */
1061 arg = list_arg_vars(eap, arg);
1062 else if (!eap->skip)
1063 /* ":let" */
1064 list_all_vars();
Bram Moolenaar071d4272004-06-13 20:20:40 +00001065 eap->nextcmd = check_nextcmd(arg);
1066 }
1067 else
1068 {
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001069 expr = skipwhite(expr + 1);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001070
Bram Moolenaar071d4272004-06-13 20:20:40 +00001071 if (eap->skip)
1072 ++emsg_skip;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001073 i = eval0(expr, &rettv, &eap->nextcmd, !eap->skip);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001074 if (eap->skip)
1075 {
1076 if (i != FAIL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001077 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001078 --emsg_skip;
1079 }
1080 else if (i != FAIL)
1081 {
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001082 (void)ex_let_vars(eap->arg, &rettv, FALSE, semicolon, var_count,
1083 (char_u *)"=");
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001084 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001085 }
1086 }
1087}
1088
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001089/*
1090 * Assign the typevalue "tv" to the variable or variables at "arg_start".
1091 * Handles both "var" with any type and "[var, var; var]" with a list type.
1092 * Returns OK or FAIL;
1093 */
1094 static int
1095ex_let_vars(arg_start, tv, copy, semicolon, var_count, nextchars)
1096 char_u *arg_start;
1097 typeval *tv;
1098 int copy; /* copy values from "tv", don't move */
1099 int semicolon; /* from skip_var_list() */
1100 int var_count; /* from skip_var_list() */
1101 char_u *nextchars; /* characters that must follow or NULL */
1102{
1103 char_u *arg = arg_start;
1104 listvar *l;
1105 int i;
1106 listitem *item;
1107 typeval ltv;
1108
1109 if (*arg != '[')
1110 {
1111 /*
1112 * ":let var = expr" or ":for var in list"
1113 */
1114 if (ex_let_one(arg, tv, copy, nextchars) == NULL)
1115 return FAIL;
1116 return OK;
1117 }
1118
1119 /*
1120 * ":let [v1, v2] = list" or ":for [v1, v2] in listlist"
1121 */
1122 l = tv->vval.v_list;
1123 if (tv->v_type != VAR_LIST || l == NULL)
1124 {
1125 EMSG(_(e_listreq));
1126 return FAIL;
1127 }
1128
1129 i = list_len(l);
1130 if (semicolon == 0 && var_count < i)
1131 {
1132 EMSG(_("E999: Less targets than List items"));
1133 return FAIL;
1134 }
1135 if (var_count - semicolon > i)
1136 {
1137 EMSG(_("E999: More targets than List items"));
1138 return FAIL;
1139 }
1140
1141 item = l->lv_first;
1142 while (*arg != ']')
1143 {
1144 arg = skipwhite(arg + 1);
1145 arg = ex_let_one(arg, &item->li_tv, TRUE, (char_u *)",;]");
1146 item = item->li_next;
1147 if (arg == NULL)
1148 return FAIL;
1149
1150 arg = skipwhite(arg);
1151 if (*arg == ';')
1152 {
1153 /* Put the rest of the list (may be empty) in the var after ';'.
1154 * Create a new list for this. */
1155 l = list_alloc();
1156 if (l == NULL)
1157 return FAIL;
1158 while (item != NULL)
1159 {
1160 list_append_tv(l, &item->li_tv);
1161 item = item->li_next;
1162 }
1163
1164 ltv.v_type = VAR_LIST;
1165 ltv.vval.v_list = l;
1166 l->lv_refcount = 1;
1167
1168 arg = ex_let_one(skipwhite(arg + 1), &ltv, FALSE, (char_u *)"]");
1169 clear_tv(&ltv);
1170 if (arg == NULL)
1171 return FAIL;
1172 break;
1173 }
1174 else if (*arg != ',' && *arg != ']')
1175 {
1176 EMSG2(_(e_intern2), "ex_let_vars()");
1177 return FAIL;
1178 }
1179 }
1180
1181 return OK;
1182}
1183
1184/*
1185 * Skip over assignable variable "var" or list of variables "[var, var]".
1186 * Used for ":let varvar = expr" and ":for varvar in expr".
1187 * For "[var, var]" increment "*var_count" for each variable.
1188 * for "[var, var; var]" set "semicolon".
1189 * Return NULL for an error.
1190 */
1191 static char_u *
1192skip_var_list(arg, var_count, semicolon)
1193 char_u *arg;
1194 int *var_count;
1195 int *semicolon;
1196{
1197 char_u *p, *s;
1198
1199 if (*arg == '[')
1200 {
1201 /* "[var, var]": find the matching ']'. */
1202 p = arg;
1203 while (1)
1204 {
1205 p = skipwhite(p + 1); /* skip whites after '[', ';' or ',' */
1206 s = skip_var_one(p);
1207 if (s == p)
1208 {
1209 EMSG2(_(e_invarg2), p);
1210 return NULL;
1211 }
1212 ++*var_count;
1213
1214 p = skipwhite(s);
1215 if (*p == ']')
1216 break;
1217 else if (*p == ';')
1218 {
1219 if (*semicolon == 1)
1220 {
1221 EMSG(_("Double ; in list of variables"));
1222 return NULL;
1223 }
1224 *semicolon = 1;
1225 }
1226 else if (*p != ',')
1227 {
1228 EMSG2(_(e_invarg2), p);
1229 return NULL;
1230 }
1231 }
1232 return p + 1;
1233 }
1234 else
1235 return skip_var_one(arg);
1236}
1237
1238 static char_u *
1239skip_var_one(arg)
1240 char_u *arg;
1241{
1242 if (vim_strchr((char_u *)"$@&", *arg) != NULL)
1243 ++arg;
1244 return find_name_end(arg, NULL, NULL, TRUE);
1245}
1246
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001247 static void
1248list_all_vars()
1249{
1250 int i;
1251
1252 /*
1253 * List all variables.
1254 */
1255 for (i = 0; i < variables.ga_len && !got_int; ++i)
1256 if (VAR_ENTRY(i).v_name != NULL)
1257 list_one_var(&VAR_ENTRY(i), (char_u *)"");
1258 for (i = 0; i < curbuf->b_vars.ga_len && !got_int; ++i)
1259 if (BVAR_ENTRY(i).v_name != NULL)
1260 list_one_var(&BVAR_ENTRY(i), (char_u *)"b:");
1261 for (i = 0; i < curwin->w_vars.ga_len && !got_int; ++i)
1262 if (WVAR_ENTRY(i).v_name != NULL)
1263 list_one_var(&WVAR_ENTRY(i), (char_u *)"w:");
1264 for (i = 0; i < VV_LEN && !got_int; ++i)
1265 if (vimvars[i].type == VAR_NUMBER || vimvars[i].val != NULL)
1266 list_vim_var(i);
1267}
1268
1269/*
1270 * List variables in "arg".
1271 */
1272 static char_u *
1273list_arg_vars(eap, arg)
1274 exarg_T *eap;
1275 char_u *arg;
1276{
1277 int error = FALSE;
1278 char_u *temp_string = NULL;
1279 int arg_len;
1280 char_u *expr_start;
1281 char_u *expr_end;
1282 char_u *name_end;
1283 int c1 = 0, c2;
1284 int i;
1285 VAR varp;
1286 char_u *name;
1287
1288 while (!ends_excmd(*arg) && !got_int)
1289 {
1290 /* Find the end of the name. */
1291 name_end = find_name_end(arg, &expr_start, &expr_end, FALSE);
1292
1293 if (!vim_iswhite(*name_end) && !ends_excmd(*name_end))
1294 {
1295 emsg_severe = TRUE;
1296 EMSG(_(e_trailing));
1297 break;
1298 }
1299 if (!error && !eap->skip)
1300 {
1301 if (expr_start != NULL)
1302 {
1303 temp_string = make_expanded_name(arg, expr_start,
1304 expr_end, name_end);
1305 if (temp_string == NULL)
1306 {
1307 /*
1308 * Report an invalid expression in braces, unless
1309 * the expression evaluation has been cancelled due
1310 * to an aborting error, an interrupt, or an
1311 * exception.
1312 */
1313 if (!aborting())
1314 {
1315 emsg_severe = TRUE;
1316 EMSG2(_(e_invarg2), arg);
1317 break;
1318 }
1319 error = TRUE;
1320 arg = skipwhite(name_end);
1321 continue;
1322 }
1323 arg = temp_string;
1324 arg_len = STRLEN(temp_string);
1325 }
1326 else
1327 {
1328 c1 = *name_end;
1329 *name_end = NUL;
1330 arg_len = (int)(name_end - arg);
1331 }
1332 i = find_vim_var(arg, arg_len);
1333 if (i >= 0)
1334 list_vim_var(i);
1335 else if (STRCMP("b:changedtick", arg) == 0)
1336 {
1337 char_u numbuf[NUMBUFLEN];
1338
1339 sprintf((char *)numbuf, "%ld",
1340 (long)curbuf->b_changedtick);
1341 list_one_var_a((char_u *)"b:", (char_u *)"changedtick",
1342 VAR_NUMBER, numbuf);
1343 }
1344 else
1345 {
1346 varp = find_var(arg, FALSE);
1347 if (varp == NULL)
1348 {
1349 /* Skip further arguments but do continue to
1350 * search for a trailing command. */
1351 EMSG2(_("E106: Unknown variable: \"%s\""), arg);
1352 error = TRUE;
1353 }
1354 else
1355 {
1356 name = vim_strchr(arg, ':');
1357 if (name != NULL)
1358 {
1359 /* "a:" vars have no name stored, use whole arg */
1360 if (arg[0] == 'a' && arg[1] == ':')
1361 c2 = NUL;
1362 else
1363 {
1364 c2 = *++name;
1365 *name = NUL;
1366 }
1367 list_one_var(varp, arg);
1368 if (c2 != NUL)
1369 *name = c2;
1370 }
1371 else
1372 list_one_var(varp, (char_u *)"");
1373 }
1374 }
1375 if (expr_start != NULL)
1376 vim_free(temp_string);
1377 else
1378 *name_end = c1;
1379 }
1380 arg = skipwhite(name_end);
1381 }
1382
1383 return arg;
1384}
1385
1386/*
1387 * Set one item of ":let var = expr" or ":let [v1, v2] = list" to its value.
1388 * Returns a pointer to the char just after the var name.
1389 * Returns NULL if there is an error.
1390 */
1391 static char_u *
1392ex_let_one(arg, tv, copy, endchars)
1393 char_u *arg; /* points to variable name */
1394 typeval *tv; /* value to assign to variable */
1395 int copy; /* copy value from "tv" */
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001396 char_u *endchars; /* valid chars after variable name or NULL */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001397{
1398 int c1;
1399 char_u *name;
1400 char_u *p;
1401 char_u *arg_end = NULL;
1402 int len;
1403 int opt_flags;
1404
1405 /*
1406 * ":let $VAR = expr": Set environment variable.
1407 */
1408 if (*arg == '$')
1409 {
1410 /* Find the end of the name. */
1411 ++arg;
1412 name = arg;
1413 len = get_env_len(&arg);
1414 if (len == 0)
1415 EMSG2(_(e_invarg2), name - 1);
1416 else
1417 {
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001418 if (endchars != NULL
1419 && vim_strchr(endchars, *skipwhite(arg)) == NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001420 EMSG(_(e_letunexp));
1421 else
1422 {
1423 c1 = name[len];
1424 name[len] = NUL;
1425 p = get_tv_string(tv);
1426 vim_setenv(name, p);
1427 if (STRICMP(name, "HOME") == 0)
1428 init_homedir();
1429 else if (didset_vim && STRICMP(name, "VIM") == 0)
1430 didset_vim = FALSE;
1431 else if (didset_vimruntime && STRICMP(name, "VIMRUNTIME") == 0)
1432 didset_vimruntime = FALSE;
1433 name[len] = c1;
1434 arg_end = arg;
1435 }
1436 }
1437 }
1438
1439 /*
1440 * ":let &option = expr": Set option value.
1441 * ":let &l:option = expr": Set local option value.
1442 * ":let &g:option = expr": Set global option value.
1443 */
1444 else if (*arg == '&')
1445 {
1446 /* Find the end of the name. */
1447 p = find_option_end(&arg, &opt_flags);
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001448 if (p == NULL || (endchars != NULL
1449 && vim_strchr(endchars, *skipwhite(p)) == NULL))
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001450 EMSG(_(e_letunexp));
1451 else
1452 {
1453 c1 = *p;
1454 *p = NUL;
1455 set_option_value(arg, get_tv_number(tv),
1456 get_tv_string(tv), opt_flags);
1457 *p = c1;
1458 arg_end = p;
1459 }
1460 }
1461
1462 /*
1463 * ":let @r = expr": Set register contents.
1464 */
1465 else if (*arg == '@')
1466 {
1467 ++arg;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001468 if (endchars != NULL
1469 && vim_strchr(endchars, *skipwhite(arg + 1)) == NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001470 EMSG(_(e_letunexp));
1471 else
1472 {
1473 write_reg_contents(*arg == '@' ? '"' : *arg,
1474 get_tv_string(tv), -1, FALSE);
1475 arg_end = arg + 1;
1476 }
1477 }
1478
1479 /*
1480 * ":let var = expr": Set internal variable.
1481 */
1482 else if (eval_isnamec(*arg) && !VIM_ISDIGIT(*arg))
1483 {
1484 char_u *exp_name = NULL;
1485 char_u *expr_start, *expr_end;
1486
1487 /* Find the end of the name. */
1488 p = find_name_end(arg, &expr_start, &expr_end, FALSE);
1489 if (expr_start != NULL)
1490 {
1491 exp_name = make_expanded_name(arg, expr_start, expr_end, p);
1492 arg = exp_name;
1493 }
1494
1495 if (arg == NULL)
1496 {
1497 /* Report an invalid expression in braces, unless the
1498 * expression evaluation has been cancelled due to an
1499 * aborting error, an interrupt, or an exception. */
1500 if (!aborting())
1501 EMSG2(_(e_invarg2), arg);
1502 }
1503 else if (*p == '[')
1504 arg_end = set_var_idx(arg, p, tv, copy, endchars);
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001505 else if (endchars != NULL
1506 && vim_strchr(endchars, *skipwhite(p)) == NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001507 EMSG(_(e_letunexp));
1508 else if (STRNCMP(arg, "b:changedtick", 13) == 0
1509 && !eval_isnamec(arg[13]))
1510 EMSG2(_(e_readonlyvar), arg);
1511 else
1512 {
1513 c1 = *p;
1514 *p = NUL;
1515 set_var(arg, tv, copy);
1516 *p = c1;
1517 arg_end = p;
1518 }
1519
1520 vim_free(exp_name);
1521 }
1522
1523 else
1524 EMSG2(_(e_invarg2), arg);
1525
1526 return arg_end;
1527}
1528
1529/*
1530 * Set a variable with an index: "name[expr]", "name[expr][expr]", etc.
1531 * Only works if "name" is an existing List.
1532 * "ip" points to the first '['.
1533 * Returns a pointer to just after the last used ']'; NULL for error.
1534 */
1535 static char_u *
1536set_var_idx(name, ip, rettv, copy, endchars)
1537 char_u *name;
1538 char_u *ip;
1539 typeval *rettv;
1540 int copy;
1541 char_u *endchars;
1542{
1543 VAR v;
1544 int c1;
1545 char_u *p;
1546 typeval var1;
1547 typeval *tv;
1548 long n;
1549 listitem *item;
1550
1551 c1 = *ip;
1552 *ip = NUL;
1553 v = find_var(name, TRUE);
1554 if (v == NULL)
1555 EMSG2(_(e_undefvar), name);
1556 *ip = c1;
1557 if (v == NULL)
1558 return NULL;
1559
1560 tv = &v->tv;
1561 for (p = ip; *p == '['; p = skipwhite(p + 1))
1562 {
1563 if (tv->v_type != VAR_LIST || tv->vval.v_list == NULL)
1564 {
1565 EMSG(_("E999: Can only index a List"));
1566 p = NULL;
1567 break;
1568 }
1569 p = skipwhite(p + 1);
1570 if (eval1(&p, &var1, TRUE) == FAIL) /* recursive! */
1571 {
1572 p = NULL;
1573 break;
1574 }
1575 if (*p != ']')
1576 {
1577 EMSG(_(e_missbrac));
1578 clear_tv(&var1);
1579 p = NULL;
1580 break;
1581 }
1582 n = get_tv_number(&var1);
1583 clear_tv(&var1);
1584 item = list_find(tv->vval.v_list, n);
1585 if (item == NULL)
1586 {
1587 EMSGN(_(e_listidx), n);
1588 p = NULL;
1589 break;
1590 }
1591 tv = &item->li_tv;
1592 }
1593
1594 if (p != NULL)
1595 {
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001596 if (endchars != NULL && vim_strchr(endchars, *p) == NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001597 {
1598 EMSG(_(e_letunexp));
1599 p = NULL;
1600 }
1601 else
1602 {
1603 clear_tv(tv);
1604 if (copy)
1605 copy_tv(tv, rettv);
1606 else
1607 {
1608 *tv = *rettv;
1609 init_tv(rettv);
1610 }
1611 }
1612 }
1613 return p;
1614}
1615
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001616/*
1617 * Add a watcher to a list.
1618 */
1619 static void
1620list_add_watch(l, lw)
1621 listvar *l;
1622 listwatch *lw;
1623{
1624 lw->lw_next = l->lv_watch;
1625 l->lv_watch = lw;
1626}
1627
1628/*
1629 * Remove a watches from a list.
1630 * No warning when it isn't found...
1631 */
1632 static void
1633list_rem_watch(l, lwrem)
1634 listvar *l;
1635 listwatch *lwrem;
1636{
1637 listwatch *lw, **lwp;
1638
1639 lwp = &l->lv_watch;
1640 for (lw = l->lv_watch; lw != NULL; lw = lw->lw_next)
1641 {
1642 if (lw == lwrem)
1643 {
1644 *lwp = lw->lw_next;
1645 break;
1646 }
1647 lwp = &lw->lw_next;
1648 }
1649}
1650
1651/*
1652 * Just before removing an item from a list: advance watchers to the next
1653 * item.
1654 */
1655 static void
1656list_fix_watch(l, item)
1657 listvar *l;
1658 listitem *item;
1659{
1660 listwatch *lw;
1661
1662 for (lw = l->lv_watch; lw != NULL; lw = lw->lw_next)
1663 if (lw->lw_item == item)
1664 lw->lw_item = item->li_next;
1665}
1666
1667/*
1668 * Evaluate the expression used in a ":for var in expr" command.
1669 * "arg" points to "var".
1670 * Set "*errp" to TRUE for an error, FALSE otherwise;
1671 * Return a pointer that holds the info. Null when there is an error.
1672 */
1673 void *
1674eval_for_line(arg, errp, nextcmdp, skip)
1675 char_u *arg;
1676 int *errp;
1677 char_u **nextcmdp;
1678 int skip;
1679{
1680 forinfo *fi;
1681 char_u *expr;
1682 typeval tv;
1683 listvar *l;
1684
1685 *errp = TRUE; /* default: there is an error */
1686
1687 fi = (forinfo *)alloc_clear(sizeof(forinfo));
1688 if (fi == NULL)
1689 return NULL;
1690
1691 expr = skip_var_list(arg, &fi->fi_varcount, &fi->fi_semicolon);
1692 if (expr == NULL)
1693 return fi;
1694
1695 expr = skipwhite(expr);
1696 if (expr[0] != 'i' || expr[1] != 'n' || !vim_iswhite(expr[2]))
1697 {
1698 EMSG(_("E999: Missing \"in\" after :for"));
1699 return fi;
1700 }
1701
1702 if (skip)
1703 ++emsg_skip;
1704 if (eval0(skipwhite(expr + 2), &tv, nextcmdp, !skip) == OK)
1705 {
1706 *errp = FALSE;
1707 if (!skip)
1708 {
1709 l = tv.vval.v_list;
1710 if (tv.v_type != VAR_LIST || l == NULL)
1711 EMSG(_(e_listreq));
1712 else
1713 {
1714 fi->fi_list = l;
1715 list_add_watch(l, &fi->fi_lw);
1716 fi->fi_lw.lw_item = l->lv_first;
1717 }
1718 }
1719 }
1720 if (skip)
1721 --emsg_skip;
1722
1723 return fi;
1724}
1725
1726/*
1727 * Use the first item in a ":for" list. Advance to the next.
1728 * Assign the values to the variable (list). "arg" points to the first one.
1729 * Return TRUE when a valid item was found, FALSE when at end of list or
1730 * something wrong.
1731 */
1732 int
1733next_for_item(fi_void, arg)
1734 void *fi_void;
1735 char_u *arg;
1736{
1737 forinfo *fi = (forinfo *)fi_void;
1738 int result;
1739 listitem *item;
1740
1741 item = fi->fi_lw.lw_item;
1742 if (item == NULL)
1743 result = FALSE;
1744 else
1745 {
1746 fi->fi_lw.lw_item = item->li_next;
1747 result = (ex_let_vars(arg, &item->li_tv, TRUE,
1748 fi->fi_semicolon, fi->fi_varcount, NULL) == OK);
1749 }
1750 return result;
1751}
1752
1753/*
1754 * Free the structure used to store info used by ":for".
1755 */
1756 void
1757free_for_info(fi_void)
1758 void *fi_void;
1759{
1760 forinfo *fi = (forinfo *)fi_void;
1761
1762 if (fi->fi_list != NULL)
1763 list_rem_watch(fi->fi_list, &fi->fi_lw);
1764 vim_free(fi);
1765}
1766
Bram Moolenaar071d4272004-06-13 20:20:40 +00001767#if defined(FEAT_CMDL_COMPL) || defined(PROTO)
1768
1769 void
1770set_context_for_expression(xp, arg, cmdidx)
1771 expand_T *xp;
1772 char_u *arg;
1773 cmdidx_T cmdidx;
1774{
1775 int got_eq = FALSE;
1776 int c;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001777 char_u *p;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001778
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001779 if (cmdidx == CMD_let)
1780 {
1781 xp->xp_context = EXPAND_USER_VARS;
1782 if (vim_strchr(arg, '=') == NULL)
1783 {
1784 /* ":let var1 var2 ...": find last space. */
1785 for (p = arg + STRLEN(arg); p > arg; )
1786 {
1787 xp->xp_pattern = p;
1788 p = mb_ptr_back(arg, p);
1789 if (vim_iswhite(*p))
1790 break;
1791 }
1792 return;
1793 }
1794 }
1795 else
1796 xp->xp_context = cmdidx == CMD_call ? EXPAND_FUNCTIONS
1797 : EXPAND_EXPRESSION;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001798 while ((xp->xp_pattern = vim_strpbrk(arg,
1799 (char_u *)"\"'+-*/%.=!?~|&$([<>,#")) != NULL)
1800 {
1801 c = *xp->xp_pattern;
1802 if (c == '&')
1803 {
1804 c = xp->xp_pattern[1];
1805 if (c == '&')
1806 {
1807 ++xp->xp_pattern;
1808 xp->xp_context = cmdidx != CMD_let || got_eq
1809 ? EXPAND_EXPRESSION : EXPAND_NOTHING;
1810 }
1811 else if (c != ' ')
1812 xp->xp_context = EXPAND_SETTINGS;
1813 }
1814 else if (c == '$')
1815 {
1816 /* environment variable */
1817 xp->xp_context = EXPAND_ENV_VARS;
1818 }
1819 else if (c == '=')
1820 {
1821 got_eq = TRUE;
1822 xp->xp_context = EXPAND_EXPRESSION;
1823 }
1824 else if (c == '<'
1825 && xp->xp_context == EXPAND_FUNCTIONS
1826 && vim_strchr(xp->xp_pattern, '(') == NULL)
1827 {
1828 /* Function name can start with "<SNR>" */
1829 break;
1830 }
1831 else if (cmdidx != CMD_let || got_eq)
1832 {
1833 if (c == '"') /* string */
1834 {
1835 while ((c = *++xp->xp_pattern) != NUL && c != '"')
1836 if (c == '\\' && xp->xp_pattern[1] != NUL)
1837 ++xp->xp_pattern;
1838 xp->xp_context = EXPAND_NOTHING;
1839 }
1840 else if (c == '\'') /* literal string */
1841 {
1842 while ((c = *++xp->xp_pattern) != NUL && c != '\'')
1843 /* skip */ ;
1844 xp->xp_context = EXPAND_NOTHING;
1845 }
1846 else if (c == '|')
1847 {
1848 if (xp->xp_pattern[1] == '|')
1849 {
1850 ++xp->xp_pattern;
1851 xp->xp_context = EXPAND_EXPRESSION;
1852 }
1853 else
1854 xp->xp_context = EXPAND_COMMANDS;
1855 }
1856 else
1857 xp->xp_context = EXPAND_EXPRESSION;
1858 }
1859 else
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001860 /* Doesn't look like something valid, expand as an expression
1861 * anyway. */
1862 xp->xp_context = EXPAND_EXPRESSION;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001863 arg = xp->xp_pattern;
1864 if (*arg != NUL)
1865 while ((c = *++arg) != NUL && (c == ' ' || c == '\t'))
1866 /* skip */ ;
1867 }
1868 xp->xp_pattern = arg;
1869}
1870
1871#endif /* FEAT_CMDL_COMPL */
1872
1873/*
1874 * ":1,25call func(arg1, arg2)" function call.
1875 */
1876 void
1877ex_call(eap)
1878 exarg_T *eap;
1879{
1880 char_u *arg = eap->arg;
1881 char_u *startarg;
1882 char_u *alias;
1883 char_u *name;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001884 typeval rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001885 int len;
1886 linenr_T lnum;
1887 int doesrange;
1888 int failed = FALSE;
1889
1890 name = arg;
1891 len = get_func_len(&arg, &alias, !eap->skip);
1892 if (len == 0)
1893 goto end;
1894 if (alias != NULL)
1895 name = alias;
1896
1897 startarg = arg;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001898 rettv.v_type = VAR_UNKNOWN; /* clear_tv() uses this */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001899
1900 if (*startarg != '(')
1901 {
1902 EMSG2(_("E107: Missing braces: %s"), name);
1903 goto end;
1904 }
1905
1906 /*
1907 * When skipping, evaluate the function once, to find the end of the
1908 * arguments.
1909 * When the function takes a range, this is discovered after the first
1910 * call, and the loop is broken.
1911 */
1912 if (eap->skip)
1913 {
1914 ++emsg_skip;
1915 lnum = eap->line2; /* do it once, also with an invalid range */
1916 }
1917 else
1918 lnum = eap->line1;
1919 for ( ; lnum <= eap->line2; ++lnum)
1920 {
1921 if (!eap->skip && eap->addr_count > 0)
1922 {
1923 curwin->w_cursor.lnum = lnum;
1924 curwin->w_cursor.col = 0;
1925 }
1926 arg = startarg;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001927 if (get_func_tv(name, len, &rettv, &arg,
Bram Moolenaar071d4272004-06-13 20:20:40 +00001928 eap->line1, eap->line2, &doesrange, !eap->skip) == FAIL)
1929 {
1930 failed = TRUE;
1931 break;
1932 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001933 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001934 if (doesrange || eap->skip)
1935 break;
1936 /* Stop when immediately aborting on error, or when an interrupt
Bram Moolenaar49cd9572005-01-03 21:06:01 +00001937 * occurred or an exception was thrown but not caught.
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001938 * get_func_tv() returned OK, so that the check for trailing
Bram Moolenaar49cd9572005-01-03 21:06:01 +00001939 * characters below is executed. */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001940 if (aborting())
1941 break;
1942 }
1943 if (eap->skip)
1944 --emsg_skip;
1945
1946 if (!failed)
1947 {
1948 /* Check for trailing illegal characters and a following command. */
1949 if (!ends_excmd(*arg))
1950 {
1951 emsg_severe = TRUE;
1952 EMSG(_(e_trailing));
1953 }
1954 else
1955 eap->nextcmd = check_nextcmd(arg);
1956 }
1957
1958end:
1959 if (alias != NULL)
1960 vim_free(alias);
1961}
1962
1963/*
1964 * ":unlet[!] var1 ... " command.
1965 */
1966 void
1967ex_unlet(eap)
1968 exarg_T *eap;
1969{
1970 char_u *arg = eap->arg;
1971 char_u *name_end;
1972 char_u cc;
1973 char_u *expr_start;
1974 char_u *expr_end;
1975 int error = FALSE;
1976
1977 do
1978 {
1979 /* Find the end of the name. */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001980 name_end = find_name_end(arg, &expr_start, &expr_end, FALSE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001981
1982 if (!vim_iswhite(*name_end) && !ends_excmd(*name_end))
1983 {
1984 emsg_severe = TRUE;
1985 EMSG(_(e_trailing));
1986 break;
1987 }
1988
1989 if (!error && !eap->skip)
1990 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00001991 if (expr_start != NULL)
1992 {
1993 char_u *temp_string;
1994
1995 temp_string = make_expanded_name(arg, expr_start,
1996 expr_end, name_end);
1997 if (temp_string == NULL)
1998 {
1999 /*
2000 * Report an invalid expression in braces, unless the
2001 * expression evaluation has been cancelled due to an
2002 * aborting error, an interrupt, or an exception.
2003 */
2004 if (!aborting())
2005 {
2006 emsg_severe = TRUE;
2007 EMSG2(_(e_invarg2), arg);
2008 break;
2009 }
2010 error = TRUE;
2011 }
2012 else
2013 {
2014 if (do_unlet(temp_string) == FAIL && !eap->forceit)
2015 {
2016 EMSG2(_("E108: No such variable: \"%s\""), temp_string);
2017 error = TRUE;
2018 }
2019 vim_free(temp_string);
2020 }
2021 }
2022 else
Bram Moolenaar071d4272004-06-13 20:20:40 +00002023 {
2024 cc = *name_end;
2025 *name_end = NUL;
2026
2027 if (do_unlet(arg) == FAIL && !eap->forceit)
2028 {
2029 EMSG2(_("E108: No such variable: \"%s\""), arg);
2030 error = TRUE;
2031 }
2032
2033 *name_end = cc;
2034 }
2035 }
2036 arg = skipwhite(name_end);
2037 } while (!ends_excmd(*arg));
2038
2039 eap->nextcmd = check_nextcmd(arg);
2040}
2041
2042/*
2043 * "unlet" a variable. Return OK if it existed, FAIL if not.
2044 */
2045 int
2046do_unlet(name)
2047 char_u *name;
2048{
2049 VAR v;
2050
2051 v = find_var(name, TRUE);
2052 if (v != NULL)
2053 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +00002054 clear_var(v);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002055 return OK;
2056 }
2057 return FAIL;
2058}
2059
2060#if (defined(FEAT_MENU) && defined(FEAT_MULTI_LANG)) || defined(PROTO)
2061/*
2062 * Delete all "menutrans_" variables.
2063 */
2064 void
2065del_menutrans_vars()
2066{
2067 int i;
2068
2069 for (i = 0; i < variables.ga_len; ++i)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00002070 if (VAR_ENTRY(i).v_name != NULL
2071 && STRNCMP(VAR_ENTRY(i).v_name, "menutrans_", 10) == 0)
2072 clear_var(&VAR_ENTRY(i));
Bram Moolenaar071d4272004-06-13 20:20:40 +00002073}
2074#endif
2075
2076#if defined(FEAT_CMDL_COMPL) || defined(PROTO)
2077
2078/*
2079 * Local string buffer for the next two functions to store a variable name
2080 * with its prefix. Allocated in cat_prefix_varname(), freed later in
2081 * get_user_var_name().
2082 */
2083
2084static char_u *cat_prefix_varname __ARGS((int prefix, char_u *name));
2085
2086static char_u *varnamebuf = NULL;
2087static int varnamebuflen = 0;
2088
2089/*
2090 * Function to concatenate a prefix and a variable name.
2091 */
2092 static char_u *
2093cat_prefix_varname(prefix, name)
2094 int prefix;
2095 char_u *name;
2096{
2097 int len;
2098
2099 len = (int)STRLEN(name) + 3;
2100 if (len > varnamebuflen)
2101 {
2102 vim_free(varnamebuf);
2103 len += 10; /* some additional space */
2104 varnamebuf = alloc(len);
2105 if (varnamebuf == NULL)
2106 {
2107 varnamebuflen = 0;
2108 return NULL;
2109 }
2110 varnamebuflen = len;
2111 }
2112 *varnamebuf = prefix;
2113 varnamebuf[1] = ':';
2114 STRCPY(varnamebuf + 2, name);
2115 return varnamebuf;
2116}
2117
2118/*
2119 * Function given to ExpandGeneric() to obtain the list of user defined
2120 * (global/buffer/window/built-in) variable names.
2121 */
2122/*ARGSUSED*/
2123 char_u *
2124get_user_var_name(xp, idx)
2125 expand_T *xp;
2126 int idx;
2127{
2128 static int gidx;
2129 static int bidx;
2130 static int widx;
2131 static int vidx;
2132 char_u *name;
2133
2134 if (idx == 0)
2135 gidx = bidx = widx = vidx = 0;
2136 if (gidx < variables.ga_len) /* Global variables */
2137 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +00002138 while ((name = VAR_ENTRY(gidx++).v_name) == NULL
Bram Moolenaar071d4272004-06-13 20:20:40 +00002139 && gidx < variables.ga_len)
2140 /* skip */;
2141 if (name != NULL)
2142 {
2143 if (STRNCMP("g:", xp->xp_pattern, 2) == 0)
2144 return cat_prefix_varname('g', name);
2145 else
2146 return name;
2147 }
2148 }
2149 if (bidx < curbuf->b_vars.ga_len) /* Current buffer variables */
2150 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +00002151 while ((name = BVAR_ENTRY(bidx++).v_name) == NULL
Bram Moolenaar071d4272004-06-13 20:20:40 +00002152 && bidx < curbuf->b_vars.ga_len)
2153 /* skip */;
2154 if (name != NULL)
2155 return cat_prefix_varname('b', name);
2156 }
2157 if (bidx == curbuf->b_vars.ga_len)
2158 {
2159 ++bidx;
2160 return (char_u *)"b:changedtick";
2161 }
2162 if (widx < curwin->w_vars.ga_len) /* Current window variables */
2163 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +00002164 while ((name = WVAR_ENTRY(widx++).v_name) == NULL
Bram Moolenaar071d4272004-06-13 20:20:40 +00002165 && widx < curwin->w_vars.ga_len)
2166 /* skip */;
2167 if (name != NULL)
2168 return cat_prefix_varname('w', name);
2169 }
2170 if (vidx < VV_LEN) /* Built-in variables */
2171 return cat_prefix_varname('v', (char_u *)vimvars[vidx++].name);
2172
2173 vim_free(varnamebuf);
2174 varnamebuf = NULL;
2175 varnamebuflen = 0;
2176 return NULL;
2177}
2178
2179#endif /* FEAT_CMDL_COMPL */
2180
2181/*
2182 * types for expressions.
2183 */
2184typedef enum
2185{
2186 TYPE_UNKNOWN = 0
2187 , TYPE_EQUAL /* == */
2188 , TYPE_NEQUAL /* != */
2189 , TYPE_GREATER /* > */
2190 , TYPE_GEQUAL /* >= */
2191 , TYPE_SMALLER /* < */
2192 , TYPE_SEQUAL /* <= */
2193 , TYPE_MATCH /* =~ */
2194 , TYPE_NOMATCH /* !~ */
2195} exptype_T;
2196
2197/*
2198 * The "evaluate" argument: When FALSE, the argument is only parsed but not
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002199 * executed. The function may return OK, but the rettv will be of type
Bram Moolenaar071d4272004-06-13 20:20:40 +00002200 * VAR_UNKNOWN. The function still returns FAIL for a syntax error.
2201 */
2202
2203/*
2204 * Handle zero level expression.
2205 * This calls eval1() and handles error message and nextcmd.
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002206 * Put the result in "rettv" when returning OK and "evaluate" is TRUE.
Bram Moolenaar071d4272004-06-13 20:20:40 +00002207 * Return OK or FAIL.
2208 */
2209 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002210eval0(arg, rettv, nextcmd, evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002211 char_u *arg;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002212 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002213 char_u **nextcmd;
2214 int evaluate;
2215{
2216 int ret;
2217 char_u *p;
2218
2219 p = skipwhite(arg);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002220 ret = eval1(&p, rettv, evaluate);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002221 if (ret == FAIL || !ends_excmd(*p))
2222 {
2223 if (ret != FAIL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002224 clear_tv(rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002225 /*
2226 * Report the invalid expression unless the expression evaluation has
2227 * been cancelled due to an aborting error, an interrupt, or an
2228 * exception.
2229 */
2230 if (!aborting())
2231 EMSG2(_(e_invexpr2), arg);
2232 ret = FAIL;
2233 }
2234 if (nextcmd != NULL)
2235 *nextcmd = check_nextcmd(p);
2236
2237 return ret;
2238}
2239
2240/*
2241 * Handle top level expression:
2242 * expr1 ? expr0 : expr0
2243 *
2244 * "arg" must point to the first non-white of the expression.
2245 * "arg" is advanced to the next non-white after the recognized expression.
2246 *
2247 * Return OK or FAIL.
2248 */
2249 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002250eval1(arg, rettv, evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002251 char_u **arg;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002252 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002253 int evaluate;
2254{
2255 int result;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00002256 typeval var2;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002257
2258 /*
2259 * Get the first variable.
2260 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002261 if (eval2(arg, rettv, evaluate) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002262 return FAIL;
2263
2264 if ((*arg)[0] == '?')
2265 {
2266 result = FALSE;
2267 if (evaluate)
2268 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002269 if (get_tv_number(rettv) != 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002270 result = TRUE;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002271 clear_tv(rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002272 }
2273
2274 /*
2275 * Get the second variable.
2276 */
2277 *arg = skipwhite(*arg + 1);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002278 if (eval1(arg, rettv, evaluate && result) == FAIL) /* recursive! */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002279 return FAIL;
2280
2281 /*
2282 * Check for the ":".
2283 */
2284 if ((*arg)[0] != ':')
2285 {
2286 EMSG(_("E109: Missing ':' after '?'"));
2287 if (evaluate && result)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002288 clear_tv(rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002289 return FAIL;
2290 }
2291
2292 /*
2293 * Get the third variable.
2294 */
2295 *arg = skipwhite(*arg + 1);
2296 if (eval1(arg, &var2, evaluate && !result) == FAIL) /* recursive! */
2297 {
2298 if (evaluate && result)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002299 clear_tv(rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002300 return FAIL;
2301 }
2302 if (evaluate && !result)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002303 *rettv = var2;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002304 }
2305
2306 return OK;
2307}
2308
2309/*
2310 * Handle first level expression:
2311 * expr2 || expr2 || expr2 logical OR
2312 *
2313 * "arg" must point to the first non-white of the expression.
2314 * "arg" is advanced to the next non-white after the recognized expression.
2315 *
2316 * Return OK or FAIL.
2317 */
2318 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002319eval2(arg, rettv, evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002320 char_u **arg;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002321 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002322 int evaluate;
2323{
Bram Moolenaar49cd9572005-01-03 21:06:01 +00002324 typeval var2;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002325 long result;
2326 int first;
2327
2328 /*
2329 * Get the first variable.
2330 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002331 if (eval3(arg, rettv, evaluate) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002332 return FAIL;
2333
2334 /*
2335 * Repeat until there is no following "||".
2336 */
2337 first = TRUE;
2338 result = FALSE;
2339 while ((*arg)[0] == '|' && (*arg)[1] == '|')
2340 {
2341 if (evaluate && first)
2342 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002343 if (get_tv_number(rettv) != 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002344 result = TRUE;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002345 clear_tv(rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002346 first = FALSE;
2347 }
2348
2349 /*
2350 * Get the second variable.
2351 */
2352 *arg = skipwhite(*arg + 2);
2353 if (eval3(arg, &var2, evaluate && !result) == FAIL)
2354 return FAIL;
2355
2356 /*
2357 * Compute the result.
2358 */
2359 if (evaluate && !result)
2360 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002361 if (get_tv_number(&var2) != 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002362 result = TRUE;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002363 clear_tv(&var2);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002364 }
2365 if (evaluate)
2366 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002367 rettv->v_type = VAR_NUMBER;
2368 rettv->vval.v_number = result;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002369 }
2370 }
2371
2372 return OK;
2373}
2374
2375/*
2376 * Handle second level expression:
2377 * expr3 && expr3 && expr3 logical AND
2378 *
2379 * "arg" must point to the first non-white of the expression.
2380 * "arg" is advanced to the next non-white after the recognized expression.
2381 *
2382 * Return OK or FAIL.
2383 */
2384 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002385eval3(arg, rettv, evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002386 char_u **arg;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002387 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002388 int evaluate;
2389{
Bram Moolenaar49cd9572005-01-03 21:06:01 +00002390 typeval var2;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002391 long result;
2392 int first;
2393
2394 /*
2395 * Get the first variable.
2396 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002397 if (eval4(arg, rettv, evaluate) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002398 return FAIL;
2399
2400 /*
2401 * Repeat until there is no following "&&".
2402 */
2403 first = TRUE;
2404 result = TRUE;
2405 while ((*arg)[0] == '&' && (*arg)[1] == '&')
2406 {
2407 if (evaluate && first)
2408 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002409 if (get_tv_number(rettv) == 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002410 result = FALSE;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002411 clear_tv(rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002412 first = FALSE;
2413 }
2414
2415 /*
2416 * Get the second variable.
2417 */
2418 *arg = skipwhite(*arg + 2);
2419 if (eval4(arg, &var2, evaluate && result) == FAIL)
2420 return FAIL;
2421
2422 /*
2423 * Compute the result.
2424 */
2425 if (evaluate && result)
2426 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002427 if (get_tv_number(&var2) == 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002428 result = FALSE;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002429 clear_tv(&var2);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002430 }
2431 if (evaluate)
2432 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002433 rettv->v_type = VAR_NUMBER;
2434 rettv->vval.v_number = result;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002435 }
2436 }
2437
2438 return OK;
2439}
2440
2441/*
2442 * Handle third level expression:
2443 * var1 == var2
2444 * var1 =~ var2
2445 * var1 != var2
2446 * var1 !~ var2
2447 * var1 > var2
2448 * var1 >= var2
2449 * var1 < var2
2450 * var1 <= var2
2451 *
2452 * "arg" must point to the first non-white of the expression.
2453 * "arg" is advanced to the next non-white after the recognized expression.
2454 *
2455 * Return OK or FAIL.
2456 */
2457 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002458eval4(arg, rettv, evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002459 char_u **arg;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002460 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002461 int evaluate;
2462{
Bram Moolenaar49cd9572005-01-03 21:06:01 +00002463 typeval var2;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002464 char_u *p;
2465 int i;
2466 exptype_T type = TYPE_UNKNOWN;
2467 int len = 2;
2468 long n1, n2;
2469 char_u *s1, *s2;
2470 char_u buf1[NUMBUFLEN], buf2[NUMBUFLEN];
2471 regmatch_T regmatch;
2472 int ic;
2473 char_u *save_cpo;
2474
2475 /*
2476 * Get the first variable.
2477 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002478 if (eval5(arg, rettv, evaluate) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002479 return FAIL;
2480
2481 p = *arg;
2482 switch (p[0])
2483 {
2484 case '=': if (p[1] == '=')
2485 type = TYPE_EQUAL;
2486 else if (p[1] == '~')
2487 type = TYPE_MATCH;
2488 break;
2489 case '!': if (p[1] == '=')
2490 type = TYPE_NEQUAL;
2491 else if (p[1] == '~')
2492 type = TYPE_NOMATCH;
2493 break;
2494 case '>': if (p[1] != '=')
2495 {
2496 type = TYPE_GREATER;
2497 len = 1;
2498 }
2499 else
2500 type = TYPE_GEQUAL;
2501 break;
2502 case '<': if (p[1] != '=')
2503 {
2504 type = TYPE_SMALLER;
2505 len = 1;
2506 }
2507 else
2508 type = TYPE_SEQUAL;
2509 break;
2510 }
2511
2512 /*
2513 * If there is a comparitive operator, use it.
2514 */
2515 if (type != TYPE_UNKNOWN)
2516 {
2517 /* extra question mark appended: ignore case */
2518 if (p[len] == '?')
2519 {
2520 ic = TRUE;
2521 ++len;
2522 }
2523 /* extra '#' appended: match case */
2524 else if (p[len] == '#')
2525 {
2526 ic = FALSE;
2527 ++len;
2528 }
2529 /* nothing appened: use 'ignorecase' */
2530 else
2531 ic = p_ic;
2532
2533 /*
2534 * Get the second variable.
2535 */
2536 *arg = skipwhite(p + len);
2537 if (eval5(arg, &var2, evaluate) == FAIL)
2538 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002539 clear_tv(rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002540 return FAIL;
2541 }
2542
2543 if (evaluate)
2544 {
2545 /*
2546 * If one of the two variables is a number, compare as a number.
2547 * When using "=~" or "!~", always compare as string.
2548 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002549 if ((rettv->v_type == VAR_NUMBER || var2.v_type == VAR_NUMBER)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002550 && type != TYPE_MATCH && type != TYPE_NOMATCH)
2551 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002552 n1 = get_tv_number(rettv);
2553 n2 = get_tv_number(&var2);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002554 switch (type)
2555 {
2556 case TYPE_EQUAL: n1 = (n1 == n2); break;
2557 case TYPE_NEQUAL: n1 = (n1 != n2); break;
2558 case TYPE_GREATER: n1 = (n1 > n2); break;
2559 case TYPE_GEQUAL: n1 = (n1 >= n2); break;
2560 case TYPE_SMALLER: n1 = (n1 < n2); break;
2561 case TYPE_SEQUAL: n1 = (n1 <= n2); break;
2562 case TYPE_UNKNOWN:
2563 case TYPE_MATCH:
2564 case TYPE_NOMATCH: break; /* avoid gcc warning */
2565 }
2566 }
2567 else
2568 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002569 s1 = get_tv_string_buf(rettv, buf1);
2570 s2 = get_tv_string_buf(&var2, buf2);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002571 if (type != TYPE_MATCH && type != TYPE_NOMATCH)
2572 i = ic ? MB_STRICMP(s1, s2) : STRCMP(s1, s2);
2573 else
2574 i = 0;
2575 n1 = FALSE;
2576 switch (type)
2577 {
2578 case TYPE_EQUAL: n1 = (i == 0); break;
2579 case TYPE_NEQUAL: n1 = (i != 0); break;
2580 case TYPE_GREATER: n1 = (i > 0); break;
2581 case TYPE_GEQUAL: n1 = (i >= 0); break;
2582 case TYPE_SMALLER: n1 = (i < 0); break;
2583 case TYPE_SEQUAL: n1 = (i <= 0); break;
2584
2585 case TYPE_MATCH:
2586 case TYPE_NOMATCH:
2587 /* avoid 'l' flag in 'cpoptions' */
2588 save_cpo = p_cpo;
2589 p_cpo = (char_u *)"";
2590 regmatch.regprog = vim_regcomp(s2,
2591 RE_MAGIC + RE_STRING);
2592 regmatch.rm_ic = ic;
2593 if (regmatch.regprog != NULL)
2594 {
2595 n1 = vim_regexec_nl(&regmatch, s1, (colnr_T)0);
2596 vim_free(regmatch.regprog);
2597 if (type == TYPE_NOMATCH)
2598 n1 = !n1;
2599 }
2600 p_cpo = save_cpo;
2601 break;
2602
2603 case TYPE_UNKNOWN: break; /* avoid gcc warning */
2604 }
2605 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002606 clear_tv(rettv);
2607 clear_tv(&var2);
2608 rettv->v_type = VAR_NUMBER;
2609 rettv->vval.v_number = n1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002610 }
2611 }
2612
2613 return OK;
2614}
2615
2616/*
2617 * Handle fourth level expression:
2618 * + number addition
2619 * - number subtraction
2620 * . string concatenation
2621 *
2622 * "arg" must point to the first non-white of the expression.
2623 * "arg" is advanced to the next non-white after the recognized expression.
2624 *
2625 * Return OK or FAIL.
2626 */
2627 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002628eval5(arg, rettv, evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002629 char_u **arg;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002630 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002631 int evaluate;
2632{
Bram Moolenaar49cd9572005-01-03 21:06:01 +00002633 typeval var2;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002634 int op;
2635 long n1, n2;
2636 char_u *s1, *s2;
2637 char_u buf1[NUMBUFLEN], buf2[NUMBUFLEN];
2638 char_u *p;
2639
2640 /*
2641 * Get the first variable.
2642 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002643 if (eval6(arg, rettv, evaluate) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002644 return FAIL;
2645
2646 /*
2647 * Repeat computing, until no '+', '-' or '.' is following.
2648 */
2649 for (;;)
2650 {
2651 op = **arg;
2652 if (op != '+' && op != '-' && op != '.')
2653 break;
2654
2655 /*
2656 * Get the second variable.
2657 */
2658 *arg = skipwhite(*arg + 1);
2659 if (eval6(arg, &var2, evaluate) == FAIL)
2660 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002661 clear_tv(rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002662 return FAIL;
2663 }
2664
2665 if (evaluate)
2666 {
2667 /*
2668 * Compute the result.
2669 */
2670 if (op == '.')
2671 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002672 s1 = get_tv_string_buf(rettv, buf1);
2673 s2 = get_tv_string_buf(&var2, buf2);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002674 op = (int)STRLEN(s1);
2675 p = alloc((unsigned)(op + STRLEN(s2) + 1));
2676 if (p != NULL)
2677 {
2678 STRCPY(p, s1);
2679 STRCPY(p + op, s2);
2680 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002681 clear_tv(rettv);
2682 rettv->v_type = VAR_STRING;
2683 rettv->vval.v_string = p;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002684 }
2685 else
2686 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002687 n1 = get_tv_number(rettv);
2688 n2 = get_tv_number(&var2);
2689 clear_tv(rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002690 if (op == '+')
2691 n1 = n1 + n2;
2692 else
2693 n1 = n1 - n2;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002694 rettv->v_type = VAR_NUMBER;
2695 rettv->vval.v_number = n1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002696 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002697 clear_tv(&var2);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002698 }
2699 }
2700 return OK;
2701}
2702
2703/*
2704 * Handle fifth level expression:
2705 * * number multiplication
2706 * / number division
2707 * % number modulo
2708 *
2709 * "arg" must point to the first non-white of the expression.
2710 * "arg" is advanced to the next non-white after the recognized expression.
2711 *
2712 * Return OK or FAIL.
2713 */
2714 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002715eval6(arg, rettv, evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002716 char_u **arg;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002717 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002718 int evaluate;
2719{
Bram Moolenaar49cd9572005-01-03 21:06:01 +00002720 typeval var2;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002721 int op;
2722 long n1, n2;
2723
2724 /*
2725 * Get the first variable.
2726 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002727 if (eval7(arg, rettv, evaluate) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002728 return FAIL;
2729
2730 /*
2731 * Repeat computing, until no '*', '/' or '%' is following.
2732 */
2733 for (;;)
2734 {
2735 op = **arg;
2736 if (op != '*' && op != '/' && op != '%')
2737 break;
2738
2739 if (evaluate)
2740 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002741 n1 = get_tv_number(rettv);
2742 clear_tv(rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002743 }
2744 else
2745 n1 = 0;
2746
2747 /*
2748 * Get the second variable.
2749 */
2750 *arg = skipwhite(*arg + 1);
2751 if (eval7(arg, &var2, evaluate) == FAIL)
2752 return FAIL;
2753
2754 if (evaluate)
2755 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002756 n2 = get_tv_number(&var2);
2757 clear_tv(&var2);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002758
2759 /*
2760 * Compute the result.
2761 */
2762 if (op == '*')
2763 n1 = n1 * n2;
2764 else if (op == '/')
2765 {
2766 if (n2 == 0) /* give an error message? */
2767 n1 = 0x7fffffffL;
2768 else
2769 n1 = n1 / n2;
2770 }
2771 else
2772 {
2773 if (n2 == 0) /* give an error message? */
2774 n1 = 0;
2775 else
2776 n1 = n1 % n2;
2777 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002778 rettv->v_type = VAR_NUMBER;
2779 rettv->vval.v_number = n1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002780 }
2781 }
2782
2783 return OK;
2784}
2785
2786/*
2787 * Handle sixth level expression:
2788 * number number constant
2789 * "string" string contstant
2790 * 'string' literal string contstant
2791 * &option-name option value
2792 * @r register contents
2793 * identifier variable value
2794 * function() function call
2795 * $VAR environment variable
2796 * (expression) nested expression
2797 *
2798 * Also handle:
2799 * ! in front logical NOT
2800 * - in front unary minus
2801 * + in front unary plus (ignored)
2802 * trailing [] subscript in String
2803 *
2804 * "arg" must point to the first non-white of the expression.
2805 * "arg" is advanced to the next non-white after the recognized expression.
2806 *
2807 * Return OK or FAIL.
2808 */
2809 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002810eval7(arg, rettv, evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002811 char_u **arg;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002812 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002813 int evaluate;
2814{
Bram Moolenaar071d4272004-06-13 20:20:40 +00002815 long n;
2816 int len;
2817 char_u *s;
2818 int val;
2819 char_u *start_leader, *end_leader;
2820 int ret = OK;
2821 char_u *alias;
2822
2823 /*
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002824 * Initialise variable so that clear_tv() can't mistake this for a
Bram Moolenaar49cd9572005-01-03 21:06:01 +00002825 * string and free a string that isn't there.
Bram Moolenaar071d4272004-06-13 20:20:40 +00002826 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002827 rettv->v_type = VAR_UNKNOWN;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002828
2829 /*
2830 * Skip '!' and '-' characters. They are handled later.
2831 */
2832 start_leader = *arg;
2833 while (**arg == '!' || **arg == '-' || **arg == '+')
2834 *arg = skipwhite(*arg + 1);
2835 end_leader = *arg;
2836
2837 switch (**arg)
2838 {
2839 /*
2840 * Number constant.
2841 */
2842 case '0':
2843 case '1':
2844 case '2':
2845 case '3':
2846 case '4':
2847 case '5':
2848 case '6':
2849 case '7':
2850 case '8':
2851 case '9':
2852 vim_str2nr(*arg, NULL, &len, TRUE, TRUE, &n, NULL);
2853 *arg += len;
2854 if (evaluate)
2855 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002856 rettv->v_type = VAR_NUMBER;
2857 rettv->vval.v_number = n;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002858 }
2859 break;
2860
2861 /*
2862 * String constant: "string".
2863 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002864 case '"': ret = get_string_tv(arg, rettv, evaluate);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002865 break;
2866
2867 /*
2868 * Literal string constant: 'string'.
2869 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002870 case '\'': ret = get_lit_string_tv(arg, rettv, evaluate);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00002871 break;
2872
2873 /*
2874 * List: [expr, expr]
2875 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002876 case '[': ret = get_list_tv(arg, rettv, evaluate);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002877 break;
2878
2879 /*
2880 * Option value: &name
2881 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002882 case '&': ret = get_option_tv(arg, rettv, evaluate);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002883 break;
2884
2885 /*
2886 * Environment variable: $VAR.
2887 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002888 case '$': ret = get_env_tv(arg, rettv, evaluate);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002889 break;
2890
2891 /*
2892 * Register contents: @r.
2893 */
2894 case '@': ++*arg;
2895 if (evaluate)
2896 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002897 rettv->v_type = VAR_STRING;
2898 rettv->vval.v_string = get_reg_contents(**arg, FALSE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002899 }
2900 if (**arg != NUL)
2901 ++*arg;
2902 break;
2903
2904 /*
2905 * nested expression: (expression).
2906 */
2907 case '(': *arg = skipwhite(*arg + 1);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002908 ret = eval1(arg, rettv, evaluate); /* recursive! */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002909 if (**arg == ')')
2910 ++*arg;
2911 else if (ret == OK)
2912 {
2913 EMSG(_("E110: Missing ')'"));
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002914 clear_tv(rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002915 ret = FAIL;
2916 }
2917 break;
2918
2919 /*
2920 * Must be a variable or function name then.
2921 */
2922 default: s = *arg;
2923 len = get_func_len(arg, &alias, evaluate);
2924 if (alias != NULL)
2925 s = alias;
2926
2927 if (len == 0)
2928 ret = FAIL;
2929 else
2930 {
2931 if (**arg == '(') /* recursive! */
2932 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +00002933 /* If "s" is the name of a variable of type VAR_FUNC
2934 * use its contents. */
2935 s = deref_func_name(s, &len);
2936
2937 /* Invoke the function. */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002938 ret = get_func_tv(s, len, rettv, arg,
Bram Moolenaar071d4272004-06-13 20:20:40 +00002939 curwin->w_cursor.lnum, curwin->w_cursor.lnum,
2940 &len, evaluate);
2941 /* Stop the expression evaluation when immediately
2942 * aborting on error, or when an interrupt occurred or
2943 * an exception was thrown but not caught. */
2944 if (aborting())
2945 {
2946 if (ret == OK)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002947 clear_tv(rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002948 ret = FAIL;
2949 }
2950 }
2951 else if (evaluate)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002952 ret = get_var_tv(s, len, rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002953 }
2954
2955 if (alias != NULL)
2956 vim_free(alias);
2957
2958 break;
2959 }
2960 *arg = skipwhite(*arg);
2961
2962 /*
Bram Moolenaar49cd9572005-01-03 21:06:01 +00002963 * Handle expr[expr] and expr[expr:expr] subscript.
Bram Moolenaar071d4272004-06-13 20:20:40 +00002964 */
Bram Moolenaar49cd9572005-01-03 21:06:01 +00002965 while (**arg == '[' && ret == OK)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002966 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002967 if (eval_index(arg, rettv, evaluate) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002968 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002969 clear_tv(rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002970 return FAIL;
2971 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00002972 }
2973
2974 /*
2975 * Apply logical NOT and unary '-', from right to left, ignore '+'.
2976 */
2977 if (ret == OK && evaluate && end_leader > start_leader)
2978 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002979 val = get_tv_number(rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002980 while (end_leader > start_leader)
2981 {
2982 --end_leader;
2983 if (*end_leader == '!')
2984 val = !val;
2985 else if (*end_leader == '-')
2986 val = -val;
2987 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002988 clear_tv(rettv);
2989 rettv->v_type = VAR_NUMBER;
2990 rettv->vval.v_number = val;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002991 }
2992
2993 return ret;
2994}
2995
2996/*
Bram Moolenaar49cd9572005-01-03 21:06:01 +00002997 * Evaluate an "[expr]" or "[expr:expr]" index.
2998 * "*arg" points to the '['.
2999 * Returns FAIL or OK. "*arg" is advanced to after the ']'.
3000 */
3001 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003002eval_index(arg, rettv, evaluate)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00003003 char_u **arg;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003004 typeval *rettv;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00003005 int evaluate;
3006{
3007 int empty1 = FALSE, empty2 = FALSE;
3008 typeval var1, var2;
3009 long n1, n2 = 0;
3010 long len;
3011 int range;
3012 char_u *s;
3013
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003014 if (rettv->v_type == VAR_FUNC)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00003015 {
3016 EMSG(_("E999: Cannot index a Funcref"));
3017 return FAIL;
3018 }
3019
3020 /*
3021 * Get the (first) variable from inside the [].
3022 */
3023 *arg = skipwhite(*arg + 1);
3024 if (**arg == ':')
3025 empty1 = TRUE;
3026 else if (eval1(arg, &var1, evaluate) == FAIL) /* recursive! */
3027 return FAIL;
3028
3029 /*
3030 * Get the second variable from inside the [:].
3031 */
3032 if (**arg == ':')
3033 {
3034 range = TRUE;
3035 *arg = skipwhite(*arg + 1);
3036 if (**arg == ']')
3037 empty2 = TRUE;
3038 else if (eval1(arg, &var2, evaluate) == FAIL) /* recursive! */
3039 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003040 clear_tv(&var1);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00003041 return FAIL;
3042 }
3043 }
3044 else
3045 range = FALSE;
3046
3047 /* Check for the ']'. */
3048 if (**arg != ']')
3049 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003050 EMSG(_(e_missbrac));
3051 clear_tv(&var1);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00003052 if (range)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003053 clear_tv(&var2);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00003054 return FAIL;
3055 }
3056
3057 if (evaluate)
3058 {
3059 if (empty1)
3060 n1 = 0;
3061 else
3062 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003063 n1 = get_tv_number(&var1);
3064 clear_tv(&var1);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00003065 }
3066 if (range)
3067 {
3068 if (empty2)
3069 n2 = -1;
3070 else
3071 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003072 n2 = get_tv_number(&var2);
3073 clear_tv(&var2);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00003074 }
3075 }
3076
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003077 switch (rettv->v_type)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00003078 {
3079 case VAR_NUMBER:
3080 case VAR_STRING:
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003081 s = get_tv_string(rettv);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00003082 len = (long)STRLEN(s);
3083 if (range)
3084 {
3085 /* The resulting variable is a substring. If the indexes
3086 * are out of range the result is empty. */
3087 if (n1 < 0)
3088 {
3089 n1 = len + n1;
3090 if (n1 < 0)
3091 n1 = 0;
3092 }
3093 if (n2 < 0)
3094 n2 = len + n2;
3095 else if (n2 >= len)
3096 n2 = len;
3097 if (n1 >= len || n2 < 0 || n1 > n2)
3098 s = NULL;
3099 else
3100 s = vim_strnsave(s + n1, (int)(n2 - n1 + 1));
3101 }
3102 else
3103 {
3104 /* The resulting variable is a string of a single
3105 * character. If the index is too big or negative the
3106 * result is empty. */
3107 if (n1 >= len || n1 < 0)
3108 s = NULL;
3109 else
3110 s = vim_strnsave(s + n1, 1);
3111 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003112 clear_tv(rettv);
3113 rettv->v_type = VAR_STRING;
3114 rettv->vval.v_string = s;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00003115 break;
3116
3117 case VAR_LIST:
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003118 len = list_len(rettv->vval.v_list);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00003119 if (n1 < 0)
3120 n1 = len + n1;
3121 if (!empty1 && (n1 < 0 || n1 >= len))
3122 {
3123 EMSGN(_(e_listidx), n1);
3124 return FAIL;
3125 }
3126 if (range)
3127 {
3128 listvar *l;
3129 listitem *item;
3130
3131 if (n2 < 0)
3132 n2 = len + n2;
3133 if (!empty2 && (n2 < 0 || n2 >= len || n2 < n1))
3134 {
3135 EMSGN(_(e_listidx), n2);
3136 return FAIL;
3137 }
3138 l = list_alloc();
3139 if (l == NULL)
3140 return FAIL;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003141 for (item = list_find(rettv->vval.v_list, n1);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00003142 n1 <= n2; ++n1)
3143 {
3144 if (list_append_tv(l, &item->li_tv) == FAIL)
3145 {
3146 list_free(l);
3147 return FAIL;
3148 }
3149 item = item->li_next;
3150 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003151 clear_tv(rettv);
3152 rettv->v_type = VAR_LIST;
3153 rettv->vval.v_list = l;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00003154 }
3155 else
3156 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003157 copy_tv(&list_find(rettv->vval.v_list, n1)->li_tv,
Bram Moolenaar49cd9572005-01-03 21:06:01 +00003158 &var1);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003159 clear_tv(rettv);
3160 *rettv = var1;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00003161 }
3162 break;
3163 }
3164 }
3165
3166 *arg = skipwhite(*arg + 1); /* skip the ']' */
3167 return OK;
3168}
3169
3170/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00003171 * Get an option value.
3172 * "arg" points to the '&' or '+' before the option name.
3173 * "arg" is advanced to character after the option name.
3174 * Return OK or FAIL.
3175 */
3176 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003177get_option_tv(arg, rettv, evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003178 char_u **arg;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003179 typeval *rettv; /* when NULL, only check if option exists */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003180 int evaluate;
3181{
3182 char_u *option_end;
3183 long numval;
3184 char_u *stringval;
3185 int opt_type;
3186 int c;
3187 int working = (**arg == '+'); /* has("+option") */
3188 int ret = OK;
3189 int opt_flags;
3190
3191 /*
3192 * Isolate the option name and find its value.
3193 */
3194 option_end = find_option_end(arg, &opt_flags);
3195 if (option_end == NULL)
3196 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003197 if (rettv != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003198 EMSG2(_("E112: Option name missing: %s"), *arg);
3199 return FAIL;
3200 }
3201
3202 if (!evaluate)
3203 {
3204 *arg = option_end;
3205 return OK;
3206 }
3207
3208 c = *option_end;
3209 *option_end = NUL;
3210 opt_type = get_option_value(*arg, &numval,
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003211 rettv == NULL ? NULL : &stringval, opt_flags);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003212
3213 if (opt_type == -3) /* invalid name */
3214 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003215 if (rettv != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003216 EMSG2(_("E113: Unknown option: %s"), *arg);
3217 ret = FAIL;
3218 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003219 else if (rettv != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003220 {
3221 if (opt_type == -2) /* hidden string option */
3222 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003223 rettv->v_type = VAR_STRING;
3224 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003225 }
3226 else if (opt_type == -1) /* hidden number option */
3227 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003228 rettv->v_type = VAR_NUMBER;
3229 rettv->vval.v_number = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003230 }
3231 else if (opt_type == 1) /* number option */
3232 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003233 rettv->v_type = VAR_NUMBER;
3234 rettv->vval.v_number = numval;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003235 }
3236 else /* string option */
3237 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003238 rettv->v_type = VAR_STRING;
3239 rettv->vval.v_string = stringval;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003240 }
3241 }
3242 else if (working && (opt_type == -2 || opt_type == -1))
3243 ret = FAIL;
3244
3245 *option_end = c; /* put back for error messages */
3246 *arg = option_end;
3247
3248 return ret;
3249}
3250
3251/*
3252 * Allocate a variable for a string constant.
3253 * Return OK or FAIL.
3254 */
3255 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003256get_string_tv(arg, rettv, evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003257 char_u **arg;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003258 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003259 int evaluate;
3260{
3261 char_u *p;
3262 char_u *name;
3263 int i;
3264 int extra = 0;
3265
3266 /*
3267 * Find the end of the string, skipping backslashed characters.
3268 */
Bram Moolenaar1cd871b2004-12-19 22:46:22 +00003269 for (p = *arg + 1; *p && *p != '"'; mb_ptr_adv(p))
Bram Moolenaar071d4272004-06-13 20:20:40 +00003270 {
3271 if (*p == '\\' && p[1] != NUL)
3272 {
3273 ++p;
3274 /* A "\<x>" form occupies at least 4 characters, and produces up
3275 * to 6 characters: reserve space for 2 extra */
3276 if (*p == '<')
3277 extra += 2;
3278 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00003279 }
3280
3281 if (*p != '"')
3282 {
3283 EMSG2(_("E114: Missing quote: %s"), *arg);
3284 return FAIL;
3285 }
3286
3287 /* If only parsing, set *arg and return here */
3288 if (!evaluate)
3289 {
3290 *arg = p + 1;
3291 return OK;
3292 }
3293
3294 /*
3295 * Copy the string into allocated memory, handling backslashed
3296 * characters.
3297 */
3298 name = alloc((unsigned)(p - *arg + extra));
3299 if (name == NULL)
3300 return FAIL;
3301
3302 i = 0;
3303 for (p = *arg + 1; *p && *p != '"'; ++p)
3304 {
3305 if (*p == '\\')
3306 {
3307 switch (*++p)
3308 {
3309 case 'b': name[i++] = BS; break;
3310 case 'e': name[i++] = ESC; break;
3311 case 'f': name[i++] = FF; break;
3312 case 'n': name[i++] = NL; break;
3313 case 'r': name[i++] = CAR; break;
3314 case 't': name[i++] = TAB; break;
3315
3316 case 'X': /* hex: "\x1", "\x12" */
3317 case 'x':
3318 case 'u': /* Unicode: "\u0023" */
3319 case 'U':
3320 if (vim_isxdigit(p[1]))
3321 {
3322 int n, nr;
3323 int c = toupper(*p);
3324
3325 if (c == 'X')
3326 n = 2;
3327 else
3328 n = 4;
3329 nr = 0;
3330 while (--n >= 0 && vim_isxdigit(p[1]))
3331 {
3332 ++p;
3333 nr = (nr << 4) + hex2nr(*p);
3334 }
3335#ifdef FEAT_MBYTE
3336 /* For "\u" store the number according to
3337 * 'encoding'. */
3338 if (c != 'X')
3339 i += (*mb_char2bytes)(nr, name + i);
3340 else
3341#endif
3342 name[i++] = nr;
3343 }
3344 else
3345 name[i++] = *p;
3346 break;
3347
3348 /* octal: "\1", "\12", "\123" */
3349 case '0':
3350 case '1':
3351 case '2':
3352 case '3':
3353 case '4':
3354 case '5':
3355 case '6':
3356 case '7': name[i] = *p - '0';
3357 if (p[1] >= '0' && p[1] <= '7')
3358 {
3359 ++p;
3360 name[i] = (name[i] << 3) + *p - '0';
3361 if (p[1] >= '0' && p[1] <= '7')
3362 {
3363 ++p;
3364 name[i] = (name[i] << 3) + *p - '0';
3365 }
3366 }
3367 ++i;
3368 break;
3369
3370 /* Special key, e.g.: "\<C-W>" */
3371 case '<': extra = trans_special(&p, name + i, TRUE);
3372 if (extra != 0)
3373 {
3374 i += extra;
3375 --p;
3376 break;
3377 }
3378 /* FALLTHROUGH */
3379
3380 default: name[i++] = *p;
3381 break;
3382 }
3383 }
3384 else
3385 name[i++] = *p;
3386
3387#ifdef FEAT_MBYTE
3388 /* For a multi-byte character copy the bytes after the first one. */
3389 if (has_mbyte)
3390 {
3391 int l = (*mb_ptr2len_check)(p);
3392
3393 while (--l > 0)
3394 name[i++] = *++p;
3395 }
3396#endif
3397 }
3398 name[i] = NUL;
3399 *arg = p + 1;
3400
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003401 rettv->v_type = VAR_STRING;
3402 rettv->vval.v_string = name;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003403
3404 return OK;
3405}
3406
3407/*
3408 * Allocate a variable for an backtick-string constant.
3409 * Return OK or FAIL.
3410 */
3411 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003412get_lit_string_tv(arg, rettv, evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003413 char_u **arg;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003414 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003415 int evaluate;
3416{
3417 char_u *p;
3418 char_u *name;
3419
3420 /*
3421 * Find the end of the string.
3422 */
3423 p = vim_strchr(*arg + 1, '\'');
3424 if (p == NULL)
3425 {
3426 EMSG2(_("E115: Missing quote: %s"), *arg);
3427 return FAIL;
3428 }
3429
3430 if (evaluate)
3431 {
3432 /*
3433 * Copy the string into allocated memory.
3434 */
3435 name = vim_strnsave(*arg + 1, (int)(p - (*arg + 1)));
3436 if (name == NULL)
3437 return FAIL;
3438
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003439 rettv->v_type = VAR_STRING;
3440 rettv->vval.v_string = name;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003441 }
3442
3443 *arg = p + 1;
3444
3445 return OK;
3446}
3447
3448/*
Bram Moolenaar49cd9572005-01-03 21:06:01 +00003449 * Allocate a variable for a List and fill it from "*arg".
3450 * Return OK or FAIL.
3451 */
3452 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003453get_list_tv(arg, rettv, evaluate)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00003454 char_u **arg;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003455 typeval *rettv;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00003456 int evaluate;
3457{
3458 listvar *l = NULL;
3459 typeval tv;
3460 listitem *item;
3461
3462 if (evaluate)
3463 {
3464 l = list_alloc();
3465 if (l == NULL)
3466 return FAIL;
3467 }
3468
3469 *arg = skipwhite(*arg + 1);
3470 while (**arg != ']' && **arg != NUL)
3471 {
3472 if (eval1(arg, &tv, evaluate) == FAIL) /* recursive! */
3473 goto failret;
3474 if (evaluate)
3475 {
3476 item = listitem_alloc();
3477 if (item != NULL)
3478 {
3479 item->li_tv = tv;
3480 list_append(l, item);
3481 }
3482 }
3483
3484 if (**arg == ']')
3485 break;
3486 if (**arg != ',')
3487 {
3488 EMSG2(_("E999: Missing comma in list: %s"), *arg);
3489 goto failret;
3490 }
3491 *arg = skipwhite(*arg + 1);
3492 }
3493
3494 if (**arg != ']')
3495 {
3496 EMSG2(_("E999: Missing end of list ']': %s"), *arg);
3497failret:
3498 if (evaluate)
3499 list_free(l);
3500 return FAIL;
3501 }
3502
3503 *arg = skipwhite(*arg + 1);
3504 if (evaluate)
3505 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003506 rettv->v_type = VAR_LIST;
3507 rettv->vval.v_list = l;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00003508 ++l->lv_refcount;
3509 }
3510
3511 return OK;
3512}
3513
3514/*
3515 * Allocate an empty header for a list.
3516 */
3517 static listvar *
3518list_alloc()
3519{
3520 return (listvar *)alloc_clear(sizeof(listvar));
3521}
3522
3523/*
3524 * Unreference a list: decrement the reference count and free it when it
3525 * becomes zero.
3526 */
3527 static void
3528list_unref(l)
3529 listvar *l;
3530{
3531 if (l != NULL && --l->lv_refcount <= 0)
3532 list_free(l);
3533}
3534
3535/*
3536 * Free a list, including all items it points to.
3537 * Ignores the reference count.
3538 */
3539 static void
3540list_free(l)
3541 listvar *l;
3542{
3543 listitem *item;
3544 listitem *next;
3545
3546 for (item = l->lv_first; item != NULL; item = next)
3547 {
3548 next = item->li_next;
3549 listitem_free(item);
3550 }
3551 vim_free(l);
3552}
3553
3554/*
3555 * Allocate a list item.
3556 */
3557 static listitem *
3558listitem_alloc()
3559{
3560 return (listitem *)alloc(sizeof(listitem));
3561}
3562
3563/*
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00003564 * Free a list item. Also clears the value. Does not notify watchers.
Bram Moolenaar49cd9572005-01-03 21:06:01 +00003565 */
3566 static void
3567listitem_free(item)
3568 listitem *item;
3569{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003570 clear_tv(&item->li_tv);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00003571 vim_free(item);
3572}
3573
3574/*
3575 * Get the number of items in a list.
3576 */
3577 static long
3578list_len(l)
3579 listvar *l;
3580{
3581 listitem *item;
3582 long len = 0;
3583
3584 if (l == NULL)
3585 return 0L;
3586 for (item = l->lv_first; item != NULL; item = item->li_next)
3587 ++len;
3588 return len;
3589}
3590
3591/*
3592 * Locate item with index "n" in list "l" and return it.
3593 * A negative index is counted from the end; -1 is the last item.
3594 * Returns NULL when "n" is out of range.
3595 */
3596 static listitem *
3597list_find(l, n)
3598 listvar *l;
3599 long n;
3600{
3601 listitem *item;
3602 long idx;
3603
3604 if (l == NULL)
3605 return NULL;
3606 if (n < 0)
3607 {
3608 idx = -1; /* search from the end */
3609 for (item = l->lv_last; item != NULL && idx > n; item = item->li_prev)
3610 --idx;
3611 }
3612 else
3613 {
3614 idx = 0; /* search from the start */
3615 for (item = l->lv_first; item != NULL && idx < n; item = item->li_next)
3616 ++idx;
3617 }
3618 if (idx != n)
3619 return NULL;
3620 return item;
3621}
3622
3623/*
3624 * Append item "item" to the end of list "l".
3625 */
3626 static void
3627list_append(l, item)
3628 listvar *l;
3629 listitem *item;
3630{
3631 if (l->lv_last == NULL)
3632 {
3633 /* empty list */
3634 l->lv_first = item;
3635 l->lv_last = item;
3636 item->li_prev = NULL;
3637 }
3638 else
3639 {
3640 l->lv_last->li_next = item;
3641 item->li_prev = l->lv_last;
3642 l->lv_last = item;
3643 }
3644 item->li_next = NULL;
3645}
3646
3647/*
3648 * Append typeval "tv" to the end of list "l".
3649 */
3650 static int
3651list_append_tv(l, tv)
3652 listvar *l;
3653 typeval *tv;
3654{
3655 listitem *ni = listitem_alloc();
3656
3657 if (ni == NULL)
3658 return FAIL;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003659 copy_tv(tv, &ni->li_tv);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00003660 list_append(l, ni);
3661 return OK;
3662}
3663
3664/*
3665 * Make a copy of list "l". Shallow if "deep" is FALSE.
3666 * The refcount of the new list is set to 1.
3667 * Returns NULL when out of memory.
3668 */
3669 static listvar *
3670list_copy(orig, deep)
3671 listvar *orig;
3672 int deep;
3673{
3674 listvar *copy;
3675 listitem *item;
3676 listitem *ni;
3677 static int recurse = 0;
3678
3679 if (orig == NULL)
3680 return NULL;
3681 if (recurse >= VAR_LIST_MAXNEST)
3682 {
3683 EMSG(_("E999: List nested too deep for making a copy"));
3684 return NULL;
3685 }
3686 ++recurse;
3687
3688 copy = list_alloc();
3689 if (copy != NULL)
3690 {
3691 for (item = orig->lv_first; item != NULL; item = item->li_next)
3692 {
3693 ni = listitem_alloc();
3694 if (ni == NULL)
3695 break;
3696 if (deep && item->li_tv.v_type == VAR_LIST)
3697 {
3698 ni->li_tv.v_type = VAR_LIST;
3699 ni->li_tv.vval.v_list = list_copy(item->li_tv.vval.v_list,
3700 TRUE);
3701 if (ni->li_tv.vval.v_list == NULL)
3702 {
3703 vim_free(ni);
3704 break;
3705 }
3706 }
3707 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003708 copy_tv(&item->li_tv, &ni->li_tv);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00003709 list_append(copy, ni);
3710 }
3711 ++copy->lv_refcount;
3712 }
3713
3714 --recurse;
3715 return copy;
3716}
3717
3718/*
3719 * Remove item with index "n" from list "l" and return it.
3720 * Returns NULL when "n" is out of range.
3721 */
3722 static listitem *
3723list_getrem(l, n)
3724 listvar *l;
3725 long n;
3726{
3727 listitem *item;
3728
3729 item = list_find(l, n);
3730 if (item != NULL)
3731 {
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00003732 list_fix_watch(l, item); /* notify watchers */
Bram Moolenaar49cd9572005-01-03 21:06:01 +00003733 if (item->li_next == NULL)
3734 l->lv_last = item->li_prev;
3735 else
3736 item->li_next->li_prev = item->li_prev;
3737 if (item->li_prev == NULL)
3738 l->lv_first = item->li_next;
3739 else
3740 item->li_prev->li_next = item->li_next;
3741 }
3742 return item;
3743}
3744
3745/*
3746 * Return an allocated string with the string representation of a list.
3747 * May return NULL.
3748 */
3749 static char_u *
3750list2string(tv)
3751 typeval *tv;
3752{
3753 garray_T ga;
3754 listitem *item;
3755 int first = TRUE;
3756 char_u *tofree;
3757 char_u *s;
3758
3759 if (tv->vval.v_list == NULL)
3760 return NULL;
3761 ga_init2(&ga, (int)sizeof(char), 80);
3762 ga_append(&ga, '[');
3763
3764 for (item = tv->vval.v_list->lv_first; item != NULL; item = item->li_next)
3765 {
3766 if (first)
3767 first = FALSE;
3768 else
3769 ga_concat(&ga, (char_u *)", ");
3770
3771 s = tv2string(&item->li_tv, &tofree);
3772 if (s != NULL)
3773 ga_concat(&ga, s);
3774 vim_free(tofree);
3775 }
3776
3777 ga_append(&ga, ']');
3778 ga_append(&ga, NUL);
3779 return (char_u *)ga.ga_data;
3780}
3781
3782/*
3783 * Return a string with the string representation of a variable.
3784 * If the memory is allocated "tofree" is set to it, otherwise NULL.
3785 * Can only be used once before the value is used, it may call
3786 * get_var_string().
3787 * May return NULL;
3788 */
3789 static char_u *
3790tv2string(tv, tofree)
3791 typeval *tv;
3792 char_u **tofree;
3793{
3794 switch (tv->v_type)
3795 {
3796 case VAR_FUNC:
3797 *tofree = NULL;
3798 return tv->vval.v_string;
3799 case VAR_LIST:
3800 *tofree = list2string(tv);
3801 return *tofree;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003802 case VAR_STRING:
3803 case VAR_NUMBER:
Bram Moolenaar49cd9572005-01-03 21:06:01 +00003804 break;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003805 default:
3806 EMSG2(_(e_intern2), "tv2string()");
Bram Moolenaar49cd9572005-01-03 21:06:01 +00003807 }
3808 *tofree = NULL;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003809 return get_tv_string(tv);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00003810}
3811
3812/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00003813 * Get the value of an environment variable.
3814 * "arg" is pointing to the '$'. It is advanced to after the name.
3815 * If the environment variable was not set, silently assume it is empty.
3816 * Always return OK.
3817 */
3818 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003819get_env_tv(arg, rettv, evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003820 char_u **arg;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003821 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003822 int evaluate;
3823{
3824 char_u *string = NULL;
3825 int len;
3826 int cc;
3827 char_u *name;
3828
3829 ++*arg;
3830 name = *arg;
3831 len = get_env_len(arg);
3832 if (evaluate)
3833 {
3834 if (len != 0)
3835 {
3836 cc = name[len];
3837 name[len] = NUL;
3838 /* first try mch_getenv(), fast for normal environment vars */
3839 string = mch_getenv(name);
3840 if (string != NULL && *string != NUL)
3841 string = vim_strsave(string);
3842 else
3843 {
3844 /* next try expanding things like $VIM and ${HOME} */
3845 string = expand_env_save(name - 1);
3846 if (string != NULL && *string == '$')
3847 {
3848 vim_free(string);
3849 string = NULL;
3850 }
3851 }
3852 name[len] = cc;
3853 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003854 rettv->v_type = VAR_STRING;
3855 rettv->vval.v_string = string;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003856 }
3857
3858 return OK;
3859}
3860
3861/*
3862 * Array with names and number of arguments of all internal functions
3863 * MUST BE KEPT SORTED IN strcmp() ORDER FOR BINARY SEARCH!
3864 */
3865static struct fst
3866{
3867 char *f_name; /* function name */
3868 char f_min_argc; /* minimal number of arguments */
3869 char f_max_argc; /* maximal number of arguments */
Bram Moolenaar49cd9572005-01-03 21:06:01 +00003870 void (*f_func) __ARGS((typeval *args, typeval *rvar));
3871 /* implemenation of function */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003872} functions[] =
3873{
3874 {"append", 2, 2, f_append},
3875 {"argc", 0, 0, f_argc},
3876 {"argidx", 0, 0, f_argidx},
3877 {"argv", 1, 1, f_argv},
3878 {"browse", 4, 4, f_browse},
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00003879 {"browsedir", 2, 2, f_browsedir},
Bram Moolenaar071d4272004-06-13 20:20:40 +00003880 {"bufexists", 1, 1, f_bufexists},
3881 {"buffer_exists", 1, 1, f_bufexists}, /* obsolete */
3882 {"buffer_name", 1, 1, f_bufname}, /* obsolete */
3883 {"buffer_number", 1, 1, f_bufnr}, /* obsolete */
3884 {"buflisted", 1, 1, f_buflisted},
3885 {"bufloaded", 1, 1, f_bufloaded},
3886 {"bufname", 1, 1, f_bufname},
3887 {"bufnr", 1, 1, f_bufnr},
3888 {"bufwinnr", 1, 1, f_bufwinnr},
3889 {"byte2line", 1, 1, f_byte2line},
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00003890 {"byteidx", 2, 2, f_byteidx},
Bram Moolenaar071d4272004-06-13 20:20:40 +00003891 {"char2nr", 1, 1, f_char2nr},
3892 {"cindent", 1, 1, f_cindent},
3893 {"col", 1, 1, f_col},
3894 {"confirm", 1, 4, f_confirm},
Bram Moolenaar49cd9572005-01-03 21:06:01 +00003895 {"copy", 1, 1, f_copy},
Bram Moolenaar071d4272004-06-13 20:20:40 +00003896 {"cscope_connection",0,3, f_cscope_connection},
3897 {"cursor", 2, 2, f_cursor},
Bram Moolenaar49cd9572005-01-03 21:06:01 +00003898 {"deepcopy", 1, 1, f_deepcopy},
Bram Moolenaar071d4272004-06-13 20:20:40 +00003899 {"delete", 1, 1, f_delete},
3900 {"did_filetype", 0, 0, f_did_filetype},
Bram Moolenaar47136d72004-10-12 20:02:24 +00003901 {"diff_filler", 1, 1, f_diff_filler},
3902 {"diff_hlID", 2, 2, f_diff_hlID},
Bram Moolenaar071d4272004-06-13 20:20:40 +00003903 {"escape", 2, 2, f_escape},
3904 {"eventhandler", 0, 0, f_eventhandler},
3905 {"executable", 1, 1, f_executable},
3906 {"exists", 1, 1, f_exists},
3907 {"expand", 1, 2, f_expand},
3908 {"file_readable", 1, 1, f_filereadable}, /* obsolete */
3909 {"filereadable", 1, 1, f_filereadable},
3910 {"filewritable", 1, 1, f_filewritable},
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00003911 {"finddir", 1, 3, f_finddir},
3912 {"findfile", 1, 3, f_findfile},
Bram Moolenaar071d4272004-06-13 20:20:40 +00003913 {"fnamemodify", 2, 2, f_fnamemodify},
3914 {"foldclosed", 1, 1, f_foldclosed},
3915 {"foldclosedend", 1, 1, f_foldclosedend},
3916 {"foldlevel", 1, 1, f_foldlevel},
3917 {"foldtext", 0, 0, f_foldtext},
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00003918 {"foldtextresult", 1, 1, f_foldtextresult},
Bram Moolenaar071d4272004-06-13 20:20:40 +00003919 {"foreground", 0, 0, f_foreground},
Bram Moolenaar49cd9572005-01-03 21:06:01 +00003920 {"function", 1, 1, f_function},
Bram Moolenaar071d4272004-06-13 20:20:40 +00003921 {"getbufvar", 2, 2, f_getbufvar},
3922 {"getchar", 0, 1, f_getchar},
3923 {"getcharmod", 0, 0, f_getcharmod},
3924 {"getcmdline", 0, 0, f_getcmdline},
3925 {"getcmdpos", 0, 0, f_getcmdpos},
3926 {"getcwd", 0, 0, f_getcwd},
Bram Moolenaar46c9c732004-12-12 11:37:09 +00003927 {"getfontname", 0, 1, f_getfontname},
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00003928 {"getfperm", 1, 1, f_getfperm},
Bram Moolenaar071d4272004-06-13 20:20:40 +00003929 {"getfsize", 1, 1, f_getfsize},
3930 {"getftime", 1, 1, f_getftime},
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00003931 {"getftype", 1, 1, f_getftype},
Bram Moolenaar071d4272004-06-13 20:20:40 +00003932 {"getline", 1, 1, f_getline},
3933 {"getreg", 0, 1, f_getreg},
3934 {"getregtype", 0, 1, f_getregtype},
3935 {"getwinposx", 0, 0, f_getwinposx},
3936 {"getwinposy", 0, 0, f_getwinposy},
3937 {"getwinvar", 2, 2, f_getwinvar},
3938 {"glob", 1, 1, f_glob},
3939 {"globpath", 2, 2, f_globpath},
3940 {"has", 1, 1, f_has},
3941 {"hasmapto", 1, 2, f_hasmapto},
3942 {"highlightID", 1, 1, f_hlID}, /* obsolete */
3943 {"highlight_exists",1, 1, f_hlexists}, /* obsolete */
3944 {"histadd", 2, 2, f_histadd},
3945 {"histdel", 1, 2, f_histdel},
3946 {"histget", 1, 2, f_histget},
3947 {"histnr", 1, 1, f_histnr},
3948 {"hlID", 1, 1, f_hlID},
3949 {"hlexists", 1, 1, f_hlexists},
3950 {"hostname", 0, 0, f_hostname},
3951 {"iconv", 3, 3, f_iconv},
3952 {"indent", 1, 1, f_indent},
3953 {"input", 1, 2, f_input},
3954 {"inputdialog", 1, 3, f_inputdialog},
3955 {"inputrestore", 0, 0, f_inputrestore},
3956 {"inputsave", 0, 0, f_inputsave},
3957 {"inputsecret", 1, 2, f_inputsecret},
Bram Moolenaar49cd9572005-01-03 21:06:01 +00003958 {"insert", 2, 3, f_insert},
Bram Moolenaar071d4272004-06-13 20:20:40 +00003959 {"isdirectory", 1, 1, f_isdirectory},
3960 {"last_buffer_nr", 0, 0, f_last_buffer_nr},/* obsolete */
Bram Moolenaar49cd9572005-01-03 21:06:01 +00003961 {"len", 1, 1, f_len},
Bram Moolenaar071d4272004-06-13 20:20:40 +00003962 {"libcall", 3, 3, f_libcall},
3963 {"libcallnr", 3, 3, f_libcallnr},
3964 {"line", 1, 1, f_line},
3965 {"line2byte", 1, 1, f_line2byte},
3966 {"lispindent", 1, 1, f_lispindent},
3967 {"localtime", 0, 0, f_localtime},
3968 {"maparg", 1, 2, f_maparg},
3969 {"mapcheck", 1, 2, f_mapcheck},
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00003970 {"match", 2, 4, f_match},
3971 {"matchend", 2, 4, f_matchend},
3972 {"matchstr", 2, 4, f_matchstr},
Bram Moolenaar071d4272004-06-13 20:20:40 +00003973 {"mode", 0, 0, f_mode},
3974 {"nextnonblank", 1, 1, f_nextnonblank},
3975 {"nr2char", 1, 1, f_nr2char},
3976 {"prevnonblank", 1, 1, f_prevnonblank},
3977 {"remote_expr", 2, 3, f_remote_expr},
3978 {"remote_foreground", 1, 1, f_remote_foreground},
3979 {"remote_peek", 1, 2, f_remote_peek},
3980 {"remote_read", 1, 1, f_remote_read},
3981 {"remote_send", 2, 3, f_remote_send},
Bram Moolenaar49cd9572005-01-03 21:06:01 +00003982 {"remove", 2, 2, f_remove},
Bram Moolenaar071d4272004-06-13 20:20:40 +00003983 {"rename", 2, 2, f_rename},
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00003984 {"repeat", 2, 2, f_repeat},
Bram Moolenaar071d4272004-06-13 20:20:40 +00003985 {"resolve", 1, 1, f_resolve},
3986 {"search", 1, 2, f_search},
3987 {"searchpair", 3, 5, f_searchpair},
3988 {"server2client", 2, 2, f_server2client},
3989 {"serverlist", 0, 0, f_serverlist},
3990 {"setbufvar", 3, 3, f_setbufvar},
3991 {"setcmdpos", 1, 1, f_setcmdpos},
3992 {"setline", 2, 2, f_setline},
3993 {"setreg", 2, 3, f_setreg},
3994 {"setwinvar", 3, 3, f_setwinvar},
3995 {"simplify", 1, 1, f_simplify},
3996#ifdef HAVE_STRFTIME
3997 {"strftime", 1, 2, f_strftime},
3998#endif
3999 {"stridx", 2, 2, f_stridx},
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004000 {"string", 1, 1, f_string},
Bram Moolenaar071d4272004-06-13 20:20:40 +00004001 {"strlen", 1, 1, f_strlen},
4002 {"strpart", 2, 3, f_strpart},
4003 {"strridx", 2, 2, f_strridx},
4004 {"strtrans", 1, 1, f_strtrans},
4005 {"submatch", 1, 1, f_submatch},
4006 {"substitute", 4, 4, f_substitute},
4007 {"synID", 3, 3, f_synID},
4008 {"synIDattr", 2, 3, f_synIDattr},
4009 {"synIDtrans", 1, 1, f_synIDtrans},
Bram Moolenaarc0197e22004-09-13 20:26:32 +00004010 {"system", 1, 2, f_system},
Bram Moolenaar071d4272004-06-13 20:20:40 +00004011 {"tempname", 0, 0, f_tempname},
4012 {"tolower", 1, 1, f_tolower},
4013 {"toupper", 1, 1, f_toupper},
Bram Moolenaar8299df92004-07-10 09:47:34 +00004014 {"tr", 3, 3, f_tr},
Bram Moolenaar071d4272004-06-13 20:20:40 +00004015 {"type", 1, 1, f_type},
4016 {"virtcol", 1, 1, f_virtcol},
4017 {"visualmode", 0, 1, f_visualmode},
4018 {"winbufnr", 1, 1, f_winbufnr},
4019 {"wincol", 0, 0, f_wincol},
4020 {"winheight", 1, 1, f_winheight},
4021 {"winline", 0, 0, f_winline},
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00004022 {"winnr", 0, 1, f_winnr},
Bram Moolenaar071d4272004-06-13 20:20:40 +00004023 {"winrestcmd", 0, 0, f_winrestcmd},
4024 {"winwidth", 1, 1, f_winwidth},
4025};
4026
4027#if defined(FEAT_CMDL_COMPL) || defined(PROTO)
4028
4029/*
4030 * Function given to ExpandGeneric() to obtain the list of internal
4031 * or user defined function names.
4032 */
4033 char_u *
4034get_function_name(xp, idx)
4035 expand_T *xp;
4036 int idx;
4037{
4038 static int intidx = -1;
4039 char_u *name;
4040
4041 if (idx == 0)
4042 intidx = -1;
4043 if (intidx < 0)
4044 {
4045 name = get_user_func_name(xp, idx);
4046 if (name != NULL)
4047 return name;
4048 }
4049 if (++intidx < (int)(sizeof(functions) / sizeof(struct fst)))
4050 {
4051 STRCPY(IObuff, functions[intidx].f_name);
4052 STRCAT(IObuff, "(");
4053 if (functions[intidx].f_max_argc == 0)
4054 STRCAT(IObuff, ")");
4055 return IObuff;
4056 }
4057
4058 return NULL;
4059}
4060
4061/*
4062 * Function given to ExpandGeneric() to obtain the list of internal or
4063 * user defined variable or function names.
4064 */
4065/*ARGSUSED*/
4066 char_u *
4067get_expr_name(xp, idx)
4068 expand_T *xp;
4069 int idx;
4070{
4071 static int intidx = -1;
4072 char_u *name;
4073
4074 if (idx == 0)
4075 intidx = -1;
4076 if (intidx < 0)
4077 {
4078 name = get_function_name(xp, idx);
4079 if (name != NULL)
4080 return name;
4081 }
4082 return get_user_var_name(xp, ++intidx);
4083}
4084
4085#endif /* FEAT_CMDL_COMPL */
4086
4087/*
4088 * Find internal function in table above.
4089 * Return index, or -1 if not found
4090 */
4091 static int
4092find_internal_func(name)
4093 char_u *name; /* name of the function */
4094{
4095 int first = 0;
4096 int last = (int)(sizeof(functions) / sizeof(struct fst)) - 1;
4097 int cmp;
4098 int x;
4099
4100 /*
4101 * Find the function name in the table. Binary search.
4102 */
4103 while (first <= last)
4104 {
4105 x = first + ((unsigned)(last - first) >> 1);
4106 cmp = STRCMP(name, functions[x].f_name);
4107 if (cmp < 0)
4108 last = x - 1;
4109 else if (cmp > 0)
4110 first = x + 1;
4111 else
4112 return x;
4113 }
4114 return -1;
4115}
4116
4117/*
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004118 * Check if "name" is a variable of type VAR_FUNC. If so, return the function
4119 * name it contains, otherwise return "name".
4120 */
4121 static char_u *
4122deref_func_name(name, lenp)
4123 char_u *name;
4124 int *lenp;
4125{
4126 VAR v;
4127 int cc;
4128
4129 cc = name[*lenp];
4130 name[*lenp] = NUL;
4131 v = find_var(name, FALSE);
4132 name[*lenp] = cc;
4133 if (v != NULL && v->tv.v_type == VAR_FUNC)
4134 {
4135 if (v->tv.vval.v_string == NULL)
4136 {
4137 *lenp = 0;
4138 return (char_u *)""; /* just in case */
4139 }
4140 *lenp = STRLEN(v->tv.vval.v_string);
4141 return v->tv.vval.v_string;
4142 }
4143
4144 return name;
4145}
4146
4147/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00004148 * Allocate a variable for the result of a function.
4149 * Return OK or FAIL.
4150 */
4151 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004152get_func_tv(name, len, rettv, arg, firstline, lastline, doesrange, evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004153 char_u *name; /* name of the function */
4154 int len; /* length of "name" */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004155 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004156 char_u **arg; /* argument, pointing to the '(' */
4157 linenr_T firstline; /* first line of range */
4158 linenr_T lastline; /* last line of range */
4159 int *doesrange; /* return: function handled range */
4160 int evaluate;
4161{
4162 char_u *argp;
4163 int ret = OK;
4164#define MAX_FUNC_ARGS 20
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004165 typeval argvars[MAX_FUNC_ARGS]; /* vars for arguments */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004166 int argcount = 0; /* number of arguments found */
4167
4168 /*
4169 * Get the arguments.
4170 */
4171 argp = *arg;
4172 while (argcount < MAX_FUNC_ARGS)
4173 {
4174 argp = skipwhite(argp + 1); /* skip the '(' or ',' */
4175 if (*argp == ')' || *argp == ',' || *argp == NUL)
4176 break;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004177 if (eval1(&argp, &argvars[argcount], evaluate) == FAIL)
4178 {
4179 ret = FAIL;
4180 break;
4181 }
4182 ++argcount;
4183 if (*argp != ',')
4184 break;
4185 }
4186 if (*argp == ')')
4187 ++argp;
4188 else
4189 ret = FAIL;
4190
4191 if (ret == OK)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004192 ret = call_func(name, len, rettv, argcount, argvars,
Bram Moolenaar071d4272004-06-13 20:20:40 +00004193 firstline, lastline, doesrange, evaluate);
4194 else if (!aborting())
4195 EMSG2(_("E116: Invalid arguments for function %s"), name);
4196
4197 while (--argcount >= 0)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004198 clear_tv(&argvars[argcount]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004199
4200 *arg = skipwhite(argp);
4201 return ret;
4202}
4203
4204
4205/*
4206 * Call a function with its resolved parameters
4207 * Return OK or FAIL.
4208 */
4209 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004210call_func(name, len, rettv, argcount, argvars, firstline, lastline,
Bram Moolenaar071d4272004-06-13 20:20:40 +00004211 doesrange, evaluate)
4212 char_u *name; /* name of the function */
4213 int len; /* length of "name" */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004214 typeval *rettv; /* return value goes here */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004215 int argcount; /* number of "argvars" */
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004216 typeval *argvars; /* vars for arguments */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004217 linenr_T firstline; /* first line of range */
4218 linenr_T lastline; /* last line of range */
4219 int *doesrange; /* return: function handled range */
4220 int evaluate;
4221{
4222 int ret = FAIL;
4223 static char *errors[] =
4224 {N_("E117: Unknown function: %s"),
4225 N_("E118: Too many arguments for function: %s"),
4226 N_("E119: Not enough arguments for function: %s"),
4227 N_("E120: Using <SID> not in a script context: %s"),
4228 };
4229#define ERROR_UNKNOWN 0
4230#define ERROR_TOOMANY 1
4231#define ERROR_TOOFEW 2
4232#define ERROR_SCRIPT 3
4233#define ERROR_NONE 4
4234#define ERROR_OTHER 5
4235 int error = ERROR_NONE;
4236 int i;
4237 int llen;
4238 ufunc_T *fp;
4239 int cc;
4240#define FLEN_FIXED 40
4241 char_u fname_buf[FLEN_FIXED + 1];
4242 char_u *fname;
4243
4244 /*
4245 * In a script change <SID>name() and s:name() to K_SNR 123_name().
4246 * Change <SNR>123_name() to K_SNR 123_name().
4247 * Use fname_buf[] when it fits, otherwise allocate memory (slow).
4248 */
4249 cc = name[len];
4250 name[len] = NUL;
4251 llen = eval_fname_script(name);
4252 if (llen > 0)
4253 {
4254 fname_buf[0] = K_SPECIAL;
4255 fname_buf[1] = KS_EXTRA;
4256 fname_buf[2] = (int)KE_SNR;
4257 i = 3;
4258 if (eval_fname_sid(name)) /* "<SID>" or "s:" */
4259 {
4260 if (current_SID <= 0)
4261 error = ERROR_SCRIPT;
4262 else
4263 {
4264 sprintf((char *)fname_buf + 3, "%ld_", (long)current_SID);
4265 i = (int)STRLEN(fname_buf);
4266 }
4267 }
4268 if (i + STRLEN(name + llen) < FLEN_FIXED)
4269 {
4270 STRCPY(fname_buf + i, name + llen);
4271 fname = fname_buf;
4272 }
4273 else
4274 {
4275 fname = alloc((unsigned)(i + STRLEN(name + llen) + 1));
4276 if (fname == NULL)
4277 error = ERROR_OTHER;
4278 else
4279 {
4280 mch_memmove(fname, fname_buf, (size_t)i);
4281 STRCPY(fname + i, name + llen);
4282 }
4283 }
4284 }
4285 else
4286 fname = name;
4287
4288 *doesrange = FALSE;
4289
4290
4291 /* execute the function if no errors detected and executing */
4292 if (evaluate && error == ERROR_NONE)
4293 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004294 rettv->v_type = VAR_NUMBER; /* default is number rettv */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004295 error = ERROR_UNKNOWN;
4296
4297 if (!ASCII_ISLOWER(fname[0]))
4298 {
4299 /*
4300 * User defined function.
4301 */
4302 fp = find_func(fname);
4303#ifdef FEAT_AUTOCMD
4304 if (fp == NULL && apply_autocmds(EVENT_FUNCUNDEFINED,
4305 fname, fname, TRUE, NULL)
4306#ifdef FEAT_EVAL
4307 && !aborting()
4308#endif
4309 )
4310 {
4311 /* executed an autocommand, search for function again */
4312 fp = find_func(fname);
4313 }
4314#endif
4315 if (fp != NULL)
4316 {
4317 if (fp->flags & FC_RANGE)
4318 *doesrange = TRUE;
4319 if (argcount < fp->args.ga_len)
4320 error = ERROR_TOOFEW;
4321 else if (!fp->varargs && argcount > fp->args.ga_len)
4322 error = ERROR_TOOMANY;
4323 else
4324 {
4325 /*
4326 * Call the user function.
4327 * Save and restore search patterns, script variables and
4328 * redo buffer.
4329 */
4330 save_search_patterns();
4331 saveRedobuff();
4332 ++fp->calls;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004333 call_user_func(fp, argcount, argvars, rettv,
Bram Moolenaar071d4272004-06-13 20:20:40 +00004334 firstline, lastline);
4335 --fp->calls;
4336 restoreRedobuff();
4337 restore_search_patterns();
4338 error = ERROR_NONE;
4339 }
4340 }
4341 }
4342 else
4343 {
4344 /*
4345 * Find the function name in the table, call its implementation.
4346 */
4347 i = find_internal_func(fname);
4348 if (i >= 0)
4349 {
4350 if (argcount < functions[i].f_min_argc)
4351 error = ERROR_TOOFEW;
4352 else if (argcount > functions[i].f_max_argc)
4353 error = ERROR_TOOMANY;
4354 else
4355 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004356 argvars[argcount].v_type = VAR_UNKNOWN;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004357 functions[i].f_func(argvars, rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004358 error = ERROR_NONE;
4359 }
4360 }
4361 }
4362 /*
4363 * The function call (or "FuncUndefined" autocommand sequence) might
4364 * have been aborted by an error, an interrupt, or an explicitly thrown
4365 * exception that has not been caught so far. This situation can be
4366 * tested for by calling aborting(). For an error in an internal
4367 * function or for the "E132" error in call_user_func(), however, the
4368 * throw point at which the "force_abort" flag (temporarily reset by
4369 * emsg()) is normally updated has not been reached yet. We need to
4370 * update that flag first to make aborting() reliable.
4371 */
4372 update_force_abort();
4373 }
4374 if (error == ERROR_NONE)
4375 ret = OK;
4376
4377 /*
4378 * Report an error unless the argument evaluation or function call has been
4379 * cancelled due to an aborting error, an interrupt, or an exception.
4380 */
4381 if (error < ERROR_NONE && !aborting())
4382 EMSG2((char_u *)_(errors[error]), name);
4383
4384 name[len] = cc;
4385 if (fname != name && fname != fname_buf)
4386 vim_free(fname);
4387
4388 return ret;
4389}
4390
4391/*********************************************
4392 * Implementation of the built-in functions
4393 */
4394
4395/*
4396 * "append(lnum, string)" function
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004397 * or "append(list, item)" function
Bram Moolenaar071d4272004-06-13 20:20:40 +00004398 */
4399 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004400f_append(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004401 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004402 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004403{
4404 long lnum;
4405
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004406 rettv->vval.v_number = 1; /* Default: Failed */
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004407 if (argvars[0].v_type == VAR_LIST)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004408 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004409 if (argvars[0].vval.v_list != NULL
4410 && list_append_tv(argvars[0].vval.v_list, &argvars[1]) == OK)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004411 copy_tv(&argvars[0], rettv);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004412 }
4413 else
4414 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004415 lnum = get_tv_lnum(argvars);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004416 if (lnum >= 0
4417 && lnum <= curbuf->b_ml.ml_line_count
4418 && u_save(lnum, lnum + 1) == OK)
4419 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004420 ml_append(lnum, get_tv_string(&argvars[1]), (colnr_T)0, FALSE);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004421 if (curwin->w_cursor.lnum > lnum)
4422 ++curwin->w_cursor.lnum;
4423 appended_lines_mark(lnum, 1L);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004424 rettv->vval.v_number = 0;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004425 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004426 }
4427}
4428
4429/*
4430 * "argc()" function
4431 */
4432/* ARGSUSED */
4433 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004434f_argc(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004435 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004436 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004437{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004438 rettv->vval.v_number = ARGCOUNT;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004439}
4440
4441/*
4442 * "argidx()" function
4443 */
4444/* ARGSUSED */
4445 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004446f_argidx(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004447 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004448 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004449{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004450 rettv->vval.v_number = curwin->w_arg_idx;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004451}
4452
4453/*
4454 * "argv(nr)" function
4455 */
4456 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004457f_argv(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004458 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004459 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004460{
4461 int idx;
4462
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004463 idx = get_tv_number(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004464 if (idx >= 0 && idx < ARGCOUNT)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004465 rettv->vval.v_string = vim_strsave(alist_name(&ARGLIST[idx]));
Bram Moolenaar071d4272004-06-13 20:20:40 +00004466 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004467 rettv->vval.v_string = NULL;
4468 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004469}
4470
4471/*
4472 * "browse(save, title, initdir, default)" function
4473 */
4474/* ARGSUSED */
4475 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004476f_browse(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004477 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004478 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004479{
4480#ifdef FEAT_BROWSE
4481 int save;
4482 char_u *title;
4483 char_u *initdir;
4484 char_u *defname;
4485 char_u buf[NUMBUFLEN];
4486 char_u buf2[NUMBUFLEN];
4487
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004488 save = get_tv_number(&argvars[0]);
4489 title = get_tv_string(&argvars[1]);
4490 initdir = get_tv_string_buf(&argvars[2], buf);
4491 defname = get_tv_string_buf(&argvars[3], buf2);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004492
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004493 rettv->vval.v_string =
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00004494 do_browse(save ? BROWSE_SAVE : 0,
4495 title, defname, NULL, initdir, NULL, curbuf);
4496#else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004497 rettv->vval.v_string = NULL;
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00004498#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004499 rettv->v_type = VAR_STRING;
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00004500}
4501
4502/*
4503 * "browsedir(title, initdir)" function
4504 */
4505/* ARGSUSED */
4506 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004507f_browsedir(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004508 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004509 typeval *rettv;
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00004510{
4511#ifdef FEAT_BROWSE
4512 char_u *title;
4513 char_u *initdir;
4514 char_u buf[NUMBUFLEN];
4515
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004516 title = get_tv_string(&argvars[0]);
4517 initdir = get_tv_string_buf(&argvars[1], buf);
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00004518
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004519 rettv->vval.v_string = do_browse(BROWSE_DIR,
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00004520 title, NULL, NULL, initdir, NULL, curbuf);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004521#else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004522 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004523#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004524 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004525}
4526
4527/*
4528 * Find a buffer by number or exact name.
4529 */
4530 static buf_T *
4531find_buffer(avar)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004532 typeval *avar;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004533{
4534 buf_T *buf = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004535
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004536 if (avar->v_type == VAR_NUMBER)
4537 buf = buflist_findnr((int)avar->vval.v_number);
4538 else if (avar->vval.v_string != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004539 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004540 buf = buflist_findname_exp(avar->vval.v_string);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004541 if (buf == NULL)
4542 {
4543 /* No full path name match, try a match with a URL or a "nofile"
4544 * buffer, these don't use the full path. */
4545 for (buf = firstbuf; buf != NULL; buf = buf->b_next)
4546 if (buf->b_fname != NULL
4547 && (path_with_url(buf->b_fname)
4548#ifdef FEAT_QUICKFIX
4549 || bt_nofile(buf)
4550#endif
4551 )
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004552 && STRCMP(buf->b_fname, avar->vval.v_string) == 0)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004553 break;
4554 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004555 }
4556 return buf;
4557}
4558
4559/*
4560 * "bufexists(expr)" function
4561 */
4562 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004563f_bufexists(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004564 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004565 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004566{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004567 rettv->vval.v_number = (find_buffer(&argvars[0]) != NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004568}
4569
4570/*
4571 * "buflisted(expr)" function
4572 */
4573 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004574f_buflisted(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004575 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004576 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004577{
4578 buf_T *buf;
4579
4580 buf = find_buffer(&argvars[0]);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004581 rettv->vval.v_number = (buf != NULL && buf->b_p_bl);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004582}
4583
4584/*
4585 * "bufloaded(expr)" function
4586 */
4587 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004588f_bufloaded(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004589 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004590 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004591{
4592 buf_T *buf;
4593
4594 buf = find_buffer(&argvars[0]);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004595 rettv->vval.v_number = (buf != NULL && buf->b_ml.ml_mfp != NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004596}
4597
4598/*
4599 * Get buffer by number or pattern.
4600 */
4601 static buf_T *
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004602get_buf_tv(tv)
4603 typeval *tv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004604{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004605 char_u *name = tv->vval.v_string;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004606 int save_magic;
4607 char_u *save_cpo;
4608 buf_T *buf;
4609
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004610 if (tv->v_type == VAR_NUMBER)
4611 return buflist_findnr((int)tv->vval.v_number);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004612 if (name == NULL || *name == NUL)
4613 return curbuf;
4614 if (name[0] == '$' && name[1] == NUL)
4615 return lastbuf;
4616
4617 /* Ignore 'magic' and 'cpoptions' here to make scripts portable */
4618 save_magic = p_magic;
4619 p_magic = TRUE;
4620 save_cpo = p_cpo;
4621 p_cpo = (char_u *)"";
4622
4623 buf = buflist_findnr(buflist_findpat(name, name + STRLEN(name),
4624 TRUE, FALSE));
4625
4626 p_magic = save_magic;
4627 p_cpo = save_cpo;
4628
4629 /* If not found, try expanding the name, like done for bufexists(). */
4630 if (buf == NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004631 buf = find_buffer(tv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004632
4633 return buf;
4634}
4635
4636/*
4637 * "bufname(expr)" function
4638 */
4639 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004640f_bufname(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004641 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004642 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004643{
4644 buf_T *buf;
4645
4646 ++emsg_off;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004647 buf = get_buf_tv(&argvars[0]);
4648 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004649 if (buf != NULL && buf->b_fname != NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004650 rettv->vval.v_string = vim_strsave(buf->b_fname);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004651 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004652 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004653 --emsg_off;
4654}
4655
4656/*
4657 * "bufnr(expr)" function
4658 */
4659 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004660f_bufnr(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004661 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004662 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004663{
4664 buf_T *buf;
4665
4666 ++emsg_off;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004667 buf = get_buf_tv(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004668 if (buf != NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004669 rettv->vval.v_number = buf->b_fnum;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004670 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004671 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004672 --emsg_off;
4673}
4674
4675/*
4676 * "bufwinnr(nr)" function
4677 */
4678 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004679f_bufwinnr(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004680 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004681 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004682{
4683#ifdef FEAT_WINDOWS
4684 win_T *wp;
4685 int winnr = 0;
4686#endif
4687 buf_T *buf;
4688
4689 ++emsg_off;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004690 buf = get_buf_tv(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004691#ifdef FEAT_WINDOWS
4692 for (wp = firstwin; wp; wp = wp->w_next)
4693 {
4694 ++winnr;
4695 if (wp->w_buffer == buf)
4696 break;
4697 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004698 rettv->vval.v_number = (wp != NULL ? winnr : -1);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004699#else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004700 rettv->vval.v_number = (curwin->w_buffer == buf ? 1 : -1);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004701#endif
4702 --emsg_off;
4703}
4704
4705/*
4706 * "byte2line(byte)" function
4707 */
4708/*ARGSUSED*/
4709 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004710f_byte2line(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004711 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004712 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004713{
4714#ifndef FEAT_BYTEOFF
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004715 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004716#else
4717 long boff = 0;
4718
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004719 boff = get_tv_number(&argvars[0]) - 1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004720 if (boff < 0)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004721 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004722 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004723 rettv->vval.v_number = ml_find_line_or_offset(curbuf,
Bram Moolenaar071d4272004-06-13 20:20:40 +00004724 (linenr_T)0, &boff);
4725#endif
4726}
4727
4728/*
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00004729 * "byteidx()" function
4730 */
4731/*ARGSUSED*/
4732 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004733f_byteidx(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004734 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004735 typeval *rettv;
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00004736{
4737#ifdef FEAT_MBYTE
4738 char_u *t;
4739#endif
4740 char_u *str;
4741 long idx;
4742
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004743 str = get_tv_string(&argvars[0]);
4744 idx = get_tv_number(&argvars[1]);
4745 rettv->vval.v_number = -1;
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00004746 if (idx < 0)
4747 return;
4748
4749#ifdef FEAT_MBYTE
4750 t = str;
4751 for ( ; idx > 0; idx--)
4752 {
4753 if (*t == NUL) /* EOL reached */
4754 return;
4755 t += mb_ptr2len_check(t);
4756 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004757 rettv->vval.v_number = t - str;
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00004758#else
4759 if (idx <= STRLEN(str))
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004760 rettv->vval.v_number = idx;
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00004761#endif
4762}
4763
4764/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00004765 * "char2nr(string)" function
4766 */
4767 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004768f_char2nr(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004769 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004770 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004771{
4772#ifdef FEAT_MBYTE
4773 if (has_mbyte)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004774 rettv->vval.v_number =
4775 (*mb_ptr2char)(get_tv_string(&argvars[0]));
Bram Moolenaar071d4272004-06-13 20:20:40 +00004776 else
4777#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004778 rettv->vval.v_number = get_tv_string(&argvars[0])[0];
Bram Moolenaar071d4272004-06-13 20:20:40 +00004779}
4780
4781/*
4782 * "cindent(lnum)" function
4783 */
4784 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004785f_cindent(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004786 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004787 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004788{
4789#ifdef FEAT_CINDENT
4790 pos_T pos;
4791 linenr_T lnum;
4792
4793 pos = curwin->w_cursor;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004794 lnum = get_tv_lnum(argvars);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004795 if (lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count)
4796 {
4797 curwin->w_cursor.lnum = lnum;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004798 rettv->vval.v_number = get_c_indent();
Bram Moolenaar071d4272004-06-13 20:20:40 +00004799 curwin->w_cursor = pos;
4800 }
4801 else
4802#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004803 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004804}
4805
4806/*
4807 * "col(string)" function
4808 */
4809 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004810f_col(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004811 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004812 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004813{
4814 colnr_T col = 0;
4815 pos_T *fp;
4816
4817 fp = var2fpos(&argvars[0], FALSE);
4818 if (fp != NULL)
4819 {
4820 if (fp->col == MAXCOL)
4821 {
4822 /* '> can be MAXCOL, get the length of the line then */
4823 if (fp->lnum <= curbuf->b_ml.ml_line_count)
4824 col = STRLEN(ml_get(fp->lnum)) + 1;
4825 else
4826 col = MAXCOL;
4827 }
4828 else
4829 {
4830 col = fp->col + 1;
4831#ifdef FEAT_VIRTUALEDIT
4832 /* col(".") when the cursor is on the NUL at the end of the line
4833 * because of "coladd" can be seen as an extra column. */
4834 if (virtual_active() && fp == &curwin->w_cursor)
4835 {
4836 char_u *p = ml_get_cursor();
4837
4838 if (curwin->w_cursor.coladd >= (colnr_T)chartabsize(p,
4839 curwin->w_virtcol - curwin->w_cursor.coladd))
4840 {
4841# ifdef FEAT_MBYTE
4842 int l;
4843
4844 if (*p != NUL && p[(l = (*mb_ptr2len_check)(p))] == NUL)
4845 col += l;
4846# else
4847 if (*p != NUL && p[1] == NUL)
4848 ++col;
4849# endif
4850 }
4851 }
4852#endif
4853 }
4854 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004855 rettv->vval.v_number = col;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004856}
4857
4858/*
4859 * "confirm(message, buttons[, default [, type]])" function
4860 */
4861/*ARGSUSED*/
4862 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004863f_confirm(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004864 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004865 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004866{
4867#if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
4868 char_u *message;
4869 char_u *buttons = NULL;
4870 char_u buf[NUMBUFLEN];
4871 char_u buf2[NUMBUFLEN];
4872 int def = 1;
4873 int type = VIM_GENERIC;
4874 int c;
4875
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004876 message = get_tv_string(&argvars[0]);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004877 if (argvars[1].v_type != VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004878 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004879 buttons = get_tv_string_buf(&argvars[1], buf);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004880 if (argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004881 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004882 def = get_tv_number(&argvars[2]);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004883 if (argvars[3].v_type != VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004884 {
4885 /* avoid that TOUPPER_ASC calls get_var_string_buf() twice */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004886 c = *get_tv_string_buf(&argvars[3], buf2);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004887 switch (TOUPPER_ASC(c))
4888 {
4889 case 'E': type = VIM_ERROR; break;
4890 case 'Q': type = VIM_QUESTION; break;
4891 case 'I': type = VIM_INFO; break;
4892 case 'W': type = VIM_WARNING; break;
4893 case 'G': type = VIM_GENERIC; break;
4894 }
4895 }
4896 }
4897 }
4898
4899 if (buttons == NULL || *buttons == NUL)
4900 buttons = (char_u *)_("&Ok");
4901
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004902 rettv->vval.v_number = do_dialog(type, NULL, message, buttons,
Bram Moolenaar071d4272004-06-13 20:20:40 +00004903 def, NULL);
4904#else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004905 rettv->vval.v_number = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004906#endif
4907}
4908
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004909/*
4910 * "copy()" function
4911 */
4912 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004913f_copy(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004914 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004915 typeval *rettv;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004916{
4917 if (argvars[0].v_type == VAR_LIST)
4918 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004919 rettv->v_type = VAR_LIST;
4920 rettv->vval.v_list = list_copy(argvars[0].vval.v_list, FALSE);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004921 }
4922 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004923 copy_tv(&argvars[0], rettv);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004924}
Bram Moolenaar071d4272004-06-13 20:20:40 +00004925
4926/*
4927 * "cscope_connection([{num} , {dbpath} [, {prepend}]])" function
4928 *
4929 * Checks the existence of a cscope connection.
4930 */
4931/*ARGSUSED*/
4932 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004933f_cscope_connection(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004934 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004935 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004936{
4937#ifdef FEAT_CSCOPE
4938 int num = 0;
4939 char_u *dbpath = NULL;
4940 char_u *prepend = NULL;
4941 char_u buf[NUMBUFLEN];
4942
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004943 if (argvars[0].v_type != VAR_UNKNOWN
4944 && argvars[1].v_type != VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004945 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004946 num = (int)get_tv_number(&argvars[0]);
4947 dbpath = get_tv_string(&argvars[1]);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004948 if (argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004949 prepend = get_tv_string_buf(&argvars[2], buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004950 }
4951
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004952 rettv->vval.v_number = cs_connection(num, dbpath, prepend);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004953#else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004954 rettv->vval.v_number = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004955#endif
4956}
4957
4958/*
4959 * "cursor(lnum, col)" function
4960 *
4961 * Moves the cursor to the specified line and column
4962 */
4963/*ARGSUSED*/
4964 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004965f_cursor(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004966 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004967 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004968{
4969 long line, col;
4970
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004971 line = get_tv_lnum(argvars);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004972 if (line > 0)
4973 curwin->w_cursor.lnum = line;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004974 col = get_tv_number(&argvars[1]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004975 if (col > 0)
4976 curwin->w_cursor.col = col - 1;
4977#ifdef FEAT_VIRTUALEDIT
4978 curwin->w_cursor.coladd = 0;
4979#endif
4980
4981 /* Make sure the cursor is in a valid position. */
4982 check_cursor();
4983#ifdef FEAT_MBYTE
4984 /* Correct cursor for multi-byte character. */
4985 if (has_mbyte)
4986 mb_adjust_cursor();
4987#endif
Bram Moolenaarf4b8e572004-06-24 15:53:16 +00004988
4989 curwin->w_set_curswant = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004990}
4991
4992/*
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004993 * "deepcopy()" function
Bram Moolenaar071d4272004-06-13 20:20:40 +00004994 */
4995 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004996f_deepcopy(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004997 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004998 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004999{
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005000 if (argvars[0].v_type == VAR_LIST)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005001 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005002 rettv->v_type = VAR_LIST;
5003 rettv->vval.v_list = list_copy(argvars[0].vval.v_list, TRUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005004 }
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005005 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005006 copy_tv(&argvars[0], rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005007}
5008
5009/*
5010 * "delete()" function
5011 */
5012 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005013f_delete(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005014 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005015 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005016{
5017 if (check_restricted() || check_secure())
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005018 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005019 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005020 rettv->vval.v_number = mch_remove(get_tv_string(&argvars[0]));
Bram Moolenaar071d4272004-06-13 20:20:40 +00005021}
5022
5023/*
5024 * "did_filetype()" function
5025 */
5026/*ARGSUSED*/
5027 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005028f_did_filetype(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005029 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005030 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005031{
5032#ifdef FEAT_AUTOCMD
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005033 rettv->vval.v_number = did_filetype;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005034#else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005035 rettv->vval.v_number = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005036#endif
5037}
5038
5039/*
Bram Moolenaar47136d72004-10-12 20:02:24 +00005040 * "diff_filler()" function
5041 */
5042/*ARGSUSED*/
5043 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005044f_diff_filler(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005045 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005046 typeval *rettv;
Bram Moolenaar47136d72004-10-12 20:02:24 +00005047{
5048#ifdef FEAT_DIFF
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005049 rettv->vval.v_number = diff_check_fill(curwin, get_tv_lnum(argvars));
Bram Moolenaar47136d72004-10-12 20:02:24 +00005050#endif
5051}
5052
5053/*
5054 * "diff_hlID()" function
5055 */
5056/*ARGSUSED*/
5057 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005058f_diff_hlID(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005059 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005060 typeval *rettv;
Bram Moolenaar47136d72004-10-12 20:02:24 +00005061{
5062#ifdef FEAT_DIFF
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005063 linenr_T lnum = get_tv_lnum(argvars);
Bram Moolenaar47136d72004-10-12 20:02:24 +00005064 static linenr_T prev_lnum = 0;
5065 static int changedtick = 0;
5066 static int fnum = 0;
5067 static int change_start = 0;
5068 static int change_end = 0;
5069 static enum hlf_value hlID = 0;
5070 int filler_lines;
5071 int col;
5072
5073 if (lnum != prev_lnum
5074 || changedtick != curbuf->b_changedtick
5075 || fnum != curbuf->b_fnum)
5076 {
5077 /* New line, buffer, change: need to get the values. */
5078 filler_lines = diff_check(curwin, lnum);
5079 if (filler_lines < 0)
5080 {
5081 if (filler_lines == -1)
5082 {
5083 change_start = MAXCOL;
5084 change_end = -1;
5085 if (diff_find_change(curwin, lnum, &change_start, &change_end))
5086 hlID = HLF_ADD; /* added line */
5087 else
5088 hlID = HLF_CHD; /* changed line */
5089 }
5090 else
5091 hlID = HLF_ADD; /* added line */
5092 }
5093 else
5094 hlID = (enum hlf_value)0;
5095 prev_lnum = lnum;
5096 changedtick = curbuf->b_changedtick;
5097 fnum = curbuf->b_fnum;
5098 }
5099
5100 if (hlID == HLF_CHD || hlID == HLF_TXD)
5101 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005102 col = get_tv_number(&argvars[1]) - 1;
Bram Moolenaar47136d72004-10-12 20:02:24 +00005103 if (col >= change_start && col <= change_end)
5104 hlID = HLF_TXD; /* changed text */
5105 else
5106 hlID = HLF_CHD; /* changed line */
5107 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005108 rettv->vval.v_number = hlID == (enum hlf_value)0 ? 0 : (int)hlID;
Bram Moolenaar47136d72004-10-12 20:02:24 +00005109#endif
5110}
5111
5112/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00005113 * "escape({string}, {chars})" function
5114 */
5115 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005116f_escape(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005117 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005118 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005119{
5120 char_u buf[NUMBUFLEN];
5121
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005122 rettv->vval.v_string =
5123 vim_strsave_escaped(get_tv_string(&argvars[0]),
5124 get_tv_string_buf(&argvars[1], buf));
5125 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005126}
5127
5128/*
5129 * "eventhandler()" function
5130 */
5131/*ARGSUSED*/
5132 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005133f_eventhandler(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005134 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005135 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005136{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005137 rettv->vval.v_number = vgetc_busy;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005138}
5139
5140/*
5141 * "executable()" function
5142 */
5143 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005144f_executable(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005145 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005146 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005147{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005148 rettv->vval.v_number = mch_can_exe(get_tv_string(&argvars[0]));
Bram Moolenaar071d4272004-06-13 20:20:40 +00005149}
5150
5151/*
5152 * "exists()" function
5153 */
5154 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005155f_exists(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005156 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005157 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005158{
5159 char_u *p;
5160 char_u *name;
5161 int n = FALSE;
5162 int len = 0;
5163
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005164 p = get_tv_string(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005165 if (*p == '$') /* environment variable */
5166 {
5167 /* first try "normal" environment variables (fast) */
5168 if (mch_getenv(p + 1) != NULL)
5169 n = TRUE;
5170 else
5171 {
5172 /* try expanding things like $VIM and ${HOME} */
5173 p = expand_env_save(p);
5174 if (p != NULL && *p != '$')
5175 n = TRUE;
5176 vim_free(p);
5177 }
5178 }
5179 else if (*p == '&' || *p == '+') /* option */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005180 n = (get_option_tv(&p, NULL, TRUE) == OK);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005181 else if (*p == '*') /* internal or user defined function */
5182 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005183 n = function_exists(p + 1);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005184 }
5185 else if (*p == ':')
5186 {
5187 n = cmd_exists(p + 1);
5188 }
5189 else if (*p == '#')
5190 {
5191#ifdef FEAT_AUTOCMD
5192 name = p + 1;
5193 p = vim_strchr(name, '#');
5194 if (p != NULL)
5195 n = au_exists(name, p, p + 1);
5196 else
5197 n = au_exists(name, name + STRLEN(name), NULL);
5198#endif
5199 }
5200 else /* internal variable */
5201 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00005202 char_u *expr_start;
5203 char_u *expr_end;
5204 char_u *temp_string = NULL;
5205 char_u *s;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005206 name = p;
5207
Bram Moolenaar071d4272004-06-13 20:20:40 +00005208 /* Find the end of the name. */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005209 s = find_name_end(name, &expr_start, &expr_end, FALSE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005210 if (expr_start != NULL)
5211 {
5212 temp_string = make_expanded_name(name, expr_start, expr_end, s);
5213 if (temp_string != NULL)
5214 {
5215 len = STRLEN(temp_string);
5216 name = temp_string;
5217 }
5218 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00005219 if (len == 0)
5220 len = get_id_len(&p);
5221 if (len != 0)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005222 n = (get_var_tv(name, len, NULL) == OK);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005223
Bram Moolenaar071d4272004-06-13 20:20:40 +00005224 vim_free(temp_string);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005225 }
5226
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005227 rettv->vval.v_number = n;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005228}
5229
5230/*
5231 * "expand()" function
5232 */
5233 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005234f_expand(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005235 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005236 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005237{
5238 char_u *s;
5239 int len;
5240 char_u *errormsg;
5241 int flags = WILD_SILENT|WILD_USE_NL|WILD_LIST_NOTFOUND;
5242 expand_T xpc;
5243
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005244 rettv->v_type = VAR_STRING;
5245 s = get_tv_string(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005246 if (*s == '%' || *s == '#' || *s == '<')
5247 {
5248 ++emsg_off;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005249 rettv->vval.v_string = eval_vars(s, &len, NULL, &errormsg, s);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005250 --emsg_off;
5251 }
5252 else
5253 {
5254 /* When the optional second argument is non-zero, don't remove matches
5255 * for 'suffixes' and 'wildignore' */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005256 if (argvars[1].v_type != VAR_UNKNOWN && get_tv_number(&argvars[1]))
Bram Moolenaar071d4272004-06-13 20:20:40 +00005257 flags |= WILD_KEEP_ALL;
5258 ExpandInit(&xpc);
5259 xpc.xp_context = EXPAND_FILES;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005260 rettv->vval.v_string = ExpandOne(&xpc, s, NULL, flags, WILD_ALL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005261 ExpandCleanup(&xpc);
5262 }
5263}
5264
5265/*
5266 * "filereadable()" function
5267 */
5268 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005269f_filereadable(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005270 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005271 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005272{
5273 FILE *fd;
5274 char_u *p;
5275 int n;
5276
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005277 p = get_tv_string(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005278 if (*p && !mch_isdir(p) && (fd = mch_fopen((char *)p, "r")) != NULL)
5279 {
5280 n = TRUE;
5281 fclose(fd);
5282 }
5283 else
5284 n = FALSE;
5285
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005286 rettv->vval.v_number = n;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005287}
5288
5289/*
5290 * return 0 for not writable, 1 for writable file, 2 for a dir which we have
5291 * rights to write into.
5292 */
5293 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005294f_filewritable(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005295 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005296 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005297{
5298 char_u *p;
5299 int retval = 0;
5300#if defined(UNIX) || defined(VMS)
5301 int perm = 0;
5302#endif
5303
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005304 p = get_tv_string(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005305#if defined(UNIX) || defined(VMS)
5306 perm = mch_getperm(p);
5307#endif
5308#ifndef MACOS_CLASSIC /* TODO: get either mch_writable or mch_access */
5309 if (
5310# ifdef WIN3264
5311 mch_writable(p) &&
5312# else
5313# if defined(UNIX) || defined(VMS)
5314 (perm & 0222) &&
5315# endif
5316# endif
5317 mch_access((char *)p, W_OK) == 0
5318 )
5319#endif
5320 {
5321 ++retval;
5322 if (mch_isdir(p))
5323 ++retval;
5324 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005325 rettv->vval.v_number = retval;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005326}
5327
5328/*
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00005329 * "finddir({fname}[, {path}[, {count}]])" function
5330 */
5331 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005332f_finddir(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005333 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005334 typeval *rettv;
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00005335{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005336 f_findfilendir(argvars, rettv, TRUE);
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00005337}
5338
5339/*
5340 * "findfile({fname}[, {path}[, {count}]])" function
5341 */
5342 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005343f_findfile(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005344 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005345 typeval *rettv;
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00005346{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005347 f_findfilendir(argvars, rettv, FALSE);
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00005348}
5349
5350 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005351f_findfilendir(argvars, rettv, dir)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005352 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005353 typeval *rettv;
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00005354 int dir;
5355{
5356#ifdef FEAT_SEARCHPATH
5357 char_u *fname;
5358 char_u *fresult = NULL;
5359 char_u *path = *curbuf->b_p_path == NUL ? p_path : curbuf->b_p_path;
5360 char_u *p;
5361 char_u pathbuf[NUMBUFLEN];
5362 int count = 1;
5363 int first = TRUE;
5364
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005365 fname = get_tv_string(&argvars[0]);
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00005366
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005367 if (argvars[1].v_type != VAR_UNKNOWN)
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00005368 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005369 p = get_tv_string_buf(&argvars[1], pathbuf);
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00005370 if (*p != NUL)
5371 path = p;
5372
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005373 if (argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005374 count = get_tv_number(&argvars[2]);
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00005375 }
5376
5377 do
5378 {
5379 vim_free(fresult);
5380 fresult = find_file_in_path_option(first ? fname : NULL,
5381 first ? (int)STRLEN(fname) : 0,
5382 0, first, path, dir, NULL);
5383 first = FALSE;
5384 } while (--count > 0 && fresult != NULL);
5385
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005386 rettv->vval.v_string = fresult;
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00005387#else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005388 rettv->vval.v_string = NULL;
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00005389#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005390 rettv->v_type = VAR_STRING;
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00005391}
5392
5393/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00005394 * "fnamemodify({fname}, {mods})" function
5395 */
5396 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005397f_fnamemodify(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005398 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005399 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005400{
5401 char_u *fname;
5402 char_u *mods;
5403 int usedlen = 0;
5404 int len;
5405 char_u *fbuf = NULL;
5406 char_u buf[NUMBUFLEN];
5407
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005408 fname = get_tv_string(&argvars[0]);
5409 mods = get_tv_string_buf(&argvars[1], buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005410 len = (int)STRLEN(fname);
5411
5412 (void)modify_fname(mods, &usedlen, &fname, &fbuf, &len);
5413
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005414 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005415 if (fname == NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005416 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005417 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005418 rettv->vval.v_string = vim_strnsave(fname, len);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005419 vim_free(fbuf);
5420}
5421
5422/*
5423 * "foldclosed()" function
5424 */
5425 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005426f_foldclosed(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005427 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005428 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005429{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005430 foldclosed_both(argvars, rettv, FALSE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005431}
5432
5433/*
5434 * "foldclosedend()" function
5435 */
5436 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005437f_foldclosedend(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005438 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005439 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005440{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005441 foldclosed_both(argvars, rettv, TRUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005442}
5443
5444/*
5445 * "foldclosed()" function
5446 */
5447 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005448foldclosed_both(argvars, rettv, end)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005449 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005450 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005451 int end;
5452{
5453#ifdef FEAT_FOLDING
5454 linenr_T lnum;
5455 linenr_T first, last;
5456
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005457 lnum = get_tv_lnum(argvars);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005458 if (lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count)
5459 {
5460 if (hasFoldingWin(curwin, lnum, &first, &last, FALSE, NULL))
5461 {
5462 if (end)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005463 rettv->vval.v_number = (varnumber_T)last;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005464 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005465 rettv->vval.v_number = (varnumber_T)first;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005466 return;
5467 }
5468 }
5469#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005470 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005471}
5472
5473/*
5474 * "foldlevel()" function
5475 */
5476 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005477f_foldlevel(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005478 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005479 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005480{
5481#ifdef FEAT_FOLDING
5482 linenr_T lnum;
5483
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005484 lnum = get_tv_lnum(argvars);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005485 if (lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005486 rettv->vval.v_number = foldLevel(lnum);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005487 else
5488#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005489 rettv->vval.v_number = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005490}
5491
5492/*
5493 * "foldtext()" function
5494 */
5495/*ARGSUSED*/
5496 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005497f_foldtext(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005498 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005499 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005500{
5501#ifdef FEAT_FOLDING
5502 linenr_T lnum;
5503 char_u *s;
5504 char_u *r;
5505 int len;
5506 char *txt;
5507#endif
5508
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005509 rettv->v_type = VAR_STRING;
5510 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005511#ifdef FEAT_FOLDING
5512 if ((linenr_T)vimvars[VV_FOLDSTART].val > 0
5513 && (linenr_T)vimvars[VV_FOLDEND].val <= curbuf->b_ml.ml_line_count
5514 && vimvars[VV_FOLDDASHES].val != NULL)
5515 {
5516 /* Find first non-empty line in the fold. */
5517 lnum = (linenr_T)vimvars[VV_FOLDSTART].val;
5518 while (lnum < (linenr_T)vimvars[VV_FOLDEND].val)
5519 {
5520 if (!linewhite(lnum))
5521 break;
5522 ++lnum;
5523 }
5524
5525 /* Find interesting text in this line. */
5526 s = skipwhite(ml_get(lnum));
5527 /* skip C comment-start */
5528 if (s[0] == '/' && (s[1] == '*' || s[1] == '/'))
Bram Moolenaar293ee4d2004-12-09 21:34:53 +00005529 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00005530 s = skipwhite(s + 2);
Bram Moolenaar293ee4d2004-12-09 21:34:53 +00005531 if (*skipwhite(s) == NUL
5532 && lnum + 1 < (linenr_T)vimvars[VV_FOLDEND].val)
5533 {
5534 s = skipwhite(ml_get(lnum + 1));
5535 if (*s == '*')
5536 s = skipwhite(s + 1);
5537 }
5538 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00005539 txt = _("+-%s%3ld lines: ");
5540 r = alloc((unsigned)(STRLEN(txt)
5541 + STRLEN(vimvars[VV_FOLDDASHES].val) /* for %s */
5542 + 20 /* for %3ld */
5543 + STRLEN(s))); /* concatenated */
5544 if (r != NULL)
5545 {
5546 sprintf((char *)r, txt, vimvars[VV_FOLDDASHES].val,
5547 (long)((linenr_T)vimvars[VV_FOLDEND].val
5548 - (linenr_T)vimvars[VV_FOLDSTART].val + 1));
5549 len = (int)STRLEN(r);
5550 STRCAT(r, s);
5551 /* remove 'foldmarker' and 'commentstring' */
5552 foldtext_cleanup(r + len);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005553 rettv->vval.v_string = r;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005554 }
5555 }
5556#endif
5557}
5558
5559/*
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00005560 * "foldtextresult(lnum)" function
5561 */
5562/*ARGSUSED*/
5563 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005564f_foldtextresult(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005565 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005566 typeval *rettv;
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00005567{
5568#ifdef FEAT_FOLDING
5569 linenr_T lnum;
5570 char_u *text;
5571 char_u buf[51];
5572 foldinfo_T foldinfo;
5573 int fold_count;
5574#endif
5575
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005576 rettv->v_type = VAR_STRING;
5577 rettv->vval.v_string = NULL;
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00005578#ifdef FEAT_FOLDING
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005579 lnum = get_tv_lnum(argvars);
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00005580 fold_count = foldedCount(curwin, lnum, &foldinfo);
5581 if (fold_count > 0)
5582 {
5583 text = get_foldtext(curwin, lnum, lnum + fold_count - 1,
5584 &foldinfo, buf);
5585 if (text == buf)
5586 text = vim_strsave(text);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005587 rettv->vval.v_string = text;
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00005588 }
5589#endif
5590}
5591
5592/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00005593 * "foreground()" function
5594 */
5595/*ARGSUSED*/
5596 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005597f_foreground(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005598 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005599 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005600{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005601 rettv->vval.v_number = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005602#ifdef FEAT_GUI
5603 if (gui.in_use)
5604 gui_mch_set_foreground();
5605#else
5606# ifdef WIN32
5607 win32_set_foreground();
5608# endif
5609#endif
5610}
5611
5612/*
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005613 * "function()" function
5614 */
5615/*ARGSUSED*/
5616 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005617f_function(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005618 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005619 typeval *rettv;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005620{
5621 char_u *s;
5622
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005623 s = get_tv_string(&argvars[0]);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005624 if (s == NULL || *s == NUL || isdigit(*s))
5625 EMSG2(_(e_invarg2), s);
5626 else if (!function_exists(s))
5627 EMSG2(_("E999: Unknown function: %s"), s);
5628 else
5629 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005630 rettv->vval.v_string = vim_strsave(s);
5631 rettv->v_type = VAR_FUNC;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005632 }
5633}
5634
5635/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00005636 * "getchar()" function
5637 */
5638 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005639f_getchar(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005640 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005641 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005642{
5643 varnumber_T n;
5644
5645 ++no_mapping;
5646 ++allow_keys;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005647 if (argvars[0].v_type == VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005648 /* getchar(): blocking wait. */
5649 n = safe_vgetc();
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005650 else if (get_tv_number(&argvars[0]) == 1)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005651 /* getchar(1): only check if char avail */
5652 n = vpeekc();
5653 else if (vpeekc() == NUL)
5654 /* getchar(0) and no char avail: return zero */
5655 n = 0;
5656 else
5657 /* getchar(0) and char avail: return char */
5658 n = safe_vgetc();
5659 --no_mapping;
5660 --allow_keys;
5661
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005662 rettv->vval.v_number = n;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005663 if (IS_SPECIAL(n) || mod_mask != 0)
5664 {
5665 char_u temp[10]; /* modifier: 3, mbyte-char: 6, NUL: 1 */
5666 int i = 0;
5667
5668 /* Turn a special key into three bytes, plus modifier. */
5669 if (mod_mask != 0)
5670 {
5671 temp[i++] = K_SPECIAL;
5672 temp[i++] = KS_MODIFIER;
5673 temp[i++] = mod_mask;
5674 }
5675 if (IS_SPECIAL(n))
5676 {
5677 temp[i++] = K_SPECIAL;
5678 temp[i++] = K_SECOND(n);
5679 temp[i++] = K_THIRD(n);
5680 }
5681#ifdef FEAT_MBYTE
5682 else if (has_mbyte)
5683 i += (*mb_char2bytes)(n, temp + i);
5684#endif
5685 else
5686 temp[i++] = n;
5687 temp[i++] = NUL;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005688 rettv->v_type = VAR_STRING;
5689 rettv->vval.v_string = vim_strsave(temp);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005690 }
5691}
5692
5693/*
5694 * "getcharmod()" function
5695 */
5696/*ARGSUSED*/
5697 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005698f_getcharmod(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005699 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005700 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005701{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005702 rettv->vval.v_number = mod_mask;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005703}
5704
5705/*
5706 * "getcmdline()" function
5707 */
5708/*ARGSUSED*/
5709 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005710f_getcmdline(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005711 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005712 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005713{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005714 rettv->v_type = VAR_STRING;
5715 rettv->vval.v_string = get_cmdline_str();
Bram Moolenaar071d4272004-06-13 20:20:40 +00005716}
5717
5718/*
5719 * "getcmdpos()" function
5720 */
5721/*ARGSUSED*/
5722 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005723f_getcmdpos(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005724 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005725 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005726{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005727 rettv->vval.v_number = get_cmdline_pos() + 1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005728}
5729
5730/*
5731 * "getbufvar()" function
5732 */
5733 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005734f_getbufvar(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005735 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005736 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005737{
5738 buf_T *buf;
5739 buf_T *save_curbuf;
5740 char_u *varname;
5741 VAR v;
5742
5743 ++emsg_off;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005744 buf = get_buf_tv(&argvars[0]);
5745 varname = get_tv_string(&argvars[1]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005746
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005747 rettv->v_type = VAR_STRING;
5748 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005749
5750 if (buf != NULL && varname != NULL)
5751 {
5752 if (*varname == '&') /* buffer-local-option */
5753 {
5754 /* set curbuf to be our buf, temporarily */
5755 save_curbuf = curbuf;
5756 curbuf = buf;
5757
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005758 get_option_tv(&varname, rettv, TRUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005759
5760 /* restore previous notion of curbuf */
5761 curbuf = save_curbuf;
5762 }
5763 else
5764 {
5765 /* look up the variable */
5766 v = find_var_in_ga(&buf->b_vars, varname);
5767 if (v != NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005768 copy_tv(&v->tv, rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005769 }
5770 }
5771
5772 --emsg_off;
5773}
5774
5775/*
5776 * "getcwd()" function
5777 */
5778/*ARGSUSED*/
5779 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005780f_getcwd(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005781 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005782 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005783{
5784 char_u cwd[MAXPATHL];
5785
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005786 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005787 if (mch_dirname(cwd, MAXPATHL) == FAIL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005788 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005789 else
5790 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005791 rettv->vval.v_string = vim_strsave(cwd);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005792#ifdef BACKSLASH_IN_FILENAME
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005793 slash_adjust(rettv->vval.v_string);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005794#endif
5795 }
5796}
5797
5798/*
Bram Moolenaar46c9c732004-12-12 11:37:09 +00005799 * "getfontname()" function
5800 */
Bram Moolenaar1cd871b2004-12-19 22:46:22 +00005801/*ARGSUSED*/
Bram Moolenaar46c9c732004-12-12 11:37:09 +00005802 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005803f_getfontname(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005804 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005805 typeval *rettv;
Bram Moolenaar46c9c732004-12-12 11:37:09 +00005806{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005807 rettv->v_type = VAR_STRING;
5808 rettv->vval.v_string = NULL;
Bram Moolenaar46c9c732004-12-12 11:37:09 +00005809#ifdef FEAT_GUI
5810 if (gui.in_use)
5811 {
5812 GuiFont font;
5813 char_u *name = NULL;
5814
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005815 if (argvars[0].v_type == VAR_UNKNOWN)
Bram Moolenaar46c9c732004-12-12 11:37:09 +00005816 {
5817 /* Get the "Normal" font. Either the name saved by
5818 * hl_set_font_name() or from the font ID. */
5819 font = gui.norm_font;
5820 name = hl_get_font_name();
5821 }
5822 else
5823 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005824 name = get_tv_string(&argvars[0]);
Bram Moolenaar46c9c732004-12-12 11:37:09 +00005825 if (STRCMP(name, "*") == 0) /* don't use font dialog */
5826 return;
5827 font = gui_mch_get_font(name, FALSE);
5828 if (font == NOFONT)
5829 return; /* Invalid font name, return empty string. */
5830 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005831 rettv->vval.v_string = gui_mch_get_fontname(font, name);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005832 if (argvars[0].v_type != VAR_UNKNOWN)
Bram Moolenaar46c9c732004-12-12 11:37:09 +00005833 gui_mch_free_font(font);
5834 }
5835#endif
5836}
5837
5838/*
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00005839 * "getfperm({fname})" function
5840 */
5841 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005842f_getfperm(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005843 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005844 typeval *rettv;
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00005845{
5846 char_u *fname;
5847 struct stat st;
5848 char_u *perm = NULL;
5849 char_u flags[] = "rwx";
5850 int i;
5851
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005852 fname = get_tv_string(&argvars[0]);
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00005853
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005854 rettv->v_type = VAR_STRING;
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00005855 if (mch_stat((char *)fname, &st) >= 0)
5856 {
5857 perm = vim_strsave((char_u *)"---------");
5858 if (perm != NULL)
5859 {
5860 for (i = 0; i < 9; i++)
5861 {
5862 if (st.st_mode & (1 << (8 - i)))
5863 perm[i] = flags[i % 3];
5864 }
5865 }
5866 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005867 rettv->vval.v_string = perm;
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00005868}
5869
5870/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00005871 * "getfsize({fname})" function
5872 */
5873 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005874f_getfsize(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005875 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005876 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005877{
5878 char_u *fname;
5879 struct stat st;
5880
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005881 fname = get_tv_string(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005882
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005883 rettv->v_type = VAR_NUMBER;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005884
5885 if (mch_stat((char *)fname, &st) >= 0)
5886 {
5887 if (mch_isdir(fname))
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005888 rettv->vval.v_number = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005889 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005890 rettv->vval.v_number = (varnumber_T)st.st_size;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005891 }
5892 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005893 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005894}
5895
5896/*
5897 * "getftime({fname})" function
5898 */
5899 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005900f_getftime(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005901 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005902 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005903{
5904 char_u *fname;
5905 struct stat st;
5906
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005907 fname = get_tv_string(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005908
5909 if (mch_stat((char *)fname, &st) >= 0)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005910 rettv->vval.v_number = (varnumber_T)st.st_mtime;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005911 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005912 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005913}
5914
5915/*
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00005916 * "getftype({fname})" function
5917 */
5918 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005919f_getftype(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005920 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005921 typeval *rettv;
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00005922{
5923 char_u *fname;
5924 struct stat st;
5925 char_u *type = NULL;
5926 char *t;
5927
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005928 fname = get_tv_string(&argvars[0]);
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00005929
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005930 rettv->v_type = VAR_STRING;
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00005931 if (mch_lstat((char *)fname, &st) >= 0)
5932 {
5933#ifdef S_ISREG
5934 if (S_ISREG(st.st_mode))
5935 t = "file";
5936 else if (S_ISDIR(st.st_mode))
5937 t = "dir";
5938# ifdef S_ISLNK
5939 else if (S_ISLNK(st.st_mode))
5940 t = "link";
5941# endif
5942# ifdef S_ISBLK
5943 else if (S_ISBLK(st.st_mode))
5944 t = "bdev";
5945# endif
5946# ifdef S_ISCHR
5947 else if (S_ISCHR(st.st_mode))
5948 t = "cdev";
5949# endif
5950# ifdef S_ISFIFO
5951 else if (S_ISFIFO(st.st_mode))
5952 t = "fifo";
5953# endif
5954# ifdef S_ISSOCK
5955 else if (S_ISSOCK(st.st_mode))
5956 t = "fifo";
5957# endif
5958 else
5959 t = "other";
5960#else
5961# ifdef S_IFMT
5962 switch (st.st_mode & S_IFMT)
5963 {
5964 case S_IFREG: t = "file"; break;
5965 case S_IFDIR: t = "dir"; break;
5966# ifdef S_IFLNK
5967 case S_IFLNK: t = "link"; break;
5968# endif
5969# ifdef S_IFBLK
5970 case S_IFBLK: t = "bdev"; break;
5971# endif
5972# ifdef S_IFCHR
5973 case S_IFCHR: t = "cdev"; break;
5974# endif
5975# ifdef S_IFIFO
5976 case S_IFIFO: t = "fifo"; break;
5977# endif
5978# ifdef S_IFSOCK
5979 case S_IFSOCK: t = "socket"; break;
5980# endif
5981 default: t = "other";
5982 }
5983# else
5984 if (mch_isdir(fname))
5985 t = "dir";
5986 else
5987 t = "file";
5988# endif
5989#endif
5990 type = vim_strsave((char_u *)t);
5991 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005992 rettv->vval.v_string = type;
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00005993}
5994
5995/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00005996 * "getreg()" function
5997 */
5998 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005999f_getreg(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006000 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006001 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006002{
6003 char_u *strregname;
6004 int regname;
6005
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006006 if (argvars[0].v_type != VAR_UNKNOWN)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006007 strregname = get_tv_string(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006008 else
6009 strregname = vimvars[VV_REG].val;
6010 regname = (strregname == NULL ? '"' : *strregname);
6011 if (regname == 0)
6012 regname = '"';
6013
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006014 rettv->v_type = VAR_STRING;
6015 rettv->vval.v_string = get_reg_contents(regname, TRUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006016}
6017
6018/*
6019 * "getregtype()" function
6020 */
6021 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006022f_getregtype(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006023 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006024 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006025{
6026 char_u *strregname;
6027 int regname;
6028 char_u buf[NUMBUFLEN + 2];
6029 long reglen = 0;
6030
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006031 if (argvars[0].v_type != VAR_UNKNOWN)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006032 strregname = get_tv_string(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006033 else
6034 /* Default to v:register */
6035 strregname = vimvars[VV_REG].val;
6036
6037 regname = (strregname == NULL ? '"' : *strregname);
6038 if (regname == 0)
6039 regname = '"';
6040
6041 buf[0] = NUL;
6042 buf[1] = NUL;
6043 switch (get_reg_type(regname, &reglen))
6044 {
6045 case MLINE: buf[0] = 'V'; break;
6046 case MCHAR: buf[0] = 'v'; break;
6047#ifdef FEAT_VISUAL
6048 case MBLOCK:
6049 buf[0] = Ctrl_V;
6050 sprintf((char *)buf + 1, "%ld", reglen + 1);
6051 break;
6052#endif
6053 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006054 rettv->v_type = VAR_STRING;
6055 rettv->vval.v_string = vim_strsave(buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006056}
6057
6058/*
6059 * "getline(lnum)" function
6060 */
6061 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006062f_getline(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006063 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006064 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006065{
6066 linenr_T lnum;
6067 char_u *p;
6068
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006069 lnum = get_tv_lnum(argvars);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006070
6071 if (lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count)
6072 p = ml_get(lnum);
6073 else
6074 p = (char_u *)"";
6075
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006076 rettv->v_type = VAR_STRING;
6077 rettv->vval.v_string = vim_strsave(p);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006078}
6079
6080/*
6081 * "getwinposx()" function
6082 */
6083/*ARGSUSED*/
6084 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006085f_getwinposx(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006086 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006087 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006088{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006089 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006090#ifdef FEAT_GUI
6091 if (gui.in_use)
6092 {
6093 int x, y;
6094
6095 if (gui_mch_get_winpos(&x, &y) == OK)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006096 rettv->vval.v_number = x;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006097 }
6098#endif
6099}
6100
6101/*
6102 * "getwinposy()" function
6103 */
6104/*ARGSUSED*/
6105 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006106f_getwinposy(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006107 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006108 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006109{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006110 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006111#ifdef FEAT_GUI
6112 if (gui.in_use)
6113 {
6114 int x, y;
6115
6116 if (gui_mch_get_winpos(&x, &y) == OK)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006117 rettv->vval.v_number = y;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006118 }
6119#endif
6120}
6121
6122/*
6123 * "getwinvar()" function
6124 */
6125 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006126f_getwinvar(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006127 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006128 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006129{
6130 win_T *win, *oldcurwin;
6131 char_u *varname;
6132 VAR v;
6133
6134 ++emsg_off;
6135 win = find_win_by_nr(&argvars[0]);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006136 varname = get_tv_string(&argvars[1]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006137
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006138 rettv->v_type = VAR_STRING;
6139 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006140
6141 if (win != NULL && varname != NULL)
6142 {
6143 if (*varname == '&') /* window-local-option */
6144 {
6145 /* set curwin to be our win, temporarily */
6146 oldcurwin = curwin;
6147 curwin = win;
6148
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006149 get_option_tv(&varname, rettv, 1);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006150
6151 /* restore previous notion of curwin */
6152 curwin = oldcurwin;
6153 }
6154 else
6155 {
6156 /* look up the variable */
6157 v = find_var_in_ga(&win->w_vars, varname);
6158 if (v != NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006159 copy_tv(&v->tv, rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006160 }
6161 }
6162
6163 --emsg_off;
6164}
6165
6166/*
6167 * "glob()" function
6168 */
6169 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006170f_glob(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006171 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006172 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006173{
6174 expand_T xpc;
6175
6176 ExpandInit(&xpc);
6177 xpc.xp_context = EXPAND_FILES;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006178 rettv->v_type = VAR_STRING;
6179 rettv->vval.v_string = ExpandOne(&xpc, get_tv_string(&argvars[0]),
Bram Moolenaar071d4272004-06-13 20:20:40 +00006180 NULL, WILD_USE_NL|WILD_SILENT, WILD_ALL);
6181 ExpandCleanup(&xpc);
6182}
6183
6184/*
6185 * "globpath()" function
6186 */
6187 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006188f_globpath(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006189 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006190 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006191{
6192 char_u buf1[NUMBUFLEN];
6193
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006194 rettv->v_type = VAR_STRING;
6195 rettv->vval.v_string = globpath(get_tv_string(&argvars[0]),
6196 get_tv_string_buf(&argvars[1], buf1));
Bram Moolenaar071d4272004-06-13 20:20:40 +00006197}
6198
6199/*
6200 * "has()" function
6201 */
6202 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006203f_has(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006204 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006205 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006206{
6207 int i;
6208 char_u *name;
6209 int n = FALSE;
6210 static char *(has_list[]) =
6211 {
6212#ifdef AMIGA
6213 "amiga",
6214# ifdef FEAT_ARP
6215 "arp",
6216# endif
6217#endif
6218#ifdef __BEOS__
6219 "beos",
6220#endif
6221#ifdef MSDOS
6222# ifdef DJGPP
6223 "dos32",
6224# else
6225 "dos16",
6226# endif
6227#endif
6228#ifdef MACOS /* TODO: Should we add MACOS_CLASSIC, MACOS_X? (Dany) */
6229 "mac",
6230#endif
6231#if defined(MACOS_X_UNIX)
6232 "macunix",
6233#endif
6234#ifdef OS2
6235 "os2",
6236#endif
6237#ifdef __QNX__
6238 "qnx",
6239#endif
6240#ifdef RISCOS
6241 "riscos",
6242#endif
6243#ifdef UNIX
6244 "unix",
6245#endif
6246#ifdef VMS
6247 "vms",
6248#endif
6249#ifdef WIN16
6250 "win16",
6251#endif
6252#ifdef WIN32
6253 "win32",
6254#endif
6255#if defined(UNIX) && (defined(__CYGWIN32__) || defined(__CYGWIN__))
6256 "win32unix",
6257#endif
6258#ifdef WIN64
6259 "win64",
6260#endif
6261#ifdef EBCDIC
6262 "ebcdic",
6263#endif
6264#ifndef CASE_INSENSITIVE_FILENAME
6265 "fname_case",
6266#endif
6267#ifdef FEAT_ARABIC
6268 "arabic",
6269#endif
6270#ifdef FEAT_AUTOCMD
6271 "autocmd",
6272#endif
6273#ifdef FEAT_BEVAL
6274 "balloon_eval",
6275#endif
6276#if defined(SOME_BUILTIN_TCAPS) || defined(ALL_BUILTIN_TCAPS)
6277 "builtin_terms",
6278# ifdef ALL_BUILTIN_TCAPS
6279 "all_builtin_terms",
6280# endif
6281#endif
6282#ifdef FEAT_BYTEOFF
6283 "byte_offset",
6284#endif
6285#ifdef FEAT_CINDENT
6286 "cindent",
6287#endif
6288#ifdef FEAT_CLIENTSERVER
6289 "clientserver",
6290#endif
6291#ifdef FEAT_CLIPBOARD
6292 "clipboard",
6293#endif
6294#ifdef FEAT_CMDL_COMPL
6295 "cmdline_compl",
6296#endif
6297#ifdef FEAT_CMDHIST
6298 "cmdline_hist",
6299#endif
6300#ifdef FEAT_COMMENTS
6301 "comments",
6302#endif
6303#ifdef FEAT_CRYPT
6304 "cryptv",
6305#endif
6306#ifdef FEAT_CSCOPE
6307 "cscope",
6308#endif
6309#ifdef DEBUG
6310 "debug",
6311#endif
6312#ifdef FEAT_CON_DIALOG
6313 "dialog_con",
6314#endif
6315#ifdef FEAT_GUI_DIALOG
6316 "dialog_gui",
6317#endif
6318#ifdef FEAT_DIFF
6319 "diff",
6320#endif
6321#ifdef FEAT_DIGRAPHS
6322 "digraphs",
6323#endif
6324#ifdef FEAT_DND
6325 "dnd",
6326#endif
6327#ifdef FEAT_EMACS_TAGS
6328 "emacs_tags",
6329#endif
6330 "eval", /* always present, of course! */
6331#ifdef FEAT_EX_EXTRA
6332 "ex_extra",
6333#endif
6334#ifdef FEAT_SEARCH_EXTRA
6335 "extra_search",
6336#endif
6337#ifdef FEAT_FKMAP
6338 "farsi",
6339#endif
6340#ifdef FEAT_SEARCHPATH
6341 "file_in_path",
6342#endif
6343#ifdef FEAT_FIND_ID
6344 "find_in_path",
6345#endif
6346#ifdef FEAT_FOLDING
6347 "folding",
6348#endif
6349#ifdef FEAT_FOOTER
6350 "footer",
6351#endif
6352#if !defined(USE_SYSTEM) && defined(UNIX)
6353 "fork",
6354#endif
6355#ifdef FEAT_GETTEXT
6356 "gettext",
6357#endif
6358#ifdef FEAT_GUI
6359 "gui",
6360#endif
6361#ifdef FEAT_GUI_ATHENA
6362# ifdef FEAT_GUI_NEXTAW
6363 "gui_neXtaw",
6364# else
6365 "gui_athena",
6366# endif
6367#endif
Bram Moolenaar843ee412004-06-30 16:16:41 +00006368#ifdef FEAT_GUI_KDE
6369 "gui_kde",
6370#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00006371#ifdef FEAT_GUI_GTK
6372 "gui_gtk",
6373# ifdef HAVE_GTK2
6374 "gui_gtk2",
6375# endif
6376#endif
6377#ifdef FEAT_GUI_MAC
6378 "gui_mac",
6379#endif
6380#ifdef FEAT_GUI_MOTIF
6381 "gui_motif",
6382#endif
6383#ifdef FEAT_GUI_PHOTON
6384 "gui_photon",
6385#endif
6386#ifdef FEAT_GUI_W16
6387 "gui_win16",
6388#endif
6389#ifdef FEAT_GUI_W32
6390 "gui_win32",
6391#endif
6392#ifdef FEAT_HANGULIN
6393 "hangul_input",
6394#endif
6395#if defined(HAVE_ICONV_H) && defined(USE_ICONV)
6396 "iconv",
6397#endif
6398#ifdef FEAT_INS_EXPAND
6399 "insert_expand",
6400#endif
6401#ifdef FEAT_JUMPLIST
6402 "jumplist",
6403#endif
6404#ifdef FEAT_KEYMAP
6405 "keymap",
6406#endif
6407#ifdef FEAT_LANGMAP
6408 "langmap",
6409#endif
6410#ifdef FEAT_LIBCALL
6411 "libcall",
6412#endif
6413#ifdef FEAT_LINEBREAK
6414 "linebreak",
6415#endif
6416#ifdef FEAT_LISP
6417 "lispindent",
6418#endif
6419#ifdef FEAT_LISTCMDS
6420 "listcmds",
6421#endif
6422#ifdef FEAT_LOCALMAP
6423 "localmap",
6424#endif
6425#ifdef FEAT_MENU
6426 "menu",
6427#endif
6428#ifdef FEAT_SESSION
6429 "mksession",
6430#endif
6431#ifdef FEAT_MODIFY_FNAME
6432 "modify_fname",
6433#endif
6434#ifdef FEAT_MOUSE
6435 "mouse",
6436#endif
6437#ifdef FEAT_MOUSESHAPE
6438 "mouseshape",
6439#endif
6440#if defined(UNIX) || defined(VMS)
6441# ifdef FEAT_MOUSE_DEC
6442 "mouse_dec",
6443# endif
6444# ifdef FEAT_MOUSE_GPM
6445 "mouse_gpm",
6446# endif
6447# ifdef FEAT_MOUSE_JSB
6448 "mouse_jsbterm",
6449# endif
6450# ifdef FEAT_MOUSE_NET
6451 "mouse_netterm",
6452# endif
6453# ifdef FEAT_MOUSE_PTERM
6454 "mouse_pterm",
6455# endif
6456# ifdef FEAT_MOUSE_XTERM
6457 "mouse_xterm",
6458# endif
6459#endif
6460#ifdef FEAT_MBYTE
6461 "multi_byte",
6462#endif
6463#ifdef FEAT_MBYTE_IME
6464 "multi_byte_ime",
6465#endif
6466#ifdef FEAT_MULTI_LANG
6467 "multi_lang",
6468#endif
Bram Moolenaar325b7a22004-07-05 15:58:32 +00006469#ifdef FEAT_MZSCHEME
6470 "mzscheme",
6471#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00006472#ifdef FEAT_OLE
6473 "ole",
6474#endif
6475#ifdef FEAT_OSFILETYPE
6476 "osfiletype",
6477#endif
6478#ifdef FEAT_PATH_EXTRA
6479 "path_extra",
6480#endif
6481#ifdef FEAT_PERL
6482#ifndef DYNAMIC_PERL
6483 "perl",
6484#endif
6485#endif
6486#ifdef FEAT_PYTHON
6487#ifndef DYNAMIC_PYTHON
6488 "python",
6489#endif
6490#endif
6491#ifdef FEAT_POSTSCRIPT
6492 "postscript",
6493#endif
6494#ifdef FEAT_PRINTER
6495 "printer",
6496#endif
6497#ifdef FEAT_QUICKFIX
6498 "quickfix",
6499#endif
6500#ifdef FEAT_RIGHTLEFT
6501 "rightleft",
6502#endif
6503#if defined(FEAT_RUBY) && !defined(DYNAMIC_RUBY)
6504 "ruby",
6505#endif
6506#ifdef FEAT_SCROLLBIND
6507 "scrollbind",
6508#endif
6509#ifdef FEAT_CMDL_INFO
6510 "showcmd",
6511 "cmdline_info",
6512#endif
6513#ifdef FEAT_SIGNS
6514 "signs",
6515#endif
6516#ifdef FEAT_SMARTINDENT
6517 "smartindent",
6518#endif
6519#ifdef FEAT_SNIFF
6520 "sniff",
6521#endif
6522#ifdef FEAT_STL_OPT
6523 "statusline",
6524#endif
6525#ifdef FEAT_SUN_WORKSHOP
6526 "sun_workshop",
6527#endif
6528#ifdef FEAT_NETBEANS_INTG
6529 "netbeans_intg",
6530#endif
6531#ifdef FEAT_SYN_HL
6532 "syntax",
6533#endif
6534#if defined(USE_SYSTEM) || !defined(UNIX)
6535 "system",
6536#endif
6537#ifdef FEAT_TAG_BINS
6538 "tag_binary",
6539#endif
6540#ifdef FEAT_TAG_OLDSTATIC
6541 "tag_old_static",
6542#endif
6543#ifdef FEAT_TAG_ANYWHITE
6544 "tag_any_white",
6545#endif
6546#ifdef FEAT_TCL
6547# ifndef DYNAMIC_TCL
6548 "tcl",
6549# endif
6550#endif
6551#ifdef TERMINFO
6552 "terminfo",
6553#endif
6554#ifdef FEAT_TERMRESPONSE
6555 "termresponse",
6556#endif
6557#ifdef FEAT_TEXTOBJ
6558 "textobjects",
6559#endif
6560#ifdef HAVE_TGETENT
6561 "tgetent",
6562#endif
6563#ifdef FEAT_TITLE
6564 "title",
6565#endif
6566#ifdef FEAT_TOOLBAR
6567 "toolbar",
6568#endif
6569#ifdef FEAT_USR_CMDS
6570 "user-commands", /* was accidentally included in 5.4 */
6571 "user_commands",
6572#endif
6573#ifdef FEAT_VIMINFO
6574 "viminfo",
6575#endif
6576#ifdef FEAT_VERTSPLIT
6577 "vertsplit",
6578#endif
6579#ifdef FEAT_VIRTUALEDIT
6580 "virtualedit",
6581#endif
6582#ifdef FEAT_VISUAL
6583 "visual",
6584#endif
6585#ifdef FEAT_VISUALEXTRA
6586 "visualextra",
6587#endif
6588#ifdef FEAT_VREPLACE
6589 "vreplace",
6590#endif
6591#ifdef FEAT_WILDIGN
6592 "wildignore",
6593#endif
6594#ifdef FEAT_WILDMENU
6595 "wildmenu",
6596#endif
6597#ifdef FEAT_WINDOWS
6598 "windows",
6599#endif
6600#ifdef FEAT_WAK
6601 "winaltkeys",
6602#endif
6603#ifdef FEAT_WRITEBACKUP
6604 "writebackup",
6605#endif
6606#ifdef FEAT_XIM
6607 "xim",
6608#endif
6609#ifdef FEAT_XFONTSET
6610 "xfontset",
6611#endif
6612#ifdef USE_XSMP
6613 "xsmp",
6614#endif
6615#ifdef USE_XSMP_INTERACT
6616 "xsmp_interact",
6617#endif
6618#ifdef FEAT_XCLIPBOARD
6619 "xterm_clipboard",
6620#endif
6621#ifdef FEAT_XTERM_SAVE
6622 "xterm_save",
6623#endif
6624#if defined(UNIX) && defined(FEAT_X11)
6625 "X11",
6626#endif
6627 NULL
6628 };
6629
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006630 name = get_tv_string(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006631 for (i = 0; has_list[i] != NULL; ++i)
6632 if (STRICMP(name, has_list[i]) == 0)
6633 {
6634 n = TRUE;
6635 break;
6636 }
6637
6638 if (n == FALSE)
6639 {
6640 if (STRNICMP(name, "patch", 5) == 0)
6641 n = has_patch(atoi((char *)name + 5));
6642 else if (STRICMP(name, "vim_starting") == 0)
6643 n = (starting != 0);
6644#ifdef DYNAMIC_TCL
6645 else if (STRICMP(name, "tcl") == 0)
6646 n = tcl_enabled(FALSE);
6647#endif
6648#if defined(USE_ICONV) && defined(DYNAMIC_ICONV)
6649 else if (STRICMP(name, "iconv") == 0)
6650 n = iconv_enabled(FALSE);
6651#endif
6652#ifdef DYNAMIC_RUBY
6653 else if (STRICMP(name, "ruby") == 0)
6654 n = ruby_enabled(FALSE);
6655#endif
6656#ifdef DYNAMIC_PYTHON
6657 else if (STRICMP(name, "python") == 0)
6658 n = python_enabled(FALSE);
6659#endif
6660#ifdef DYNAMIC_PERL
6661 else if (STRICMP(name, "perl") == 0)
6662 n = perl_enabled(FALSE);
6663#endif
6664#ifdef FEAT_GUI
6665 else if (STRICMP(name, "gui_running") == 0)
6666 n = (gui.in_use || gui.starting);
6667# ifdef FEAT_GUI_W32
6668 else if (STRICMP(name, "gui_win32s") == 0)
6669 n = gui_is_win32s();
6670# endif
6671# ifdef FEAT_BROWSE
6672 else if (STRICMP(name, "browse") == 0)
6673 n = gui.in_use; /* gui_mch_browse() works when GUI is running */
6674# endif
6675#endif
6676#ifdef FEAT_SYN_HL
6677 else if (STRICMP(name, "syntax_items") == 0)
6678 n = syntax_present(curbuf);
6679#endif
6680#if defined(WIN3264)
6681 else if (STRICMP(name, "win95") == 0)
6682 n = mch_windows95();
6683#endif
Bram Moolenaar35a9aaa2004-10-24 19:23:07 +00006684#ifdef FEAT_NETBEANS_INTG
6685 else if (STRICMP(name, "netbeans_enabled") == 0)
6686 n = usingNetbeans;
6687#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00006688 }
6689
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006690 rettv->vval.v_number = n;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006691}
6692
6693/*
6694 * "hasmapto()" function
6695 */
6696 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006697f_hasmapto(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006698 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006699 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006700{
6701 char_u *name;
6702 char_u *mode;
6703 char_u buf[NUMBUFLEN];
6704
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006705 name = get_tv_string(&argvars[0]);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006706 if (argvars[1].v_type == VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006707 mode = (char_u *)"nvo";
6708 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006709 mode = get_tv_string_buf(&argvars[1], buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006710
6711 if (map_to_exists(name, mode))
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006712 rettv->vval.v_number = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006713 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006714 rettv->vval.v_number = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006715}
6716
6717/*
6718 * "histadd()" function
6719 */
6720/*ARGSUSED*/
6721 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006722f_histadd(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006723 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006724 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006725{
6726#ifdef FEAT_CMDHIST
6727 int histype;
6728 char_u *str;
6729 char_u buf[NUMBUFLEN];
6730#endif
6731
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006732 rettv->vval.v_number = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006733 if (check_restricted() || check_secure())
6734 return;
6735#ifdef FEAT_CMDHIST
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006736 histype = get_histtype(get_tv_string(&argvars[0]));
Bram Moolenaar071d4272004-06-13 20:20:40 +00006737 if (histype >= 0)
6738 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006739 str = get_tv_string_buf(&argvars[1], buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006740 if (*str != NUL)
6741 {
6742 add_to_history(histype, str, FALSE, NUL);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006743 rettv->vval.v_number = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006744 return;
6745 }
6746 }
6747#endif
6748}
6749
6750/*
6751 * "histdel()" function
6752 */
6753/*ARGSUSED*/
6754 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006755f_histdel(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006756 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006757 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006758{
6759#ifdef FEAT_CMDHIST
6760 int n;
6761 char_u buf[NUMBUFLEN];
6762
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006763 if (argvars[1].v_type == VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006764 /* only one argument: clear entire history */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006765 n = clr_history(get_histtype(get_tv_string(&argvars[0])));
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006766 else if (argvars[1].v_type == VAR_NUMBER)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006767 /* index given: remove that entry */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006768 n = del_history_idx(get_histtype(get_tv_string(&argvars[0])),
6769 (int)get_tv_number(&argvars[1]));
Bram Moolenaar071d4272004-06-13 20:20:40 +00006770 else
6771 /* string given: remove all matching entries */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006772 n = del_history_entry(get_histtype(get_tv_string(&argvars[0])),
6773 get_tv_string_buf(&argvars[1], buf));
6774 rettv->vval.v_number = n;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006775#else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006776 rettv->vval.v_number = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006777#endif
6778}
6779
6780/*
6781 * "histget()" function
6782 */
6783/*ARGSUSED*/
6784 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006785f_histget(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006786 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006787 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006788{
6789#ifdef FEAT_CMDHIST
6790 int type;
6791 int idx;
6792
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006793 type = get_histtype(get_tv_string(&argvars[0]));
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006794 if (argvars[1].v_type == VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006795 idx = get_history_idx(type);
6796 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006797 idx = (int)get_tv_number(&argvars[1]);
6798 rettv->vval.v_string = vim_strsave(get_history_entry(type, idx));
Bram Moolenaar071d4272004-06-13 20:20:40 +00006799#else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006800 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006801#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006802 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006803}
6804
6805/*
6806 * "histnr()" function
6807 */
6808/*ARGSUSED*/
6809 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006810f_histnr(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006811 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006812 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006813{
6814 int i;
6815
6816#ifdef FEAT_CMDHIST
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006817 i = get_histtype(get_tv_string(&argvars[0]));
Bram Moolenaar071d4272004-06-13 20:20:40 +00006818 if (i >= HIST_CMD && i < HIST_COUNT)
6819 i = get_history_idx(i);
6820 else
6821#endif
6822 i = -1;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006823 rettv->vval.v_number = i;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006824}
6825
6826/*
6827 * "highlight_exists()" function
6828 */
6829 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006830f_hlexists(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006831 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006832 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006833{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006834 rettv->vval.v_number = highlight_exists(get_tv_string(&argvars[0]));
Bram Moolenaar071d4272004-06-13 20:20:40 +00006835}
6836
6837/*
6838 * "highlightID(name)" function
6839 */
6840 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006841f_hlID(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006842 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006843 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006844{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006845 rettv->vval.v_number = syn_name2id(get_tv_string(&argvars[0]));
Bram Moolenaar071d4272004-06-13 20:20:40 +00006846}
6847
6848/*
6849 * "hostname()" function
6850 */
6851/*ARGSUSED*/
6852 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006853f_hostname(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006854 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006855 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006856{
6857 char_u hostname[256];
6858
6859 mch_get_host_name(hostname, 256);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006860 rettv->v_type = VAR_STRING;
6861 rettv->vval.v_string = vim_strsave(hostname);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006862}
6863
6864/*
6865 * iconv() function
6866 */
6867/*ARGSUSED*/
6868 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006869f_iconv(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006870 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006871 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006872{
6873#ifdef FEAT_MBYTE
6874 char_u buf1[NUMBUFLEN];
6875 char_u buf2[NUMBUFLEN];
6876 char_u *from, *to, *str;
6877 vimconv_T vimconv;
6878#endif
6879
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006880 rettv->v_type = VAR_STRING;
6881 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006882
6883#ifdef FEAT_MBYTE
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006884 str = get_tv_string(&argvars[0]);
6885 from = enc_canonize(enc_skip(get_tv_string_buf(&argvars[1], buf1)));
6886 to = enc_canonize(enc_skip(get_tv_string_buf(&argvars[2], buf2)));
Bram Moolenaar071d4272004-06-13 20:20:40 +00006887 vimconv.vc_type = CONV_NONE;
6888 convert_setup(&vimconv, from, to);
6889
6890 /* If the encodings are equal, no conversion needed. */
6891 if (vimconv.vc_type == CONV_NONE)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006892 rettv->vval.v_string = vim_strsave(str);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006893 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006894 rettv->vval.v_string = string_convert(&vimconv, str, NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006895
6896 convert_setup(&vimconv, NULL, NULL);
6897 vim_free(from);
6898 vim_free(to);
6899#endif
6900}
6901
6902/*
6903 * "indent()" function
6904 */
6905 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006906f_indent(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006907 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006908 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006909{
6910 linenr_T lnum;
6911
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006912 lnum = get_tv_lnum(argvars);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006913 if (lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006914 rettv->vval.v_number = get_indent_lnum(lnum);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006915 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006916 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006917}
6918
6919static int inputsecret_flag = 0;
6920
6921/*
6922 * "input()" function
6923 * Also handles inputsecret() when inputsecret is set.
6924 */
6925 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006926f_input(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006927 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006928 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006929{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006930 char_u *prompt = get_tv_string(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006931 char_u *p = NULL;
6932 int c;
6933 char_u buf[NUMBUFLEN];
6934 int cmd_silent_save = cmd_silent;
6935
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006936 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006937
6938#ifdef NO_CONSOLE_INPUT
6939 /* While starting up, there is no place to enter text. */
6940 if (no_console_input())
6941 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006942 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006943 return;
6944 }
6945#endif
6946
6947 cmd_silent = FALSE; /* Want to see the prompt. */
6948 if (prompt != NULL)
6949 {
6950 /* Only the part of the message after the last NL is considered as
6951 * prompt for the command line */
6952 p = vim_strrchr(prompt, '\n');
6953 if (p == NULL)
6954 p = prompt;
6955 else
6956 {
6957 ++p;
6958 c = *p;
6959 *p = NUL;
6960 msg_start();
6961 msg_clr_eos();
6962 msg_puts_attr(prompt, echo_attr);
6963 msg_didout = FALSE;
6964 msg_starthere();
6965 *p = c;
6966 }
6967 cmdline_row = msg_row;
6968 }
6969
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006970 if (argvars[1].v_type != VAR_UNKNOWN)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006971 stuffReadbuffSpec(get_tv_string_buf(&argvars[1], buf));
Bram Moolenaar071d4272004-06-13 20:20:40 +00006972
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006973 rettv->vval.v_string =
Bram Moolenaar071d4272004-06-13 20:20:40 +00006974 getcmdline_prompt(inputsecret_flag ? NUL : '@', p, echo_attr);
6975
6976 /* since the user typed this, no need to wait for return */
6977 need_wait_return = FALSE;
6978 msg_didout = FALSE;
6979 cmd_silent = cmd_silent_save;
6980}
6981
6982/*
6983 * "inputdialog()" function
6984 */
6985 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006986f_inputdialog(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006987 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006988 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006989{
6990#if defined(FEAT_GUI_TEXTDIALOG)
6991 /* Use a GUI dialog if the GUI is running and 'c' is not in 'guioptions' */
6992 if (gui.in_use && vim_strchr(p_go, GO_CONDIALOG) == NULL)
6993 {
6994 char_u *message;
6995 char_u buf[NUMBUFLEN];
6996
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006997 message = get_tv_string(&argvars[0]);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006998 if (argvars[1].v_type != VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006999 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007000 STRNCPY(IObuff, get_tv_string_buf(&argvars[1], buf), IOSIZE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007001 IObuff[IOSIZE - 1] = NUL;
7002 }
7003 else
7004 IObuff[0] = NUL;
7005 if (do_dialog(VIM_QUESTION, NULL, message, (char_u *)_("&OK\n&Cancel"),
7006 1, IObuff) == 1)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007007 rettv->vval.v_string = vim_strsave(IObuff);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007008 else
7009 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007010 if (argvars[1].v_type != VAR_UNKNOWN
7011 && argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007012 rettv->vval.v_string = vim_strsave(
7013 get_tv_string_buf(&argvars[2], buf));
Bram Moolenaar071d4272004-06-13 20:20:40 +00007014 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007015 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007016 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007017 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007018 }
7019 else
7020#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007021 f_input(argvars, rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007022}
7023
7024static garray_T ga_userinput = {0, 0, sizeof(tasave_T), 4, NULL};
7025
7026/*
7027 * "inputrestore()" function
7028 */
7029/*ARGSUSED*/
7030 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007031f_inputrestore(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007032 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007033 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007034{
7035 if (ga_userinput.ga_len > 0)
7036 {
7037 --ga_userinput.ga_len;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007038 restore_typeahead((tasave_T *)(ga_userinput.ga_data)
7039 + ga_userinput.ga_len);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007040 rettv->vval.v_number = 0; /* OK */
Bram Moolenaar071d4272004-06-13 20:20:40 +00007041 }
7042 else if (p_verbose > 1)
7043 {
7044 msg((char_u *)_("called inputrestore() more often than inputsave()"));
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007045 rettv->vval.v_number = 1; /* Failed */
Bram Moolenaar071d4272004-06-13 20:20:40 +00007046 }
7047}
7048
7049/*
7050 * "inputsave()" function
7051 */
7052/*ARGSUSED*/
7053 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007054f_inputsave(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007055 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007056 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007057{
7058 /* Add an entry to the stack of typehead storage. */
7059 if (ga_grow(&ga_userinput, 1) == OK)
7060 {
7061 save_typeahead((tasave_T *)(ga_userinput.ga_data)
7062 + ga_userinput.ga_len);
7063 ++ga_userinput.ga_len;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007064 rettv->vval.v_number = 0; /* OK */
Bram Moolenaar071d4272004-06-13 20:20:40 +00007065 }
7066 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007067 rettv->vval.v_number = 1; /* Failed */
Bram Moolenaar071d4272004-06-13 20:20:40 +00007068}
7069
7070/*
7071 * "inputsecret()" function
7072 */
7073 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007074f_inputsecret(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007075 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007076 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007077{
7078 ++cmdline_star;
7079 ++inputsecret_flag;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007080 f_input(argvars, rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007081 --cmdline_star;
7082 --inputsecret_flag;
7083}
7084
7085/*
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007086 * "insert()" function
7087 */
7088 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007089f_insert(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007090 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007091 typeval *rettv;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007092{
7093 long before = 0;
7094 long n;
7095 listitem *item;
7096 listitem *ni;
7097 listvar *l;
7098
7099 if (argvars[0].v_type != VAR_LIST)
7100 EMSG(_("E999: First argument of insert() must be a list"));
7101 else if ((l = argvars[0].vval.v_list) != NULL)
7102 {
7103 if (argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007104 before = get_tv_number(&argvars[2]);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007105
7106 if (before < 0)
7107 {
7108 /* Count from the end: -1 is before last item. */
7109 item = l->lv_last;
7110 for (n = before + 1; n < 0 && item != NULL; ++n)
7111 item = item->li_prev;
7112 if (item == NULL)
7113 n = 1; /* report an error, don't append */
7114 }
7115 else
7116 {
7117 /* Can't use list_find() here, we allow one past the end. */
7118 item = l->lv_first;
7119 for (n = before; n > 0 && item != NULL; --n)
7120 item = item->li_next;
7121 }
7122 if (n > 0)
7123 EMSGN(_(e_listidx), before);
7124 else
7125 {
7126 ni = listitem_alloc();
7127 if (ni != NULL)
7128 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007129 copy_tv(&argvars[1], &ni->li_tv);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007130 if (item == NULL)
7131 /* Append new item at end of list. */
7132 list_append(l, ni);
7133 else
7134 {
7135 /* Insert new item before existing item. */
7136 ni->li_prev = item->li_prev;
7137 ni->li_next = item;
7138 if (item->li_prev == NULL)
7139 l->lv_first = ni;
7140 else
7141 item->li_prev->li_next = ni;
7142 item->li_prev = ni;
7143 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007144 copy_tv(&argvars[0], rettv);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007145 }
7146 }
7147 }
7148}
7149
7150/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00007151 * "isdirectory()" function
7152 */
7153 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007154f_isdirectory(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007155 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007156 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007157{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007158 rettv->vval.v_number = mch_isdir(get_tv_string(&argvars[0]));
Bram Moolenaar071d4272004-06-13 20:20:40 +00007159}
7160
7161/*
7162 * "last_buffer_nr()" function.
7163 */
7164/*ARGSUSED*/
7165 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007166f_last_buffer_nr(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007167 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007168 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007169{
7170 int n = 0;
7171 buf_T *buf;
7172
7173 for (buf = firstbuf; buf != NULL; buf = buf->b_next)
7174 if (n < buf->b_fnum)
7175 n = buf->b_fnum;
7176
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007177 rettv->vval.v_number = n;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007178}
7179
7180/*
7181 * "len()" function
7182 */
7183 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007184f_len(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007185 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007186 typeval *rettv;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007187{
7188 switch (argvars[0].v_type)
7189 {
7190 case VAR_STRING:
7191 case VAR_NUMBER:
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007192 rettv->vval.v_number = (varnumber_T)STRLEN(
7193 get_tv_string(&argvars[0]));
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007194 break;
7195 case VAR_LIST:
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007196 rettv->vval.v_number = list_len(argvars[0].vval.v_list);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007197 break;
7198 default:
7199 EMSG(_("E999: Invalid type for len()"));
7200 break;
7201 }
7202}
7203
7204/*
7205 * "libcall()" function
7206 */
7207 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007208f_libcall(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007209 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007210 typeval *rettv;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007211{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007212 libcall_common(argvars, rettv, VAR_STRING);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007213}
7214
7215/*
7216 * "libcallnr()" function
7217 */
7218 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007219f_libcallnr(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007220 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007221 typeval *rettv;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007222{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007223 libcall_common(argvars, rettv, VAR_NUMBER);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007224}
7225
7226 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007227libcall_common(argvars, rettv, type)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007228 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007229 typeval *rettv;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007230 int type;
7231{
7232#ifdef FEAT_LIBCALL
7233 char_u *string_in;
7234 char_u **string_result;
7235 int nr_result;
7236#endif
7237
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007238 rettv->v_type = type;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007239 if (type == VAR_NUMBER)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007240 rettv->vval.v_number = 0;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007241 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007242 rettv->vval.v_string = NULL;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007243
7244 if (check_restricted() || check_secure())
7245 return;
7246
7247#ifdef FEAT_LIBCALL
7248 /* The first two args must be strings, otherwise its meaningless */
7249 if (argvars[0].v_type == VAR_STRING && argvars[1].v_type == VAR_STRING)
7250 {
7251 if (argvars[2].v_type == VAR_NUMBER)
7252 string_in = NULL;
7253 else
7254 string_in = argvars[2].vval.v_string;
7255 if (type == VAR_NUMBER)
7256 string_result = NULL;
7257 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007258 string_result = &rettv->vval.v_string;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007259 if (mch_libcall(argvars[0].vval.v_string,
7260 argvars[1].vval.v_string,
7261 string_in,
7262 argvars[2].vval.v_number,
7263 string_result,
7264 &nr_result) == OK
7265 && type == VAR_NUMBER)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007266 rettv->vval.v_number = nr_result;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007267 }
7268#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00007269}
7270
7271/*
7272 * "line(string)" function
7273 */
7274 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007275f_line(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007276 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007277 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007278{
7279 linenr_T lnum = 0;
7280 pos_T *fp;
7281
7282 fp = var2fpos(&argvars[0], TRUE);
7283 if (fp != NULL)
7284 lnum = fp->lnum;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007285 rettv->vval.v_number = lnum;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007286}
7287
7288/*
7289 * "line2byte(lnum)" function
7290 */
7291/*ARGSUSED*/
7292 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007293f_line2byte(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007294 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007295 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007296{
7297#ifndef FEAT_BYTEOFF
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007298 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007299#else
7300 linenr_T lnum;
7301
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007302 lnum = get_tv_lnum(argvars);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007303 if (lnum < 1 || lnum > curbuf->b_ml.ml_line_count + 1)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007304 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007305 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007306 rettv->vval.v_number = ml_find_line_or_offset(curbuf, lnum, NULL);
7307 if (rettv->vval.v_number >= 0)
7308 ++rettv->vval.v_number;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007309#endif
7310}
7311
7312/*
7313 * "lispindent(lnum)" function
7314 */
7315 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007316f_lispindent(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007317 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007318 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007319{
7320#ifdef FEAT_LISP
7321 pos_T pos;
7322 linenr_T lnum;
7323
7324 pos = curwin->w_cursor;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007325 lnum = get_tv_lnum(argvars);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007326 if (lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count)
7327 {
7328 curwin->w_cursor.lnum = lnum;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007329 rettv->vval.v_number = get_lisp_indent();
Bram Moolenaar071d4272004-06-13 20:20:40 +00007330 curwin->w_cursor = pos;
7331 }
7332 else
7333#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007334 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007335}
7336
7337/*
7338 * "localtime()" function
7339 */
7340/*ARGSUSED*/
7341 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007342f_localtime(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007343 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007344 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007345{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007346 rettv->vval.v_number = (varnumber_T)time(NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007347}
7348
7349/*
7350 * "maparg()" function
7351 */
7352 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007353f_maparg(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007354 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007355 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007356{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007357 get_maparg(argvars, rettv, TRUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007358}
7359
7360/*
7361 * "mapcheck()" function
7362 */
7363 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007364f_mapcheck(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007365 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007366 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007367{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007368 get_maparg(argvars, rettv, FALSE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007369}
7370
7371 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007372get_maparg(argvars, rettv, exact)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007373 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007374 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007375 int exact;
7376{
7377 char_u *keys;
7378 char_u *which;
7379 char_u buf[NUMBUFLEN];
7380 char_u *keys_buf = NULL;
7381 char_u *rhs;
7382 int mode;
7383 garray_T ga;
7384
7385 /* return empty string for failure */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007386 rettv->v_type = VAR_STRING;
7387 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007388
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007389 keys = get_tv_string(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007390 if (*keys == NUL)
7391 return;
7392
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007393 if (argvars[1].v_type != VAR_UNKNOWN)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007394 which = get_tv_string_buf(&argvars[1], buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007395 else
7396 which = (char_u *)"";
7397 mode = get_map_mode(&which, 0);
7398
7399 keys = replace_termcodes(keys, &keys_buf, TRUE, TRUE);
7400 rhs = check_map(keys, mode, exact);
7401 vim_free(keys_buf);
7402 if (rhs != NULL)
7403 {
7404 ga_init(&ga);
7405 ga.ga_itemsize = 1;
7406 ga.ga_growsize = 40;
7407
7408 while (*rhs != NUL)
7409 ga_concat(&ga, str2special(&rhs, FALSE));
7410
7411 ga_append(&ga, NUL);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007412 rettv->vval.v_string = (char_u *)ga.ga_data;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007413 }
7414}
7415
7416/*
7417 * "match()" function
7418 */
7419 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007420f_match(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007421 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007422 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007423{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007424 find_some_match(argvars, rettv, 1);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007425}
7426
7427/*
7428 * "matchend()" function
7429 */
7430 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007431f_matchend(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007432 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007433 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007434{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007435 find_some_match(argvars, rettv, 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007436}
7437
7438/*
7439 * "matchstr()" function
7440 */
7441 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007442f_matchstr(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007443 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007444 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007445{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007446 find_some_match(argvars, rettv, 2);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007447}
7448
7449 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007450find_some_match(argvars, rettv, type)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007451 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007452 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007453 int type;
7454{
7455 char_u *str;
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00007456 char_u *expr;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007457 char_u *pat;
7458 regmatch_T regmatch;
7459 char_u patbuf[NUMBUFLEN];
7460 char_u *save_cpo;
7461 long start = 0;
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00007462 long nth = 1;
7463 int match;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007464
7465 /* Make 'cpoptions' empty, the 'l' flag should not be used here. */
7466 save_cpo = p_cpo;
7467 p_cpo = (char_u *)"";
7468
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007469 expr = str = get_tv_string(&argvars[0]);
7470 pat = get_tv_string_buf(&argvars[1], patbuf);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007471
7472 if (type == 2)
7473 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007474 rettv->v_type = VAR_STRING;
7475 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007476 }
7477 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007478 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007479
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007480 if (argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007481 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007482 start = get_tv_number(&argvars[2]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007483 if (start < 0)
7484 start = 0;
7485 if (start > (long)STRLEN(str))
7486 goto theend;
7487 str += start;
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00007488
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007489 if (argvars[3].v_type != VAR_UNKNOWN)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007490 nth = get_tv_number(&argvars[3]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007491 }
7492
7493 regmatch.regprog = vim_regcomp(pat, RE_MAGIC + RE_STRING);
7494 if (regmatch.regprog != NULL)
7495 {
7496 regmatch.rm_ic = p_ic;
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00007497
7498 while (1)
7499 {
7500 match = vim_regexec_nl(&regmatch, str, (colnr_T)0);
7501 if (!match || --nth <= 0)
7502 break;
7503 /* Advance to just after the match. */
7504#ifdef FEAT_MBYTE
7505 str = regmatch.startp[0] + mb_ptr2len_check(regmatch.startp[0]);
7506#else
7507 str = regmatch.startp[0] + 1;
7508#endif
7509 }
7510
7511 if (match)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007512 {
7513 if (type == 2)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007514 rettv->vval.v_string = vim_strnsave(regmatch.startp[0],
Bram Moolenaar071d4272004-06-13 20:20:40 +00007515 (int)(regmatch.endp[0] - regmatch.startp[0]));
7516 else
7517 {
7518 if (type != 0)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007519 rettv->vval.v_number =
Bram Moolenaar071d4272004-06-13 20:20:40 +00007520 (varnumber_T)(regmatch.startp[0] - str);
7521 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007522 rettv->vval.v_number =
Bram Moolenaar071d4272004-06-13 20:20:40 +00007523 (varnumber_T)(regmatch.endp[0] - str);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007524 rettv->vval.v_number += str - expr;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007525 }
7526 }
7527 vim_free(regmatch.regprog);
7528 }
7529
7530theend:
7531 p_cpo = save_cpo;
7532}
7533
7534/*
7535 * "mode()" function
7536 */
7537/*ARGSUSED*/
7538 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007539f_mode(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007540 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007541 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007542{
7543 char_u buf[2];
7544
7545#ifdef FEAT_VISUAL
7546 if (VIsual_active)
7547 {
7548 if (VIsual_select)
7549 buf[0] = VIsual_mode + 's' - 'v';
7550 else
7551 buf[0] = VIsual_mode;
7552 }
7553 else
7554#endif
7555 if (State == HITRETURN || State == ASKMORE || State == SETWSIZE)
7556 buf[0] = 'r';
7557 else if (State & INSERT)
7558 {
7559 if (State & REPLACE_FLAG)
7560 buf[0] = 'R';
7561 else
7562 buf[0] = 'i';
7563 }
7564 else if (State & CMDLINE)
7565 buf[0] = 'c';
7566 else
7567 buf[0] = 'n';
7568
7569 buf[1] = NUL;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007570 rettv->vval.v_string = vim_strsave(buf);
7571 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007572}
7573
7574/*
7575 * "nr2char()" function
7576 */
7577 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007578f_nr2char(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007579 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007580 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007581{
7582 char_u buf[NUMBUFLEN];
7583
7584#ifdef FEAT_MBYTE
7585 if (has_mbyte)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007586 buf[(*mb_char2bytes)((int)get_tv_number(&argvars[0]), buf)] = NUL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007587 else
7588#endif
7589 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007590 buf[0] = (char_u)get_tv_number(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007591 buf[1] = NUL;
7592 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007593 rettv->v_type = VAR_STRING;
7594 rettv->vval.v_string = vim_strsave(buf);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007595}
7596
7597/*
7598 * "remove({list}, {idx})" function
7599 */
7600 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007601f_remove(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007602 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007603 typeval *rettv;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007604{
7605 listvar *l;
7606 listitem *item;
7607 long idx;
7608
7609 if (argvars[0].v_type != VAR_LIST)
7610 EMSG(_("E999: First argument of remove() must be a list"));
7611 else if ((l = argvars[0].vval.v_list) != NULL)
7612 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007613 idx = get_tv_number(&argvars[1]);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007614 item = list_getrem(l, idx);
7615 if (item == NULL)
7616 EMSGN(_(e_listidx), idx);
7617 else
7618 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007619 *rettv = item->li_tv;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007620 vim_free(item);
7621 }
7622 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00007623}
7624
7625/*
7626 * "rename({from}, {to})" function
7627 */
7628 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007629f_rename(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007630 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007631 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007632{
7633 char_u buf[NUMBUFLEN];
7634
7635 if (check_restricted() || check_secure())
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007636 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007637 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007638 rettv->vval.v_number = vim_rename(get_tv_string(&argvars[0]),
7639 get_tv_string_buf(&argvars[1], buf));
Bram Moolenaar071d4272004-06-13 20:20:40 +00007640}
7641
7642/*
7643 * "resolve()" function
7644 */
7645 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007646f_resolve(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007647 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007648 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007649{
7650 char_u *p;
7651
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007652 p = get_tv_string(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007653#ifdef FEAT_SHORTCUT
7654 {
7655 char_u *v = NULL;
7656
7657 v = mch_resolve_shortcut(p);
7658 if (v != NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007659 rettv->vval.v_string = v;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007660 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007661 rettv->vval.v_string = vim_strsave(p);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007662 }
7663#else
7664# ifdef HAVE_READLINK
7665 {
7666 char_u buf[MAXPATHL + 1];
7667 char_u *cpy;
7668 int len;
7669 char_u *remain = NULL;
7670 char_u *q;
7671 int is_relative_to_current = FALSE;
7672 int has_trailing_pathsep = FALSE;
7673 int limit = 100;
7674
7675 p = vim_strsave(p);
7676
7677 if (p[0] == '.' && (vim_ispathsep(p[1])
7678 || (p[1] == '.' && (vim_ispathsep(p[2])))))
7679 is_relative_to_current = TRUE;
7680
7681 len = STRLEN(p);
Bram Moolenaar1cd871b2004-12-19 22:46:22 +00007682 if (len > 0 && after_pathsep(p, p + len))
Bram Moolenaar071d4272004-06-13 20:20:40 +00007683 has_trailing_pathsep = TRUE;
7684
7685 q = getnextcomp(p);
7686 if (*q != NUL)
7687 {
7688 /* Separate the first path component in "p", and keep the
7689 * remainder (beginning with the path separator). */
7690 remain = vim_strsave(q - 1);
7691 q[-1] = NUL;
7692 }
7693
7694 for (;;)
7695 {
7696 for (;;)
7697 {
7698 len = readlink((char *)p, (char *)buf, MAXPATHL);
7699 if (len <= 0)
7700 break;
7701 buf[len] = NUL;
7702
7703 if (limit-- == 0)
7704 {
7705 vim_free(p);
7706 vim_free(remain);
7707 EMSG(_("E655: Too many symbolic links (cycle?)"));
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007708 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007709 goto fail;
7710 }
7711
7712 /* Ensure that the result will have a trailing path separator
7713 * if the argument has one. */
7714 if (remain == NULL && has_trailing_pathsep)
7715 add_pathsep(buf);
7716
7717 /* Separate the first path component in the link value and
7718 * concatenate the remainders. */
7719 q = getnextcomp(vim_ispathsep(*buf) ? buf + 1 : buf);
7720 if (*q != NUL)
7721 {
7722 if (remain == NULL)
7723 remain = vim_strsave(q - 1);
7724 else
7725 {
7726 cpy = vim_strnsave(q-1, STRLEN(q-1)+STRLEN(remain));
7727 if (cpy != NULL)
7728 {
7729 STRCAT(cpy, remain);
7730 vim_free(remain);
7731 remain = cpy;
7732 }
7733 }
7734 q[-1] = NUL;
7735 }
7736
7737 q = gettail(p);
7738 if (q > p && *q == NUL)
7739 {
7740 /* Ignore trailing path separator. */
7741 q[-1] = NUL;
7742 q = gettail(p);
7743 }
7744 if (q > p && !mch_isFullName(buf))
7745 {
7746 /* symlink is relative to directory of argument */
7747 cpy = alloc((unsigned)(STRLEN(p) + STRLEN(buf) + 1));
7748 if (cpy != NULL)
7749 {
7750 STRCPY(cpy, p);
7751 STRCPY(gettail(cpy), buf);
7752 vim_free(p);
7753 p = cpy;
7754 }
7755 }
7756 else
7757 {
7758 vim_free(p);
7759 p = vim_strsave(buf);
7760 }
7761 }
7762
7763 if (remain == NULL)
7764 break;
7765
7766 /* Append the first path component of "remain" to "p". */
7767 q = getnextcomp(remain + 1);
7768 len = q - remain - (*q != NUL);
7769 cpy = vim_strnsave(p, STRLEN(p) + len);
7770 if (cpy != NULL)
7771 {
7772 STRNCAT(cpy, remain, len);
7773 vim_free(p);
7774 p = cpy;
7775 }
7776 /* Shorten "remain". */
7777 if (*q != NUL)
7778 STRCPY(remain, q - 1);
7779 else
7780 {
7781 vim_free(remain);
7782 remain = NULL;
7783 }
7784 }
7785
7786 /* If the result is a relative path name, make it explicitly relative to
7787 * the current directory if and only if the argument had this form. */
7788 if (!vim_ispathsep(*p))
7789 {
7790 if (is_relative_to_current
7791 && *p != NUL
7792 && !(p[0] == '.'
7793 && (p[1] == NUL
7794 || vim_ispathsep(p[1])
7795 || (p[1] == '.'
7796 && (p[2] == NUL
7797 || vim_ispathsep(p[2]))))))
7798 {
7799 /* Prepend "./". */
7800 cpy = vim_strnsave((char_u *)"./", 2 + STRLEN(p));
7801 if (cpy != NULL)
7802 {
7803 STRCAT(cpy, p);
7804 vim_free(p);
7805 p = cpy;
7806 }
7807 }
7808 else if (!is_relative_to_current)
7809 {
7810 /* Strip leading "./". */
7811 q = p;
7812 while (q[0] == '.' && vim_ispathsep(q[1]))
7813 q += 2;
7814 if (q > p)
7815 mch_memmove(p, p + 2, STRLEN(p + 2) + (size_t)1);
7816 }
7817 }
7818
7819 /* Ensure that the result will have no trailing path separator
7820 * if the argument had none. But keep "/" or "//". */
7821 if (!has_trailing_pathsep)
7822 {
7823 q = p + STRLEN(p);
Bram Moolenaar1cd871b2004-12-19 22:46:22 +00007824 if (after_pathsep(p, q))
7825 *gettail_sep(p) = NUL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007826 }
7827
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007828 rettv->vval.v_string = p;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007829 }
7830# else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007831 rettv->vval.v_string = vim_strsave(p);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007832# endif
7833#endif
7834
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007835 simplify_filename(rettv->vval.v_string);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007836
7837#ifdef HAVE_READLINK
7838fail:
7839#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007840 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007841}
7842
7843/*
7844 * "simplify()" function
7845 */
7846 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007847f_simplify(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007848 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007849 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007850{
7851 char_u *p;
7852
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007853 p = get_tv_string(&argvars[0]);
7854 rettv->vval.v_string = vim_strsave(p);
7855 simplify_filename(rettv->vval.v_string); /* simplify in place */
7856 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007857}
7858
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00007859#define SP_NOMOVE 1 /* don't move cursor */
7860#define SP_REPEAT 2 /* repeat to find outer pair */
7861#define SP_RETCOUNT 4 /* return matchcount */
7862
Bram Moolenaar071d4272004-06-13 20:20:40 +00007863/*
7864 * "search()" function
7865 */
7866 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007867f_search(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007868 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007869 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007870{
7871 char_u *pat;
7872 pos_T pos;
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00007873 pos_T save_cursor;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007874 int save_p_ws = p_ws;
7875 int dir;
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00007876 int flags = 0;
7877
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007878 rettv->vval.v_number = 0; /* default: FAIL */
Bram Moolenaar071d4272004-06-13 20:20:40 +00007879
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007880 pat = get_tv_string(&argvars[0]);
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00007881 dir = get_search_arg(&argvars[1], &flags); /* may set p_ws */
7882 if (dir == 0)
7883 goto theend;
7884 if ((flags & ~SP_NOMOVE) != 0)
7885 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007886 EMSG2(_(e_invarg2), get_tv_string(&argvars[1]));
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00007887 goto theend;
7888 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00007889
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00007890 pos = save_cursor = curwin->w_cursor;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007891 if (searchit(curwin, curbuf, &pos, dir, pat, 1L,
7892 SEARCH_KEEP, RE_SEARCH) != FAIL)
7893 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007894 rettv->vval.v_number = pos.lnum;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007895 curwin->w_cursor = pos;
7896 /* "/$" will put the cursor after the end of the line, may need to
7897 * correct that here */
7898 check_cursor();
7899 }
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00007900
7901 /* If 'n' flag is used: restore cursor position. */
7902 if (flags & SP_NOMOVE)
7903 curwin->w_cursor = save_cursor;
7904theend:
Bram Moolenaar071d4272004-06-13 20:20:40 +00007905 p_ws = save_p_ws;
7906}
7907
Bram Moolenaar071d4272004-06-13 20:20:40 +00007908/*
7909 * "searchpair()" function
7910 */
7911 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007912f_searchpair(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007913 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007914 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007915{
7916 char_u *spat, *mpat, *epat;
7917 char_u *skip;
7918 char_u *pat, *pat2, *pat3;
7919 pos_T pos;
7920 pos_T firstpos;
7921 pos_T save_cursor;
7922 pos_T save_pos;
7923 int save_p_ws = p_ws;
7924 char_u *save_cpo;
7925 int dir;
7926 int flags = 0;
7927 char_u nbuf1[NUMBUFLEN];
7928 char_u nbuf2[NUMBUFLEN];
7929 char_u nbuf3[NUMBUFLEN];
7930 int n;
7931 int r;
7932 int nest = 1;
7933 int err;
7934
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007935 rettv->vval.v_number = 0; /* default: FAIL */
Bram Moolenaar071d4272004-06-13 20:20:40 +00007936
7937 /* Make 'cpoptions' empty, the 'l' flag should not be used here. */
7938 save_cpo = p_cpo;
7939 p_cpo = (char_u *)"";
7940
7941 /* Get the three pattern arguments: start, middle, end. */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007942 spat = get_tv_string(&argvars[0]);
7943 mpat = get_tv_string_buf(&argvars[1], nbuf1);
7944 epat = get_tv_string_buf(&argvars[2], nbuf2);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007945
7946 /* Make two search patterns: start/end (pat2, for in nested pairs) and
7947 * start/middle/end (pat3, for the top pair). */
7948 pat2 = alloc((unsigned)(STRLEN(spat) + STRLEN(epat) + 15));
7949 pat3 = alloc((unsigned)(STRLEN(spat) + STRLEN(mpat) + STRLEN(epat) + 23));
7950 if (pat2 == NULL || pat3 == NULL)
7951 goto theend;
7952 sprintf((char *)pat2, "\\(%s\\m\\)\\|\\(%s\\m\\)", spat, epat);
7953 if (*mpat == NUL)
7954 STRCPY(pat3, pat2);
7955 else
7956 sprintf((char *)pat3, "\\(%s\\m\\)\\|\\(%s\\m\\)\\|\\(%s\\m\\)",
7957 spat, epat, mpat);
7958
7959 /* Handle the optional fourth argument: flags */
7960 dir = get_search_arg(&argvars[3], &flags); /* may set p_ws */
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00007961 if (dir == 0)
7962 goto theend;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007963
7964 /* Optional fifth argument: skip expresion */
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007965 if (argvars[3].v_type == VAR_UNKNOWN
7966 || argvars[4].v_type == VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007967 skip = (char_u *)"";
7968 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007969 skip = get_tv_string_buf(&argvars[4], nbuf3);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007970
7971 save_cursor = curwin->w_cursor;
7972 pos = curwin->w_cursor;
7973 firstpos.lnum = 0;
7974 pat = pat3;
7975 for (;;)
7976 {
7977 n = searchit(curwin, curbuf, &pos, dir, pat, 1L,
7978 SEARCH_KEEP, RE_SEARCH);
7979 if (n == FAIL || (firstpos.lnum != 0 && equalpos(pos, firstpos)))
7980 /* didn't find it or found the first match again: FAIL */
7981 break;
7982
7983 if (firstpos.lnum == 0)
7984 firstpos = pos;
7985
7986 /* If the skip pattern matches, ignore this match. */
7987 if (*skip != NUL)
7988 {
7989 save_pos = curwin->w_cursor;
7990 curwin->w_cursor = pos;
7991 r = eval_to_bool(skip, &err, NULL, FALSE);
7992 curwin->w_cursor = save_pos;
7993 if (err)
7994 {
7995 /* Evaluating {skip} caused an error, break here. */
7996 curwin->w_cursor = save_cursor;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007997 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007998 break;
7999 }
8000 if (r)
8001 continue;
8002 }
8003
8004 if ((dir == BACKWARD && n == 3) || (dir == FORWARD && n == 2))
8005 {
8006 /* Found end when searching backwards or start when searching
8007 * forward: nested pair. */
8008 ++nest;
8009 pat = pat2; /* nested, don't search for middle */
8010 }
8011 else
8012 {
8013 /* Found end when searching forward or start when searching
8014 * backward: end of (nested) pair; or found middle in outer pair. */
8015 if (--nest == 1)
8016 pat = pat3; /* outer level, search for middle */
8017 }
8018
8019 if (nest == 0)
8020 {
8021 /* Found the match: return matchcount or line number. */
8022 if (flags & SP_RETCOUNT)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008023 ++rettv->vval.v_number;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008024 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008025 rettv->vval.v_number = pos.lnum;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008026 curwin->w_cursor = pos;
8027 if (!(flags & SP_REPEAT))
8028 break;
8029 nest = 1; /* search for next unmatched */
8030 }
8031 }
8032
8033 /* If 'n' flag is used or search failed: restore cursor position. */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008034 if ((flags & SP_NOMOVE) || rettv->vval.v_number == 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008035 curwin->w_cursor = save_cursor;
8036
8037theend:
8038 vim_free(pat2);
8039 vim_free(pat3);
8040 p_ws = save_p_ws;
8041 p_cpo = save_cpo;
8042}
8043
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00008044/*
8045 * Get flags for a search function.
8046 * Possibly sets "p_ws".
8047 * Returns BACKWARD, FORWARD or zero (for an error).
8048 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00008049 static int
8050get_search_arg(varp, flagsp)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008051 typeval *varp;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008052 int *flagsp;
8053{
8054 int dir = FORWARD;
8055 char_u *flags;
8056 char_u nbuf[NUMBUFLEN];
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00008057 int mask;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008058
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008059 if (varp->v_type != VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008060 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008061 flags = get_tv_string_buf(varp, nbuf);
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00008062 while (*flags != NUL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008063 {
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00008064 switch (*flags)
8065 {
8066 case 'b': dir = BACKWARD; break;
8067 case 'w': p_ws = TRUE; break;
8068 case 'W': p_ws = FALSE; break;
8069 default: mask = 0;
8070 if (flagsp != NULL)
8071 switch (*flags)
8072 {
8073 case 'n': mask = SP_NOMOVE; break;
8074 case 'r': mask = SP_REPEAT; break;
8075 case 'm': mask = SP_RETCOUNT; break;
8076 }
8077 if (mask == 0)
8078 {
8079 EMSG2(_(e_invarg2), flags);
8080 dir = 0;
8081 }
8082 else
8083 *flagsp |= mask;
8084 }
8085 if (dir == 0)
8086 break;
8087 ++flags;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008088 }
8089 }
8090 return dir;
8091}
8092
8093/*
8094 * "setbufvar()" function
8095 */
8096/*ARGSUSED*/
8097 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008098f_setbufvar(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008099 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008100 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008101{
8102 buf_T *buf;
8103#ifdef FEAT_AUTOCMD
8104 aco_save_T aco;
8105#else
8106 buf_T *save_curbuf;
8107#endif
8108 char_u *varname, *bufvarname;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008109 typeval *varp;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008110 char_u nbuf[NUMBUFLEN];
8111
8112 if (check_restricted() || check_secure())
8113 return;
8114 ++emsg_off;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008115 buf = get_buf_tv(&argvars[0]);
8116 varname = get_tv_string(&argvars[1]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008117 varp = &argvars[2];
8118
8119 if (buf != NULL && varname != NULL && varp != NULL)
8120 {
8121 /* set curbuf to be our buf, temporarily */
8122#ifdef FEAT_AUTOCMD
8123 aucmd_prepbuf(&aco, buf);
8124#else
8125 save_curbuf = curbuf;
8126 curbuf = buf;
8127#endif
8128
8129 if (*varname == '&')
8130 {
8131 ++varname;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008132 set_option_value(varname, get_tv_number(varp),
8133 get_tv_string_buf(varp, nbuf), OPT_LOCAL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008134 }
8135 else
8136 {
8137 bufvarname = alloc((unsigned)STRLEN(varname) + 3);
8138 if (bufvarname != NULL)
8139 {
8140 STRCPY(bufvarname, "b:");
8141 STRCPY(bufvarname + 2, varname);
Bram Moolenaar1c2fda22005-01-02 11:43:19 +00008142 set_var(bufvarname, varp, TRUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008143 vim_free(bufvarname);
8144 }
8145 }
8146
8147 /* reset notion of buffer */
8148#ifdef FEAT_AUTOCMD
8149 aucmd_restbuf(&aco);
8150#else
8151 curbuf = save_curbuf;
8152#endif
8153 }
8154 --emsg_off;
8155}
8156
8157/*
8158 * "setcmdpos()" function
8159 */
8160 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008161f_setcmdpos(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008162 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008163 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008164{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008165 rettv->vval.v_number = set_cmdline_pos(
8166 (int)get_tv_number(&argvars[0]) - 1);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008167}
8168
8169/*
8170 * "setline()" function
8171 */
8172 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008173f_setline(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008174 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008175 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008176{
8177 linenr_T lnum;
8178 char_u *line;
8179
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008180 lnum = get_tv_lnum(argvars);
8181 line = get_tv_string(&argvars[1]);
8182 rettv->vval.v_number = 1; /* FAIL is default */
Bram Moolenaar071d4272004-06-13 20:20:40 +00008183
8184 if (lnum >= 1
8185 && lnum <= curbuf->b_ml.ml_line_count
8186 && u_savesub(lnum) == OK
8187 && ml_replace(lnum, line, TRUE) == OK)
8188 {
8189 changed_bytes(lnum, 0);
8190 check_cursor_col();
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008191 rettv->vval.v_number = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008192 }
8193}
8194
8195/*
8196 * "setreg()" function
8197 */
8198 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008199f_setreg(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008200 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008201 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008202{
8203 int regname;
8204 char_u *strregname;
8205 char_u *stropt;
8206 int append;
8207 char_u yank_type;
8208 long block_len;
8209
8210 block_len = -1;
8211 yank_type = MAUTO;
8212 append = FALSE;
8213
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008214 strregname = get_tv_string(argvars);
8215 rettv->vval.v_number = 1; /* FAIL is default */
Bram Moolenaar071d4272004-06-13 20:20:40 +00008216
8217 regname = (strregname == NULL ? '"' : *strregname);
8218 if (regname == 0 || regname == '@')
8219 regname = '"';
8220 else if (regname == '=')
8221 return;
8222
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008223 if (argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008224 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008225 for (stropt = get_tv_string(&argvars[2]); *stropt != NUL; ++stropt)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008226 switch (*stropt)
8227 {
8228 case 'a': case 'A': /* append */
8229 append = TRUE;
8230 break;
8231 case 'v': case 'c': /* character-wise selection */
8232 yank_type = MCHAR;
8233 break;
8234 case 'V': case 'l': /* line-wise selection */
8235 yank_type = MLINE;
8236 break;
8237#ifdef FEAT_VISUAL
8238 case 'b': case Ctrl_V: /* block-wise selection */
8239 yank_type = MBLOCK;
8240 if (VIM_ISDIGIT(stropt[1]))
8241 {
8242 ++stropt;
8243 block_len = getdigits(&stropt) - 1;
8244 --stropt;
8245 }
8246 break;
8247#endif
8248 }
8249 }
8250
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008251 write_reg_contents_ex(regname, get_tv_string(&argvars[1]), -1,
Bram Moolenaar071d4272004-06-13 20:20:40 +00008252 append, yank_type, block_len);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008253 rettv->vval.v_number = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008254}
8255
8256
8257/*
8258 * "setwinvar(expr)" function
8259 */
8260/*ARGSUSED*/
8261 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008262f_setwinvar(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008263 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008264 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008265{
8266 win_T *win;
8267#ifdef FEAT_WINDOWS
8268 win_T *save_curwin;
8269#endif
8270 char_u *varname, *winvarname;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008271 typeval *varp;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008272 char_u nbuf[NUMBUFLEN];
8273
8274 if (check_restricted() || check_secure())
8275 return;
8276 ++emsg_off;
8277 win = find_win_by_nr(&argvars[0]);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008278 varname = get_tv_string(&argvars[1]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008279 varp = &argvars[2];
8280
8281 if (win != NULL && varname != NULL && varp != NULL)
8282 {
8283#ifdef FEAT_WINDOWS
8284 /* set curwin to be our win, temporarily */
8285 save_curwin = curwin;
8286 curwin = win;
8287 curbuf = curwin->w_buffer;
8288#endif
8289
8290 if (*varname == '&')
8291 {
8292 ++varname;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008293 set_option_value(varname, get_tv_number(varp),
8294 get_tv_string_buf(varp, nbuf), OPT_LOCAL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008295 }
8296 else
8297 {
8298 winvarname = alloc((unsigned)STRLEN(varname) + 3);
8299 if (winvarname != NULL)
8300 {
8301 STRCPY(winvarname, "w:");
8302 STRCPY(winvarname + 2, varname);
Bram Moolenaar1c2fda22005-01-02 11:43:19 +00008303 set_var(winvarname, varp, TRUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008304 vim_free(winvarname);
8305 }
8306 }
8307
8308#ifdef FEAT_WINDOWS
8309 /* Restore current window, if it's still valid (autocomands can make
8310 * it invalid). */
8311 if (win_valid(save_curwin))
8312 {
8313 curwin = save_curwin;
8314 curbuf = curwin->w_buffer;
8315 }
8316#endif
8317 }
8318 --emsg_off;
8319}
8320
8321/*
8322 * "nextnonblank()" function
8323 */
8324 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008325f_nextnonblank(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008326 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008327 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008328{
8329 linenr_T lnum;
8330
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008331 for (lnum = get_tv_lnum(argvars); ; ++lnum)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008332 {
8333 if (lnum > curbuf->b_ml.ml_line_count)
8334 {
8335 lnum = 0;
8336 break;
8337 }
8338 if (*skipwhite(ml_get(lnum)) != NUL)
8339 break;
8340 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008341 rettv->vval.v_number = lnum;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008342}
8343
8344/*
8345 * "prevnonblank()" function
8346 */
8347 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008348f_prevnonblank(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008349 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008350 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008351{
8352 linenr_T lnum;
8353
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008354 lnum = get_tv_lnum(argvars);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008355 if (lnum < 1 || lnum > curbuf->b_ml.ml_line_count)
8356 lnum = 0;
8357 else
8358 while (lnum >= 1 && *skipwhite(ml_get(lnum)) == NUL)
8359 --lnum;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008360 rettv->vval.v_number = lnum;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008361}
8362
8363#if defined(FEAT_CLIENTSERVER) && defined(FEAT_X11)
8364static void make_connection __ARGS((void));
8365static int check_connection __ARGS((void));
8366
8367 static void
8368make_connection()
8369{
8370 if (X_DISPLAY == NULL
8371# ifdef FEAT_GUI
8372 && !gui.in_use
8373# endif
8374 )
8375 {
8376 x_force_connect = TRUE;
8377 setup_term_clip();
8378 x_force_connect = FALSE;
8379 }
8380}
8381
8382 static int
8383check_connection()
8384{
8385 make_connection();
8386 if (X_DISPLAY == NULL)
8387 {
8388 EMSG(_("E240: No connection to Vim server"));
8389 return FAIL;
8390 }
8391 return OK;
8392}
8393#endif
8394
8395/*ARGSUSED*/
8396 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008397f_serverlist(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008398 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008399 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008400{
8401 char_u *r = NULL;
8402
8403#ifdef FEAT_CLIENTSERVER
8404# ifdef WIN32
8405 r = serverGetVimNames();
8406# else
8407 make_connection();
8408 if (X_DISPLAY != NULL)
8409 r = serverGetVimNames(X_DISPLAY);
8410# endif
8411#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008412 rettv->v_type = VAR_STRING;
8413 rettv->vval.v_string = r;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008414}
8415
8416/*ARGSUSED*/
8417 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008418f_remote_peek(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008419 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008420 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008421{
8422#ifdef FEAT_CLIENTSERVER
8423 var v;
8424 char_u *s = NULL;
8425# ifdef WIN32
8426 int n = 0;
8427# endif
8428
8429 if (check_restricted() || check_secure())
8430 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008431 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008432 return;
8433 }
8434# ifdef WIN32
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008435 sscanf(get_tv_string(&argvars[0]), "%x", &n);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008436 if (n == 0)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008437 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008438 else
8439 {
8440 s = serverGetReply((HWND)n, FALSE, FALSE, FALSE);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008441 rettv->vval.v_number = (s != NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008442 }
8443# else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008444 rettv->vval.v_number = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008445 if (check_connection() == FAIL)
8446 return;
8447
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008448 rettv->vval.v_number = serverPeekReply(X_DISPLAY,
8449 serverStrToWin(get_tv_string(&argvars[0])), &s);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008450# endif
8451
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008452 if (argvars[1].v_type != VAR_UNKNOWN && rettv->vval.v_number > 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008453 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008454 v.tv.v_type = VAR_STRING;
8455 v.tv.vval.v_string = vim_strsave(s);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008456 set_var(get_tv_string(&argvars[1]), &v.tv, FALSE);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008457 vim_free(v.tv.vval.v_string);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008458 }
8459#else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008460 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008461#endif
8462}
8463
8464/*ARGSUSED*/
8465 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008466f_remote_read(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008467 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008468 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008469{
8470 char_u *r = NULL;
8471
8472#ifdef FEAT_CLIENTSERVER
8473 if (!check_restricted() && !check_secure())
8474 {
8475# ifdef WIN32
8476 /* The server's HWND is encoded in the 'id' parameter */
8477 int n = 0;
8478
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008479 sscanf(get_tv_string(&argvars[0]), "%x", &n);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008480 if (n != 0)
8481 r = serverGetReply((HWND)n, FALSE, TRUE, TRUE);
8482 if (r == NULL)
8483# else
8484 if (check_connection() == FAIL || serverReadReply(X_DISPLAY,
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008485 serverStrToWin(get_tv_string(&argvars[0])), &r, FALSE) < 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008486# endif
8487 EMSG(_("E277: Unable to read a server reply"));
8488 }
8489#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008490 rettv->v_type = VAR_STRING;
8491 rettv->vval.v_string = r;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008492}
8493
8494/*ARGSUSED*/
8495 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008496f_server2client(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008497 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008498 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008499{
8500#ifdef FEAT_CLIENTSERVER
8501 char_u buf[NUMBUFLEN];
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008502 char_u *server = get_tv_string(&argvars[0]);
8503 char_u *reply = get_tv_string_buf(&argvars[1], buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008504
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008505 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008506 if (check_restricted() || check_secure())
8507 return;
8508# ifdef FEAT_X11
8509 if (check_connection() == FAIL)
8510 return;
8511# endif
8512
8513 if (serverSendReply(server, reply) < 0)
8514 {
8515 EMSG(_("E258: Unable to send to client"));
8516 return;
8517 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008518 rettv->vval.v_number = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008519#else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008520 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008521#endif
8522}
8523
8524#ifdef FEAT_CLIENTSERVER
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008525static void remote_common __ARGS((typeval *argvars, typeval *rettv, int expr));
Bram Moolenaar071d4272004-06-13 20:20:40 +00008526
8527 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008528remote_common(argvars, rettv, expr)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008529 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008530 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008531 int expr;
8532{
8533 char_u *server_name;
8534 char_u *keys;
8535 char_u *r = NULL;
8536 char_u buf[NUMBUFLEN];
8537# ifdef WIN32
8538 HWND w;
8539# else
8540 Window w;
8541# endif
8542
8543 if (check_restricted() || check_secure())
8544 return;
8545
8546# ifdef FEAT_X11
8547 if (check_connection() == FAIL)
8548 return;
8549# endif
8550
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008551 server_name = get_tv_string(&argvars[0]);
8552 keys = get_tv_string_buf(&argvars[1], buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008553# ifdef WIN32
8554 if (serverSendToVim(server_name, keys, &r, &w, expr, TRUE) < 0)
8555# else
8556 if (serverSendToVim(X_DISPLAY, server_name, keys, &r, &w, expr, 0, TRUE)
8557 < 0)
8558# endif
8559 {
8560 if (r != NULL)
8561 EMSG(r); /* sending worked but evaluation failed */
8562 else
8563 EMSG2(_("E241: Unable to send to %s"), server_name);
8564 return;
8565 }
8566
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008567 rettv->vval.v_string = r;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008568
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008569 if (argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008570 {
8571 var v;
8572 char_u str[30];
8573
8574 sprintf((char *)str, "0x%x", (unsigned int)w);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008575 v.tv.v_type = VAR_STRING;
8576 v.tv.vval.v_string = vim_strsave(str);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008577 set_var(get_tv_string(&argvars[2]), &v.tv, FALSE);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008578 vim_free(v.tv.vval.v_string);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008579 }
8580}
8581#endif
8582
8583/*
8584 * "remote_expr()" function
8585 */
8586/*ARGSUSED*/
8587 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008588f_remote_expr(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008589 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008590 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008591{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008592 rettv->v_type = VAR_STRING;
8593 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008594#ifdef FEAT_CLIENTSERVER
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008595 remote_common(argvars, rettv, TRUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008596#endif
8597}
8598
8599/*
8600 * "remote_send()" function
8601 */
8602/*ARGSUSED*/
8603 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008604f_remote_send(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008605 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008606 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008607{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008608 rettv->v_type = VAR_STRING;
8609 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008610#ifdef FEAT_CLIENTSERVER
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008611 remote_common(argvars, rettv, FALSE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008612#endif
8613}
8614
8615/*
8616 * "remote_foreground()" function
8617 */
8618/*ARGSUSED*/
8619 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008620f_remote_foreground(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008621 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008622 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008623{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008624 rettv->vval.v_number = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008625#ifdef FEAT_CLIENTSERVER
8626# ifdef WIN32
8627 /* On Win32 it's done in this application. */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008628 serverForeground(get_tv_string(&argvars[0]));
Bram Moolenaar071d4272004-06-13 20:20:40 +00008629# else
8630 /* Send a foreground() expression to the server. */
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008631 argvars[1].v_type = VAR_STRING;
8632 argvars[1].vval.v_string = vim_strsave((char_u *)"foreground()");
8633 argvars[2].v_type = VAR_UNKNOWN;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008634 remote_common(argvars, rettv, TRUE);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008635 vim_free(argvars[1].vval.v_string);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008636# endif
8637#endif
8638}
8639
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00008640/*
8641 * "repeat()" function
8642 */
8643/*ARGSUSED*/
8644 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008645f_repeat(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008646 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008647 typeval *rettv;
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00008648{
8649 char_u *p;
8650 int n;
8651 int slen;
8652 int len;
8653 char_u *r;
8654 int i;
8655
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008656 p = get_tv_string(&argvars[0]);
8657 n = get_tv_number(&argvars[1]);
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00008658
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008659 rettv->v_type = VAR_STRING;
8660 rettv->vval.v_string = NULL;
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00008661
8662 slen = (int)STRLEN(p);
8663 len = slen * n;
8664
8665 if (len <= 0)
8666 return;
8667
8668 r = alloc(len + 1);
8669 if (r != NULL)
8670 {
8671 for (i = 0; i < n; i++)
8672 mch_memmove(r + i * slen, p, (size_t)slen);
8673 r[len] = NUL;
8674 }
8675
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008676 rettv->vval.v_string = r;
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00008677}
8678
Bram Moolenaar071d4272004-06-13 20:20:40 +00008679#ifdef HAVE_STRFTIME
8680/*
8681 * "strftime({format}[, {time}])" function
8682 */
8683 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008684f_strftime(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008685 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008686 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008687{
8688 char_u result_buf[256];
8689 struct tm *curtime;
8690 time_t seconds;
8691 char_u *p;
8692
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008693 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008694
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008695 p = get_tv_string(&argvars[0]);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008696 if (argvars[1].v_type == VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008697 seconds = time(NULL);
8698 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008699 seconds = (time_t)get_tv_number(&argvars[1]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008700 curtime = localtime(&seconds);
8701 /* MSVC returns NULL for an invalid value of seconds. */
8702 if (curtime == NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008703 rettv->vval.v_string = vim_strsave((char_u *)_("(Invalid)"));
Bram Moolenaar071d4272004-06-13 20:20:40 +00008704 else
8705 {
8706# ifdef FEAT_MBYTE
8707 vimconv_T conv;
8708 char_u *enc;
8709
8710 conv.vc_type = CONV_NONE;
8711 enc = enc_locale();
8712 convert_setup(&conv, p_enc, enc);
8713 if (conv.vc_type != CONV_NONE)
8714 p = string_convert(&conv, p, NULL);
8715# endif
8716 if (p != NULL)
8717 (void)strftime((char *)result_buf, sizeof(result_buf),
8718 (char *)p, curtime);
8719 else
8720 result_buf[0] = NUL;
8721
8722# ifdef FEAT_MBYTE
8723 if (conv.vc_type != CONV_NONE)
8724 vim_free(p);
8725 convert_setup(&conv, enc, p_enc);
8726 if (conv.vc_type != CONV_NONE)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008727 rettv->vval.v_string = string_convert(&conv, result_buf, NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008728 else
8729# endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008730 rettv->vval.v_string = vim_strsave(result_buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008731
8732# ifdef FEAT_MBYTE
8733 /* Release conversion descriptors */
8734 convert_setup(&conv, NULL, NULL);
8735 vim_free(enc);
8736# endif
8737 }
8738}
8739#endif
8740
8741/*
8742 * "stridx()" function
8743 */
8744 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008745f_stridx(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008746 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008747 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008748{
8749 char_u buf[NUMBUFLEN];
8750 char_u *needle;
8751 char_u *haystack;
8752 char_u *pos;
8753
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008754 needle = get_tv_string(&argvars[1]);
8755 haystack = get_tv_string_buf(&argvars[0], buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008756 pos = (char_u *)strstr((char *)haystack, (char *)needle);
8757
8758 if (pos == NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008759 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008760 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008761 rettv->vval.v_number = (varnumber_T) (pos - haystack);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008762}
8763
8764/*
8765 * "strridx()" function
8766 */
8767 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008768f_strridx(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008769 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008770 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008771{
8772 char_u buf[NUMBUFLEN];
8773 char_u *needle;
8774 char_u *haystack;
8775 char_u *rest;
8776 char_u *lastmatch = NULL;
8777
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008778 needle = get_tv_string(&argvars[1]);
8779 haystack = get_tv_string_buf(&argvars[0], buf);
Bram Moolenaard4755bb2004-09-02 19:12:26 +00008780 if (*needle == NUL)
8781 /* Empty string matches past the end. */
8782 lastmatch = haystack + STRLEN(haystack);
8783 else
8784 for (rest = haystack; *rest != '\0'; ++rest)
8785 {
8786 rest = (char_u *)strstr((char *)rest, (char *)needle);
8787 if (rest == NULL)
8788 break;
8789 lastmatch = rest;
8790 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00008791
8792 if (lastmatch == NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008793 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008794 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008795 rettv->vval.v_number = (varnumber_T)(lastmatch - haystack);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008796}
8797
8798/*
8799 * "string()" function
8800 */
8801 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008802f_string(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008803 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008804 typeval *rettv;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008805{
8806 char_u *tofree;
8807
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008808 rettv->v_type = VAR_STRING;
8809 rettv->vval.v_string = tv2string(&argvars[0], &tofree);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008810 if (tofree == NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008811 rettv->vval.v_string = vim_strsave(rettv->vval.v_string);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008812}
8813
8814/*
8815 * "strlen()" function
8816 */
8817 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008818f_strlen(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008819 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008820 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008821{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008822 rettv->vval.v_number = (varnumber_T)(STRLEN(
8823 get_tv_string(&argvars[0])));
Bram Moolenaar071d4272004-06-13 20:20:40 +00008824}
8825
8826/*
8827 * "strpart()" function
8828 */
8829 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008830f_strpart(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008831 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008832 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008833{
8834 char_u *p;
8835 int n;
8836 int len;
8837 int slen;
8838
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008839 p = get_tv_string(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008840 slen = (int)STRLEN(p);
8841
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008842 n = get_tv_number(&argvars[1]);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008843 if (argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008844 len = get_tv_number(&argvars[2]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008845 else
8846 len = slen - n; /* default len: all bytes that are available. */
8847
8848 /*
8849 * Only return the overlap between the specified part and the actual
8850 * string.
8851 */
8852 if (n < 0)
8853 {
8854 len += n;
8855 n = 0;
8856 }
8857 else if (n > slen)
8858 n = slen;
8859 if (len < 0)
8860 len = 0;
8861 else if (n + len > slen)
8862 len = slen - n;
8863
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008864 rettv->v_type = VAR_STRING;
8865 rettv->vval.v_string = vim_strnsave(p + n, len);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008866}
8867
8868/*
8869 * "strtrans()" function
8870 */
8871 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008872f_strtrans(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008873 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008874 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008875{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008876 rettv->v_type = VAR_STRING;
8877 rettv->vval.v_string = transstr(get_tv_string(&argvars[0]));
Bram Moolenaar071d4272004-06-13 20:20:40 +00008878}
8879
8880/*
8881 * "synID(line, col, trans)" function
8882 */
8883/*ARGSUSED*/
8884 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008885f_synID(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008886 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008887 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008888{
8889 int id = 0;
8890#ifdef FEAT_SYN_HL
8891 long line;
8892 long col;
8893 int trans;
8894
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008895 line = get_tv_lnum(argvars);
8896 col = get_tv_number(&argvars[1]) - 1;
8897 trans = get_tv_number(&argvars[2]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008898
8899 if (line >= 1 && line <= curbuf->b_ml.ml_line_count
8900 && col >= 0 && col < (long)STRLEN(ml_get(line)))
8901 id = syn_get_id(line, col, trans);
8902#endif
8903
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008904 rettv->vval.v_number = id;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008905}
8906
8907/*
8908 * "synIDattr(id, what [, mode])" function
8909 */
8910/*ARGSUSED*/
8911 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008912f_synIDattr(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008913 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008914 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008915{
8916 char_u *p = NULL;
8917#ifdef FEAT_SYN_HL
8918 int id;
8919 char_u *what;
8920 char_u *mode;
8921 char_u modebuf[NUMBUFLEN];
8922 int modec;
8923
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008924 id = get_tv_number(&argvars[0]);
8925 what = get_tv_string(&argvars[1]);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008926 if (argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008927 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008928 mode = get_tv_string_buf(&argvars[2], modebuf);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008929 modec = TOLOWER_ASC(mode[0]);
8930 if (modec != 't' && modec != 'c'
8931#ifdef FEAT_GUI
8932 && modec != 'g'
8933#endif
8934 )
8935 modec = 0; /* replace invalid with current */
8936 }
8937 else
8938 {
8939#ifdef FEAT_GUI
8940 if (gui.in_use)
8941 modec = 'g';
8942 else
8943#endif
8944 if (t_colors > 1)
8945 modec = 'c';
8946 else
8947 modec = 't';
8948 }
8949
8950
8951 switch (TOLOWER_ASC(what[0]))
8952 {
8953 case 'b':
8954 if (TOLOWER_ASC(what[1]) == 'g') /* bg[#] */
8955 p = highlight_color(id, what, modec);
8956 else /* bold */
8957 p = highlight_has_attr(id, HL_BOLD, modec);
8958 break;
8959
8960 case 'f': /* fg[#] */
8961 p = highlight_color(id, what, modec);
8962 break;
8963
8964 case 'i':
8965 if (TOLOWER_ASC(what[1]) == 'n') /* inverse */
8966 p = highlight_has_attr(id, HL_INVERSE, modec);
8967 else /* italic */
8968 p = highlight_has_attr(id, HL_ITALIC, modec);
8969 break;
8970
8971 case 'n': /* name */
8972 p = get_highlight_name(NULL, id - 1);
8973 break;
8974
8975 case 'r': /* reverse */
8976 p = highlight_has_attr(id, HL_INVERSE, modec);
8977 break;
8978
8979 case 's': /* standout */
8980 p = highlight_has_attr(id, HL_STANDOUT, modec);
8981 break;
8982
8983 case 'u': /* underline */
8984 p = highlight_has_attr(id, HL_UNDERLINE, modec);
8985 break;
8986 }
8987
8988 if (p != NULL)
8989 p = vim_strsave(p);
8990#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008991 rettv->v_type = VAR_STRING;
8992 rettv->vval.v_string = p;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008993}
8994
8995/*
8996 * "synIDtrans(id)" function
8997 */
8998/*ARGSUSED*/
8999 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009000f_synIDtrans(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009001 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009002 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009003{
9004 int id;
9005
9006#ifdef FEAT_SYN_HL
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009007 id = get_tv_number(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009008
9009 if (id > 0)
9010 id = syn_get_final_id(id);
9011 else
9012#endif
9013 id = 0;
9014
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009015 rettv->vval.v_number = id;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009016}
9017
9018/*
9019 * "system()" function
9020 */
9021 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009022f_system(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009023 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009024 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009025{
Bram Moolenaarc0197e22004-09-13 20:26:32 +00009026 char_u *res = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009027 char_u *p;
Bram Moolenaarc0197e22004-09-13 20:26:32 +00009028 char_u *infile = NULL;
9029 char_u buf[NUMBUFLEN];
9030 int err = FALSE;
9031 FILE *fd;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009032
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009033 if (argvars[1].v_type != VAR_UNKNOWN)
Bram Moolenaarc0197e22004-09-13 20:26:32 +00009034 {
9035 /*
9036 * Write the string to a temp file, to be used for input of the shell
9037 * command.
9038 */
9039 if ((infile = vim_tempname('i')) == NULL)
9040 {
9041 EMSG(_(e_notmp));
9042 return;
9043 }
9044
9045 fd = mch_fopen((char *)infile, WRITEBIN);
9046 if (fd == NULL)
9047 {
9048 EMSG2(_(e_notopen), infile);
9049 goto done;
9050 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009051 p = get_tv_string_buf(&argvars[1], buf);
Bram Moolenaarc0197e22004-09-13 20:26:32 +00009052 if (fwrite(p, STRLEN(p), 1, fd) != 1)
9053 err = TRUE;
9054 if (fclose(fd) != 0)
9055 err = TRUE;
9056 if (err)
9057 {
9058 EMSG(_("E677: Error writing temp file"));
9059 goto done;
9060 }
9061 }
9062
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009063 res = get_cmd_output(get_tv_string(&argvars[0]), infile, SHELL_SILENT);
Bram Moolenaarc0197e22004-09-13 20:26:32 +00009064
Bram Moolenaar071d4272004-06-13 20:20:40 +00009065#ifdef USE_CR
9066 /* translate <CR> into <NL> */
Bram Moolenaarc0197e22004-09-13 20:26:32 +00009067 if (res != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009068 {
9069 char_u *s;
9070
Bram Moolenaarc0197e22004-09-13 20:26:32 +00009071 for (s = res; *s; ++s)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009072 {
9073 if (*s == CAR)
9074 *s = NL;
9075 }
9076 }
9077#else
9078# ifdef USE_CRNL
9079 /* translate <CR><NL> into <NL> */
Bram Moolenaarc0197e22004-09-13 20:26:32 +00009080 if (res != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009081 {
9082 char_u *s, *d;
9083
Bram Moolenaarc0197e22004-09-13 20:26:32 +00009084 d = res;
9085 for (s = res; *s; ++s)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009086 {
9087 if (s[0] == CAR && s[1] == NL)
9088 ++s;
9089 *d++ = *s;
9090 }
9091 *d = NUL;
9092 }
9093# endif
9094#endif
Bram Moolenaarc0197e22004-09-13 20:26:32 +00009095
9096done:
9097 if (infile != NULL)
9098 {
9099 mch_remove(infile);
9100 vim_free(infile);
9101 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009102 rettv->v_type = VAR_STRING;
9103 rettv->vval.v_string = res;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009104}
9105
9106/*
9107 * "submatch()" function
9108 */
9109 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009110f_submatch(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009111 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009112 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009113{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009114 rettv->v_type = VAR_STRING;
9115 rettv->vval.v_string = reg_submatch((int)get_tv_number(&argvars[0]));
Bram Moolenaar071d4272004-06-13 20:20:40 +00009116}
9117
9118/*
9119 * "substitute()" function
9120 */
9121 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009122f_substitute(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009123 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009124 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009125{
9126 char_u patbuf[NUMBUFLEN];
9127 char_u subbuf[NUMBUFLEN];
9128 char_u flagsbuf[NUMBUFLEN];
9129
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009130 rettv->v_type = VAR_STRING;
9131 rettv->vval.v_string = do_string_sub(
9132 get_tv_string(&argvars[0]),
9133 get_tv_string_buf(&argvars[1], patbuf),
9134 get_tv_string_buf(&argvars[2], subbuf),
9135 get_tv_string_buf(&argvars[3], flagsbuf));
Bram Moolenaar071d4272004-06-13 20:20:40 +00009136}
9137
9138/*
9139 * "tempname()" function
9140 */
9141/*ARGSUSED*/
9142 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009143f_tempname(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009144 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009145 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009146{
9147 static int x = 'A';
9148
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009149 rettv->v_type = VAR_STRING;
9150 rettv->vval.v_string = vim_tempname(x);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009151
9152 /* Advance 'x' to use A-Z and 0-9, so that there are at least 34 different
9153 * names. Skip 'I' and 'O', they are used for shell redirection. */
9154 do
9155 {
9156 if (x == 'Z')
9157 x = '0';
9158 else if (x == '9')
9159 x = 'A';
9160 else
9161 {
9162#ifdef EBCDIC
9163 if (x == 'I')
9164 x = 'J';
9165 else if (x == 'R')
9166 x = 'S';
9167 else
9168#endif
9169 ++x;
9170 }
9171 } while (x == 'I' || x == 'O');
9172}
9173
9174/*
9175 * "tolower(string)" function
9176 */
9177 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009178f_tolower(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009179 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009180 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009181{
9182 char_u *p;
9183
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009184 p = vim_strsave(get_tv_string(&argvars[0]));
9185 rettv->v_type = VAR_STRING;
9186 rettv->vval.v_string = p;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009187
9188 if (p != NULL)
9189 while (*p != NUL)
9190 {
9191#ifdef FEAT_MBYTE
9192 int l;
9193
9194 if (enc_utf8)
9195 {
9196 int c, lc;
9197
9198 c = utf_ptr2char(p);
9199 lc = utf_tolower(c);
9200 l = utf_ptr2len_check(p);
9201 /* TODO: reallocate string when byte count changes. */
9202 if (utf_char2len(lc) == l)
9203 utf_char2bytes(lc, p);
9204 p += l;
9205 }
9206 else if (has_mbyte && (l = (*mb_ptr2len_check)(p)) > 1)
9207 p += l; /* skip multi-byte character */
9208 else
9209#endif
9210 {
9211 *p = TOLOWER_LOC(*p); /* note that tolower() can be a macro */
9212 ++p;
9213 }
9214 }
9215}
9216
9217/*
9218 * "toupper(string)" function
9219 */
9220 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009221f_toupper(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009222 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009223 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009224{
9225 char_u *p;
9226
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009227 p = vim_strsave(get_tv_string(&argvars[0]));
9228 rettv->v_type = VAR_STRING;
9229 rettv->vval.v_string = p;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009230
9231 if (p != NULL)
9232 while (*p != NUL)
9233 {
9234#ifdef FEAT_MBYTE
9235 int l;
9236
9237 if (enc_utf8)
9238 {
9239 int c, uc;
9240
9241 c = utf_ptr2char(p);
9242 uc = utf_toupper(c);
9243 l = utf_ptr2len_check(p);
9244 /* TODO: reallocate string when byte count changes. */
9245 if (utf_char2len(uc) == l)
9246 utf_char2bytes(uc, p);
9247 p += l;
9248 }
9249 else if (has_mbyte && (l = (*mb_ptr2len_check)(p)) > 1)
9250 p += l; /* skip multi-byte character */
9251 else
9252#endif
9253 {
9254 *p = TOUPPER_LOC(*p); /* note that toupper() can be a macro */
9255 p++;
9256 }
9257 }
9258}
9259
9260/*
Bram Moolenaar8299df92004-07-10 09:47:34 +00009261 * "tr(string, fromstr, tostr)" function
9262 */
9263 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009264f_tr(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009265 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009266 typeval *rettv;
Bram Moolenaar8299df92004-07-10 09:47:34 +00009267{
9268 char_u *instr;
9269 char_u *fromstr;
9270 char_u *tostr;
9271 char_u *p;
9272#ifdef FEAT_MBYTE
9273 int inlen;
9274 int fromlen;
9275 int tolen;
9276 int idx;
9277 char_u *cpstr;
9278 int cplen;
9279 int first = TRUE;
9280#endif
9281 char_u buf[NUMBUFLEN];
9282 char_u buf2[NUMBUFLEN];
9283 garray_T ga;
9284
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009285 instr = get_tv_string(&argvars[0]);
9286 fromstr = get_tv_string_buf(&argvars[1], buf);
9287 tostr = get_tv_string_buf(&argvars[2], buf2);
Bram Moolenaar8299df92004-07-10 09:47:34 +00009288
9289 /* Default return value: empty string. */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009290 rettv->v_type = VAR_STRING;
9291 rettv->vval.v_string = NULL;
Bram Moolenaar8299df92004-07-10 09:47:34 +00009292 ga_init2(&ga, (int)sizeof(char), 80);
9293
9294#ifdef FEAT_MBYTE
9295 if (!has_mbyte)
9296#endif
9297 /* not multi-byte: fromstr and tostr must be the same length */
9298 if (STRLEN(fromstr) != STRLEN(tostr))
9299 {
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00009300#ifdef FEAT_MBYTE
Bram Moolenaar8299df92004-07-10 09:47:34 +00009301error:
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00009302#endif
Bram Moolenaar8299df92004-07-10 09:47:34 +00009303 EMSG2(_(e_invarg2), fromstr);
9304 ga_clear(&ga);
9305 return;
9306 }
9307
9308 /* fromstr and tostr have to contain the same number of chars */
9309 while (*instr != NUL)
9310 {
9311#ifdef FEAT_MBYTE
9312 if (has_mbyte)
9313 {
9314 inlen = mb_ptr2len_check(instr);
9315 cpstr = instr;
9316 cplen = inlen;
9317 idx = 0;
9318 for (p = fromstr; *p != NUL; p += fromlen)
9319 {
9320 fromlen = mb_ptr2len_check(p);
9321 if (fromlen == inlen && STRNCMP(instr, p, inlen) == 0)
9322 {
9323 for (p = tostr; *p != NUL; p += tolen)
9324 {
9325 tolen = mb_ptr2len_check(p);
9326 if (idx-- == 0)
9327 {
9328 cplen = tolen;
9329 cpstr = p;
9330 break;
9331 }
9332 }
9333 if (*p == NUL) /* tostr is shorter than fromstr */
9334 goto error;
9335 break;
9336 }
9337 ++idx;
9338 }
9339
9340 if (first && cpstr == instr)
9341 {
9342 /* Check that fromstr and tostr have the same number of
9343 * (multi-byte) characters. Done only once when a character
9344 * of instr doesn't appear in fromstr. */
9345 first = FALSE;
9346 for (p = tostr; *p != NUL; p += tolen)
9347 {
9348 tolen = mb_ptr2len_check(p);
9349 --idx;
9350 }
9351 if (idx != 0)
9352 goto error;
9353 }
9354
9355 ga_grow(&ga, cplen);
Bram Moolenaar2df6dcc2004-07-12 15:53:54 +00009356 mch_memmove((char *)ga.ga_data + ga.ga_len, cpstr, (size_t)cplen);
Bram Moolenaar8299df92004-07-10 09:47:34 +00009357 ga.ga_len += cplen;
Bram Moolenaar8299df92004-07-10 09:47:34 +00009358
9359 instr += inlen;
9360 }
9361 else
9362#endif
9363 {
9364 /* When not using multi-byte chars we can do it faster. */
9365 p = vim_strchr(fromstr, *instr);
9366 if (p != NULL)
9367 ga_append(&ga, tostr[p - fromstr]);
9368 else
9369 ga_append(&ga, *instr);
9370 ++instr;
9371 }
9372 }
9373
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009374 rettv->vval.v_string = ga.ga_data;
Bram Moolenaar8299df92004-07-10 09:47:34 +00009375}
9376
9377/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00009378 * "type(expr)" function
9379 */
9380 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009381f_type(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009382 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009383 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009384{
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009385 if (argvars[0].v_type == VAR_NUMBER)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009386 rettv->vval.v_number = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009387 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009388 rettv->vval.v_number = 1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009389}
9390
9391/*
9392 * "virtcol(string)" function
9393 */
9394 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009395f_virtcol(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009396 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009397 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009398{
9399 colnr_T vcol = 0;
9400 pos_T *fp;
9401
9402 fp = var2fpos(&argvars[0], FALSE);
9403 if (fp != NULL && fp->lnum <= curbuf->b_ml.ml_line_count)
9404 {
9405 getvvcol(curwin, fp, NULL, NULL, &vcol);
9406 ++vcol;
9407 }
9408
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009409 rettv->vval.v_number = vcol;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009410}
9411
9412/*
9413 * "visualmode()" function
9414 */
9415/*ARGSUSED*/
9416 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009417f_visualmode(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009418 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009419 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009420{
9421#ifdef FEAT_VISUAL
9422 char_u str[2];
9423
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009424 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009425 str[0] = curbuf->b_visual_mode_eval;
9426 str[1] = NUL;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009427 rettv->vval.v_string = vim_strsave(str);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009428
9429 /* A non-zero number or non-empty string argument: reset mode. */
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009430 if ((argvars[0].v_type == VAR_NUMBER
9431 && argvars[0].vval.v_number != 0)
9432 || (argvars[0].v_type == VAR_STRING
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009433 && *get_tv_string(&argvars[0]) != NUL))
Bram Moolenaar071d4272004-06-13 20:20:40 +00009434 curbuf->b_visual_mode_eval = NUL;
9435#else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009436 rettv->vval.v_number = 0; /* return anything, it won't work anyway */
Bram Moolenaar071d4272004-06-13 20:20:40 +00009437#endif
9438}
9439
9440/*
9441 * "winbufnr(nr)" function
9442 */
9443 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009444f_winbufnr(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009445 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009446 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009447{
9448 win_T *wp;
9449
9450 wp = find_win_by_nr(&argvars[0]);
9451 if (wp == NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009452 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009453 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009454 rettv->vval.v_number = wp->w_buffer->b_fnum;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009455}
9456
9457/*
9458 * "wincol()" function
9459 */
9460/*ARGSUSED*/
9461 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009462f_wincol(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009463 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009464 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009465{
9466 validate_cursor();
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009467 rettv->vval.v_number = curwin->w_wcol + 1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009468}
9469
9470/*
9471 * "winheight(nr)" function
9472 */
9473 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009474f_winheight(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009475 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009476 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009477{
9478 win_T *wp;
9479
9480 wp = find_win_by_nr(&argvars[0]);
9481 if (wp == NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009482 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009483 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009484 rettv->vval.v_number = wp->w_height;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009485}
9486
9487/*
9488 * "winline()" function
9489 */
9490/*ARGSUSED*/
9491 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009492f_winline(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009493 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009494 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009495{
9496 validate_cursor();
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009497 rettv->vval.v_number = curwin->w_wrow + 1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009498}
9499
9500/*
9501 * "winnr()" function
9502 */
9503/* ARGSUSED */
9504 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009505f_winnr(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009506 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009507 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009508{
9509 int nr = 1;
9510#ifdef FEAT_WINDOWS
9511 win_T *wp;
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00009512 win_T *twin = curwin;
9513 char_u *arg;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009514
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009515 if (argvars[0].v_type != VAR_UNKNOWN)
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00009516 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009517 arg = get_tv_string(&argvars[0]);
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00009518 if (STRCMP(arg, "$") == 0)
9519 twin = lastwin;
9520 else if (STRCMP(arg, "#") == 0)
9521 {
9522 twin = prevwin;
9523 if (prevwin == NULL)
9524 nr = 0;
9525 }
9526 else
9527 {
9528 EMSG2(_(e_invexpr2), arg);
9529 nr = 0;
9530 }
9531 }
9532
9533 if (nr > 0)
9534 for (wp = firstwin; wp != twin; wp = wp->w_next)
9535 ++nr;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009536#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009537 rettv->vval.v_number = nr;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009538}
9539
9540/*
9541 * "winrestcmd()" function
9542 */
9543/* ARGSUSED */
9544 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009545f_winrestcmd(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009546 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009547 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009548{
9549#ifdef FEAT_WINDOWS
9550 win_T *wp;
9551 int winnr = 1;
9552 garray_T ga;
9553 char_u buf[50];
9554
9555 ga_init2(&ga, (int)sizeof(char), 70);
9556 for (wp = firstwin; wp != NULL; wp = wp->w_next)
9557 {
9558 sprintf((char *)buf, "%dresize %d|", winnr, wp->w_height);
9559 ga_concat(&ga, buf);
9560# ifdef FEAT_VERTSPLIT
9561 sprintf((char *)buf, "vert %dresize %d|", winnr, wp->w_width);
9562 ga_concat(&ga, buf);
9563# endif
9564 ++winnr;
9565 }
Bram Moolenaar269ec652004-07-29 08:43:53 +00009566 ga_append(&ga, NUL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009567
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009568 rettv->vval.v_string = ga.ga_data;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009569#else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009570 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009571#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009572 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009573}
9574
9575/*
9576 * "winwidth(nr)" function
9577 */
9578 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009579f_winwidth(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009580 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009581 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009582{
9583 win_T *wp;
9584
9585 wp = find_win_by_nr(&argvars[0]);
9586 if (wp == NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009587 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009588 else
9589#ifdef FEAT_VERTSPLIT
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009590 rettv->vval.v_number = wp->w_width;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009591#else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009592 rettv->vval.v_number = Columns;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009593#endif
9594}
9595
9596 static win_T *
9597find_win_by_nr(vp)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009598 typeval *vp;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009599{
9600#ifdef FEAT_WINDOWS
9601 win_T *wp;
9602#endif
9603 int nr;
9604
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009605 nr = get_tv_number(vp);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009606
9607#ifdef FEAT_WINDOWS
9608 if (nr == 0)
9609 return curwin;
9610
9611 for (wp = firstwin; wp != NULL; wp = wp->w_next)
9612 if (--nr <= 0)
9613 break;
9614 return wp;
9615#else
9616 if (nr == 0 || nr == 1)
9617 return curwin;
9618 return NULL;
9619#endif
9620}
9621
9622/*
9623 * Translate a String variable into a position.
9624 */
9625 static pos_T *
9626var2fpos(varp, lnum)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009627 typeval *varp;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009628 int lnum; /* TRUE when $ is last line */
9629{
9630 char_u *name;
9631 static pos_T pos;
9632 pos_T *pp;
9633
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009634 name = get_tv_string(varp);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009635 if (name[0] == '.') /* cursor */
9636 return &curwin->w_cursor;
9637 if (name[0] == '\'') /* mark */
9638 {
9639 pp = getmark(name[1], FALSE);
9640 if (pp == NULL || pp == (pos_T *)-1 || pp->lnum <= 0)
9641 return NULL;
9642 return pp;
9643 }
9644 if (name[0] == '$') /* last column or line */
9645 {
9646 if (lnum)
9647 {
9648 pos.lnum = curbuf->b_ml.ml_line_count;
9649 pos.col = 0;
9650 }
9651 else
9652 {
9653 pos.lnum = curwin->w_cursor.lnum;
9654 pos.col = (colnr_T)STRLEN(ml_get_curline());
9655 }
9656 return &pos;
9657 }
9658 return NULL;
9659}
9660
9661/*
9662 * Get the length of an environment variable name.
9663 * Advance "arg" to the first character after the name.
9664 * Return 0 for error.
9665 */
9666 static int
9667get_env_len(arg)
9668 char_u **arg;
9669{
9670 char_u *p;
9671 int len;
9672
9673 for (p = *arg; vim_isIDc(*p); ++p)
9674 ;
9675 if (p == *arg) /* no name found */
9676 return 0;
9677
9678 len = (int)(p - *arg);
9679 *arg = p;
9680 return len;
9681}
9682
9683/*
9684 * Get the length of the name of a function or internal variable.
9685 * "arg" is advanced to the first non-white character after the name.
9686 * Return 0 if something is wrong.
9687 */
9688 static int
9689get_id_len(arg)
9690 char_u **arg;
9691{
9692 char_u *p;
9693 int len;
9694
9695 /* Find the end of the name. */
9696 for (p = *arg; eval_isnamec(*p); ++p)
9697 ;
9698 if (p == *arg) /* no name found */
9699 return 0;
9700
9701 len = (int)(p - *arg);
9702 *arg = skipwhite(p);
9703
9704 return len;
9705}
9706
9707/*
9708 * Get the length of the name of a function.
9709 * "arg" is advanced to the first non-white character after the name.
9710 * Return 0 if something is wrong.
9711 * If the name contains 'magic' {}'s, expand them and return the
9712 * expanded name in an allocated string via 'alias' - caller must free.
9713 */
9714 static int
9715get_func_len(arg, alias, evaluate)
9716 char_u **arg;
9717 char_u **alias;
9718 int evaluate;
9719{
9720 int len;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009721 char_u *p;
9722 char_u *expr_start;
9723 char_u *expr_end;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009724
9725 *alias = NULL; /* default to no alias */
9726
9727 if ((*arg)[0] == K_SPECIAL && (*arg)[1] == KS_EXTRA
9728 && (*arg)[2] == (int)KE_SNR)
9729 {
9730 /* hard coded <SNR>, already translated */
9731 *arg += 3;
9732 return get_id_len(arg) + 3;
9733 }
9734 len = eval_fname_script(*arg);
9735 if (len > 0)
9736 {
9737 /* literal "<SID>", "s:" or "<SNR>" */
9738 *arg += len;
9739 }
9740
Bram Moolenaar071d4272004-06-13 20:20:40 +00009741 /*
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009742 * Find the end of the name; check for {} construction.
Bram Moolenaar071d4272004-06-13 20:20:40 +00009743 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009744 p = find_name_end(*arg, &expr_start, &expr_end, FALSE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009745 if (expr_start != NULL)
9746 {
9747 char_u *temp_string;
9748
9749 if (!evaluate)
9750 {
9751 len += (int)(p - *arg);
9752 *arg = skipwhite(p);
9753 return len;
9754 }
9755
9756 /*
9757 * Include any <SID> etc in the expanded string:
9758 * Thus the -len here.
9759 */
9760 temp_string = make_expanded_name(*arg - len, expr_start, expr_end, p);
9761 if (temp_string == NULL)
9762 return 0;
9763 *alias = temp_string;
9764 *arg = skipwhite(p);
9765 return (int)STRLEN(temp_string);
9766 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00009767
9768 len += get_id_len(arg);
9769 if (len == 0)
9770 EMSG2(_(e_invexpr2), *arg);
9771
9772 return len;
9773}
9774
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009775/*
9776 * Find the end of a variable or function name, taking care of magic braces.
9777 * If "expr_start" is not NULL then "expr_start" and "expr_end" are set to the
9778 * start and end of the first magic braces item.
9779 * Return a pointer to just after the name. Equal to "arg" if there is no
9780 * valid name.
9781 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00009782 static char_u *
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009783find_name_end(arg, expr_start, expr_end, incl_br)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009784 char_u *arg;
9785 char_u **expr_start;
9786 char_u **expr_end;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009787 int incl_br; /* Include [] indexes */
Bram Moolenaar071d4272004-06-13 20:20:40 +00009788{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009789 int mb_nest = 0;
9790 int br_nest = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009791 char_u *p;
9792
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009793 if (expr_start != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009794 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009795 *expr_start = NULL;
9796 *expr_end = NULL;
9797 }
9798
9799 for (p = arg; *p != NUL
9800 && (eval_isnamec(*p)
9801 || (*p == '[' && incl_br)
9802 || mb_nest != 0
9803 || br_nest != 0); ++p)
9804 {
9805 if (mb_nest == 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009806 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009807 if (*p == '[')
9808 ++br_nest;
9809 else if (*p == ']')
9810 --br_nest;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009811 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009812 if (br_nest == 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009813 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009814 if (*p == '{')
9815 {
9816 mb_nest++;
9817 if (expr_start != NULL && *expr_start == NULL)
9818 *expr_start = p;
9819 }
9820 else if (*p == '}')
9821 {
9822 mb_nest--;
9823 if (expr_start != NULL && mb_nest == 0 && *expr_end == NULL)
9824 *expr_end = p;
9825 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00009826 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00009827 }
9828
9829 return p;
9830}
9831
9832/*
9833 * Return TRUE if character "c" can be used in a variable or function name.
9834 */
9835 static int
9836eval_isnamec(c)
9837 int c;
9838{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009839 return (ASCII_ISALNUM(c) || c == '_' || c == ':' || c == '{' || c == '}');
Bram Moolenaar071d4272004-06-13 20:20:40 +00009840}
9841
9842/*
9843 * Find a v: variable.
9844 * Return it's index, or -1 if not found.
9845 */
9846 static int
9847find_vim_var(name, len)
9848 char_u *name;
9849 int len; /* length of "name" */
9850{
9851 char_u *vname;
9852 int vlen;
9853 int i;
9854
9855 /*
9856 * Ignore "v:" for old built-in variables, require it for new ones.
9857 */
9858 if (name[0] == 'v' && name[1] == ':')
9859 {
9860 vname = name + 2;
9861 vlen = len - 2;
9862 }
9863 else
9864 {
9865 vname = name;
9866 vlen = len;
9867 }
9868 for (i = 0; i < VV_LEN; ++i)
9869 if (vlen == vimvars[i].len && STRCMP(vname, vimvars[i].name) == 0
9870 && ((vimvars[i].flags & VV_COMPAT) || vname != name))
9871 return i;
9872 return -1;
9873}
9874
9875/*
9876 * Set number v: variable to "val".
9877 */
9878 void
9879set_vim_var_nr(idx, val)
9880 int idx;
9881 long val;
9882{
9883 vimvars[idx].val = (char_u *)val;
9884}
9885
9886/*
9887 * Get number v: variable value;
9888 */
9889 long
9890get_vim_var_nr(idx)
9891 int idx;
9892{
9893 return (long)vimvars[idx].val;
9894}
9895
9896/*
9897 * Set v:count, v:count1 and v:prevcount.
9898 */
9899 void
9900set_vcount(count, count1)
9901 long count;
9902 long count1;
9903{
9904 vimvars[VV_PREVCOUNT].val = vimvars[VV_COUNT].val;
9905 vimvars[VV_COUNT].val = (char_u *)count;
9906 vimvars[VV_COUNT1].val = (char_u *)count1;
9907}
9908
9909/*
9910 * Set string v: variable to a copy of "val".
9911 */
9912 void
9913set_vim_var_string(idx, val, len)
9914 int idx;
9915 char_u *val;
9916 int len; /* length of "val" to use or -1 (whole string) */
9917{
9918 vim_free(vimvars[idx].val);
9919 if (val == NULL)
9920 vimvars[idx].val = NULL;
9921 else if (len == -1)
9922 vimvars[idx].val = vim_strsave(val);
9923 else
9924 vimvars[idx].val = vim_strnsave(val, len);
9925}
9926
9927/*
9928 * Set v:register if needed.
9929 */
9930 void
9931set_reg_var(c)
9932 int c;
9933{
9934 char_u regname;
9935
9936 if (c == 0 || c == ' ')
9937 regname = '"';
9938 else
9939 regname = c;
9940 /* Avoid free/alloc when the value is already right. */
9941 if (vimvars[VV_REG].val == NULL || vimvars[VV_REG].val[0] != c)
9942 set_vim_var_string(VV_REG, &regname, 1);
9943}
9944
9945/*
9946 * Get or set v:exception. If "oldval" == NULL, return the current value.
9947 * Otherwise, restore the value to "oldval" and return NULL.
9948 * Must always be called in pairs to save and restore v:exception! Does not
9949 * take care of memory allocations.
9950 */
9951 char_u *
9952v_exception(oldval)
9953 char_u *oldval;
9954{
9955 if (oldval == NULL)
9956 return vimvars[VV_EXCEPTION].val;
9957
9958 vimvars[VV_EXCEPTION].val = oldval;
9959 return NULL;
9960}
9961
9962/*
9963 * Get or set v:throwpoint. If "oldval" == NULL, return the current value.
9964 * Otherwise, restore the value to "oldval" and return NULL.
9965 * Must always be called in pairs to save and restore v:throwpoint! Does not
9966 * take care of memory allocations.
9967 */
9968 char_u *
9969v_throwpoint(oldval)
9970 char_u *oldval;
9971{
9972 if (oldval == NULL)
9973 return vimvars[VV_THROWPOINT].val;
9974
9975 vimvars[VV_THROWPOINT].val = oldval;
9976 return NULL;
9977}
9978
9979#if defined(FEAT_AUTOCMD) || defined(PROTO)
9980/*
9981 * Set v:cmdarg.
9982 * If "eap" != NULL, use "eap" to generate the value and return the old value.
9983 * If "oldarg" != NULL, restore the value to "oldarg" and return NULL.
9984 * Must always be called in pairs!
9985 */
9986 char_u *
9987set_cmdarg(eap, oldarg)
9988 exarg_T *eap;
9989 char_u *oldarg;
9990{
9991 char_u *oldval;
9992 char_u *newval;
9993 unsigned len;
9994
9995 oldval = vimvars[VV_CMDARG].val;
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +00009996 if (eap == NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009997 {
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +00009998 vim_free(oldval);
9999 vimvars[VV_CMDARG].val = oldarg;
10000 return NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010001 }
10002
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +000010003 if (eap->force_bin == FORCE_BIN)
10004 len = 6;
10005 else if (eap->force_bin == FORCE_NOBIN)
10006 len = 8;
10007 else
10008 len = 0;
10009 if (eap->force_ff != 0)
10010 len += (unsigned)STRLEN(eap->cmd + eap->force_ff) + 6;
10011# ifdef FEAT_MBYTE
10012 if (eap->force_enc != 0)
10013 len += (unsigned)STRLEN(eap->cmd + eap->force_enc) + 7;
10014# endif
10015
10016 newval = alloc(len + 1);
10017 if (newval == NULL)
10018 return NULL;
10019
10020 if (eap->force_bin == FORCE_BIN)
10021 sprintf((char *)newval, " ++bin");
10022 else if (eap->force_bin == FORCE_NOBIN)
10023 sprintf((char *)newval, " ++nobin");
10024 else
10025 *newval = NUL;
10026 if (eap->force_ff != 0)
10027 sprintf((char *)newval + STRLEN(newval), " ++ff=%s",
10028 eap->cmd + eap->force_ff);
10029# ifdef FEAT_MBYTE
10030 if (eap->force_enc != 0)
10031 sprintf((char *)newval + STRLEN(newval), " ++enc=%s",
10032 eap->cmd + eap->force_enc);
10033# endif
10034 vimvars[VV_CMDARG].val = newval;
10035 return oldval;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010036}
10037#endif
10038
10039/*
10040 * Get the value of internal variable "name".
10041 * Return OK or FAIL.
10042 */
10043 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010044get_var_tv(name, len, rettv)
Bram Moolenaar071d4272004-06-13 20:20:40 +000010045 char_u *name;
10046 int len; /* length of "name" */
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010047 typeval *rettv; /* NULL when only checking existence */
Bram Moolenaar071d4272004-06-13 20:20:40 +000010048{
10049 int ret = OK;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010050 typeval tv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010051 VAR v;
10052 int cc;
10053 int i;
10054
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010055 tv.v_type = VAR_UNKNOWN;
10056
Bram Moolenaar071d4272004-06-13 20:20:40 +000010057 /* truncate the name, so that we can use strcmp() */
10058 cc = name[len];
10059 name[len] = NUL;
10060
10061 /*
10062 * Check for "b:changedtick".
10063 */
10064 if (STRCMP(name, "b:changedtick") == 0)
10065 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010066 tv.v_type = VAR_NUMBER;
10067 tv.vval.v_number = curbuf->b_changedtick;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010068 }
10069
10070 /*
10071 * Check for built-in v: variables.
10072 */
10073 else if ((i = find_vim_var(name, len)) >= 0)
10074 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010075 tv.v_type = vimvars[i].type;
10076 if (tv.v_type == VAR_NUMBER)
10077 tv.vval.v_number = (long)vimvars[i].val;
10078 else
10079 tv.vval.v_string = vimvars[i].val;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010080 }
10081
10082 /*
10083 * Check for user-defined variables.
10084 */
10085 else
10086 {
10087 v = find_var(name, FALSE);
10088 if (v != NULL)
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010089 tv = v->tv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010090 }
10091
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010092 if (tv.v_type == VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +000010093 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010094 if (rettv != NULL)
10095 EMSG2(_(e_undefvar), name);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010096 ret = FAIL;
10097 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010098 else if (rettv != NULL)
10099 copy_tv(&tv, rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010100
10101 name[len] = cc;
10102
10103 return ret;
10104}
10105
10106/*
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010107 * Allocate memory for a variable type-value, and make it emtpy (0 or NULL
10108 * value).
10109 */
10110 static typeval *
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010111alloc_tv()
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010112{
10113 return (typeval *)alloc_clear((unsigned)sizeof(typeval));
10114}
10115
10116/*
10117 * Allocate memory for a variable type-value, and assign a string to it.
Bram Moolenaar071d4272004-06-13 20:20:40 +000010118 * The string "s" must have been allocated, it is consumed.
10119 * Return NULL for out of memory, the variable otherwise.
10120 */
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010121 static typeval *
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010122alloc_string_tv(s)
Bram Moolenaar071d4272004-06-13 20:20:40 +000010123 char_u *s;
10124{
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010125 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010126
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010127 rettv = alloc_tv();
10128 if (rettv != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000010129 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010130 rettv->v_type = VAR_STRING;
10131 rettv->vval.v_string = s;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010132 }
10133 else
10134 vim_free(s);
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010135 return rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010136}
10137
10138/*
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010139 * Free the memory for a variable type-value.
Bram Moolenaar071d4272004-06-13 20:20:40 +000010140 */
10141 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010142free_tv(varp)
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010143 typeval *varp;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010144{
10145 if (varp != NULL)
10146 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010147 switch (varp->v_type)
10148 {
10149 case VAR_STRING:
10150 case VAR_FUNC:
10151 vim_free(varp->vval.v_string);
10152 break;
10153 case VAR_LIST:
10154 list_unref(varp->vval.v_list);
10155 break;
10156 default:
10157 break;
10158 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000010159 vim_free(varp);
10160 }
10161}
10162
10163/*
10164 * Free the memory for a variable value and set the value to NULL or 0.
10165 */
10166 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010167clear_tv(varp)
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010168 typeval *varp;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010169{
10170 if (varp != NULL)
10171 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010172 switch (varp->v_type)
Bram Moolenaar071d4272004-06-13 20:20:40 +000010173 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010174 case VAR_STRING:
10175 case VAR_FUNC:
10176 vim_free(varp->vval.v_string);
10177 varp->vval.v_string = NULL;
10178 break;
10179 case VAR_LIST:
10180 list_unref(varp->vval.v_list);
10181 break;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010182 case VAR_NUMBER:
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010183 varp->vval.v_number = 0;
10184 break;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010185 case VAR_UNKNOWN:
10186 break;
10187 default:
10188 EMSG2(_(e_intern2), "clear_tv()");
Bram Moolenaar071d4272004-06-13 20:20:40 +000010189 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000010190 }
10191}
10192
10193/*
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010194 * Set the value of a variable to NULL without freeing items.
10195 */
10196 static void
10197init_tv(varp)
10198 typeval *varp;
10199{
10200 if (varp != NULL)
10201 vim_memset(varp, 0, sizeof(typeval));
10202}
10203
10204/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000010205 * Get the number value of a variable.
10206 * If it is a String variable, uses vim_str2nr().
10207 */
10208 static long
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010209get_tv_number(varp)
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010210 typeval *varp;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010211{
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010212 long n = 0L;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010213
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010214 switch (varp->v_type)
Bram Moolenaar071d4272004-06-13 20:20:40 +000010215 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010216 case VAR_NUMBER:
10217 n = (long)(varp->vval.v_number);
10218 break;
10219 case VAR_FUNC:
10220 EMSG(_("E999: Using function reference as a number"));
10221 break;
10222 case VAR_STRING:
10223 if (varp->vval.v_string != NULL)
10224 vim_str2nr(varp->vval.v_string, NULL, NULL,
10225 TRUE, TRUE, &n, NULL);
10226 break;
10227 default:
10228 break;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010229 }
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010230 return n;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010231}
10232
10233/*
10234 * Get the lnum from the first argument. Also accepts ".", "$", etc.
10235 */
10236 static linenr_T
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010237get_tv_lnum(argvars)
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010238 typeval *argvars;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010239{
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010240 typeval rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010241 linenr_T lnum;
10242
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010243 lnum = get_tv_number(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010244 if (lnum == 0) /* no valid number, try using line() */
10245 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010246 rettv.v_type = VAR_NUMBER;
10247 f_line(argvars, &rettv);
10248 lnum = rettv.vval.v_number;
10249 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010250 }
10251 return lnum;
10252}
10253
10254/*
10255 * Get the string value of a variable.
10256 * If it is a Number variable, the number is converted into a string.
10257 * get_var_string() uses a single, static buffer. YOU CAN ONLY USE IT ONCE!
10258 * get_var_string_buf() uses a given buffer.
10259 * If the String variable has never been set, return an empty string.
10260 * Never returns NULL;
10261 */
10262 static char_u *
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010263get_tv_string(varp)
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010264 typeval *varp;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010265{
10266 static char_u mybuf[NUMBUFLEN];
10267
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010268 return get_tv_string_buf(varp, mybuf);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010269}
10270
10271 static char_u *
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010272get_tv_string_buf(varp, buf)
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010273 typeval *varp;
10274 char_u *buf;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010275{
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010276 switch (varp->v_type)
Bram Moolenaar071d4272004-06-13 20:20:40 +000010277 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010278 case VAR_NUMBER:
10279 sprintf((char *)buf, "%ld", (long)varp->vval.v_number);
10280 return buf;
10281 case VAR_FUNC:
10282 EMSG(_("E99: using Funcref as a String"));
10283 break;
10284 case VAR_LIST:
10285 EMSG(_("E99: using List as a String"));
10286 break;
10287 case VAR_STRING:
10288 if (varp->vval.v_string != NULL)
10289 return varp->vval.v_string;
10290 break;
10291 default:
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010292 EMSG2(_(e_intern2), "get_tv_string_buf()");
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010293 break;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010294 }
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010295 return (char_u *)"";
Bram Moolenaar071d4272004-06-13 20:20:40 +000010296}
10297
10298/*
10299 * Find variable "name" in the list of variables.
10300 * Return a pointer to it if found, NULL if not found.
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010301 * Careful: "a:0" variables don't have a name.
Bram Moolenaar071d4272004-06-13 20:20:40 +000010302 */
10303 static VAR
10304find_var(name, writing)
10305 char_u *name;
10306 int writing;
10307{
10308 int i;
10309 char_u *varname;
10310 garray_T *gap;
10311
Bram Moolenaar071d4272004-06-13 20:20:40 +000010312 if (name[0] == 'a' && name[1] == ':')
10313 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010314 /* Function arguments "a:".
10315 * NOTE: We use a typecast, because function arguments don't have a
10316 * name. The caller must not try to access the name! */
Bram Moolenaar071d4272004-06-13 20:20:40 +000010317 if (writing)
10318 {
10319 EMSG2(_(e_readonlyvar), name);
10320 return NULL;
10321 }
10322 name += 2;
10323 if (current_funccal == NULL)
10324 return NULL;
10325 if (VIM_ISDIGIT(*name))
10326 {
10327 i = atol((char *)name);
10328 if (i == 0) /* a:0 */
10329 return &current_funccal->a0_var;
10330 i += current_funccal->func->args.ga_len;
10331 if (i > current_funccal->argcount) /* a:999 */
10332 return NULL;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010333 return (VAR)&(current_funccal->argvars[i - 1]); /* a:1, a:2, etc. */
Bram Moolenaar071d4272004-06-13 20:20:40 +000010334 }
10335 if (STRCMP(name, "firstline") == 0)
10336 return &(current_funccal->firstline);
10337 if (STRCMP(name, "lastline") == 0)
10338 return &(current_funccal->lastline);
10339 for (i = 0; i < current_funccal->func->args.ga_len; ++i)
10340 if (STRCMP(name, ((char_u **)
10341 (current_funccal->func->args.ga_data))[i]) == 0)
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010342 return (VAR)&(current_funccal->argvars[i]); /* a:name */
Bram Moolenaar071d4272004-06-13 20:20:40 +000010343 return NULL;
10344 }
10345
10346 gap = find_var_ga(name, &varname);
10347 if (gap == NULL)
10348 return NULL;
10349 return find_var_in_ga(gap, varname);
10350}
10351
10352 static VAR
10353find_var_in_ga(gap, varname)
10354 garray_T *gap;
10355 char_u *varname;
10356{
10357 int i;
10358
10359 for (i = gap->ga_len; --i >= 0; )
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010360 if (VAR_GAP_ENTRY(i, gap).v_name != NULL
10361 && STRCMP(VAR_GAP_ENTRY(i, gap).v_name, varname) == 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +000010362 break;
10363 if (i < 0)
10364 return NULL;
10365 return &VAR_GAP_ENTRY(i, gap);
10366}
10367
10368/*
10369 * Find the growarray and start of name without ':' for a variable name.
10370 */
10371 static garray_T *
10372find_var_ga(name, varname)
10373 char_u *name;
10374 char_u **varname;
10375{
10376 if (name[1] != ':')
10377 {
10378 /* If not "x:name" there must not be any ":" in the name. */
10379 if (vim_strchr(name, ':') != NULL)
10380 return NULL;
10381 *varname = name;
10382 if (current_funccal == NULL)
10383 return &variables; /* global variable */
10384 return &current_funccal->l_vars; /* local function variable */
10385 }
10386 *varname = name + 2;
10387 if (*name == 'b') /* buffer variable */
10388 return &curbuf->b_vars;
10389 if (*name == 'w') /* window variable */
10390 return &curwin->w_vars;
10391 if (*name == 'g') /* global variable */
10392 return &variables;
10393 if (*name == 'l' && current_funccal != NULL)/* local function variable */
10394 return &current_funccal->l_vars;
10395 if (*name == 's' /* script variable */
10396 && current_SID > 0 && current_SID <= ga_scripts.ga_len)
10397 return &SCRIPT_VARS(current_SID);
10398 return NULL;
10399}
10400
10401/*
10402 * Get the string value of a (global/local) variable.
10403 * Returns NULL when it doesn't exist.
10404 */
10405 char_u *
10406get_var_value(name)
10407 char_u *name;
10408{
10409 VAR v;
10410
10411 v = find_var(name, FALSE);
10412 if (v == NULL)
10413 return NULL;
10414 return get_var_string(v);
10415}
10416
10417/*
10418 * Allocate a new growarry for a sourced script. It will be used while
10419 * sourcing this script and when executing functions defined in the script.
10420 */
10421 void
10422new_script_vars(id)
10423 scid_T id;
10424{
10425 if (ga_grow(&ga_scripts, (int)(id - ga_scripts.ga_len)) == OK)
10426 {
10427 while (ga_scripts.ga_len < id)
10428 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010429 vars_init(&SCRIPT_VARS(ga_scripts.ga_len + 1));
Bram Moolenaar071d4272004-06-13 20:20:40 +000010430 ++ga_scripts.ga_len;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010431 }
10432 }
10433}
10434
10435/*
10436 * Initialize internal variables for use.
10437 */
10438 void
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010439vars_init(gap)
Bram Moolenaar071d4272004-06-13 20:20:40 +000010440 garray_T *gap;
10441{
10442 ga_init2(gap, (int)sizeof(var), 4);
10443}
10444
10445/*
10446 * Clean up a list of internal variables.
10447 */
10448 void
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010449vars_clear(gap)
Bram Moolenaar071d4272004-06-13 20:20:40 +000010450 garray_T *gap;
10451{
10452 int i;
10453
10454 for (i = gap->ga_len; --i >= 0; )
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010455 clear_var(&VAR_GAP_ENTRY(i, gap));
Bram Moolenaar071d4272004-06-13 20:20:40 +000010456 ga_clear(gap);
10457}
10458
10459 static void
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010460clear_var(v)
Bram Moolenaar071d4272004-06-13 20:20:40 +000010461 VAR v;
10462{
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010463 vim_free(v->v_name);
10464 v->v_name = NULL;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010465 clear_tv(&v->tv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010466}
10467
10468/*
10469 * List the value of one internal variable.
10470 */
10471 static void
10472list_one_var(v, prefix)
10473 VAR v;
10474 char_u *prefix;
10475{
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010476 char_u *tofree;
10477 char_u *s;
10478
10479 s = tv2string(&v->tv, &tofree);
10480 list_one_var_a(prefix, v->v_name, v->tv.v_type,
10481 s == NULL ? (char_u *)"" : s);
10482 vim_free(tofree);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010483}
10484
10485/*
10486 * List the value of one "v:" variable.
10487 */
10488 static void
10489list_vim_var(i)
10490 int i; /* index in vimvars[] */
10491{
10492 char_u *p;
10493 char_u numbuf[NUMBUFLEN];
10494
10495 if (vimvars[i].type == VAR_NUMBER)
10496 {
10497 p = numbuf;
10498 sprintf((char *)p, "%ld", (long)vimvars[i].val);
10499 }
10500 else if (vimvars[i].val == NULL)
10501 p = (char_u *)"";
10502 else
10503 p = vimvars[i].val;
10504 list_one_var_a((char_u *)"v:", (char_u *)vimvars[i].name,
10505 vimvars[i].type, p);
10506}
10507
10508 static void
10509list_one_var_a(prefix, name, type, string)
10510 char_u *prefix;
10511 char_u *name;
10512 int type;
10513 char_u *string;
10514{
10515 msg_attr(prefix, 0); /* don't use msg(), it overwrites "v:statusmsg" */
10516 if (name != NULL) /* "a:" vars don't have a name stored */
10517 msg_puts(name);
10518 msg_putchar(' ');
10519 msg_advance(22);
10520 if (type == VAR_NUMBER)
10521 msg_putchar('#');
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010522 else if (type == VAR_FUNC)
10523 msg_putchar('*');
10524 else if (type == VAR_LIST)
10525 {
10526 msg_putchar('[');
10527 if (*string == '[')
10528 ++string;
10529 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000010530 else
10531 msg_putchar(' ');
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010532
Bram Moolenaar071d4272004-06-13 20:20:40 +000010533 msg_outtrans(string);
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010534
10535 if (type == VAR_FUNC)
10536 msg_puts((char_u *)"()");
Bram Moolenaar071d4272004-06-13 20:20:40 +000010537}
10538
10539/*
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010540 * Set variable "name" to value in "tv".
Bram Moolenaar071d4272004-06-13 20:20:40 +000010541 * If the variable already exists, the value is updated.
10542 * Otherwise the variable is created.
10543 */
10544 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010545set_var(name, tv, copy)
Bram Moolenaar071d4272004-06-13 20:20:40 +000010546 char_u *name;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010547 typeval *tv;
10548 int copy; /* make copy of value in "tv" */
Bram Moolenaar071d4272004-06-13 20:20:40 +000010549{
10550 int i;
10551 VAR v;
10552 char_u *varname;
10553 garray_T *gap;
10554
10555 /*
10556 * Handle setting internal v: variables.
10557 */
10558 i = find_vim_var(name, (int)STRLEN(name));
10559 if (i >= 0)
10560 {
10561 if (vimvars[i].flags & VV_RO)
10562 EMSG2(_(e_readonlyvar), name);
Bram Moolenaar7b0294c2004-10-11 10:16:09 +000010563 else if ((vimvars[i].flags & VV_RO_SBX) && sandbox)
10564 EMSG2(_(e_readonlysbx), name);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010565 else
10566 {
10567 if (vimvars[i].type == VAR_STRING)
10568 {
10569 vim_free(vimvars[i].val);
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010570 if (copy || tv->v_type != VAR_STRING)
10571 vimvars[i].val = vim_strsave(get_tv_string(tv));
Bram Moolenaar1c2fda22005-01-02 11:43:19 +000010572 else
10573 {
10574 /* Take over the string to avoid an extra alloc/free. */
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010575 vimvars[i].val = tv->vval.v_string;
10576 tv->vval.v_string = NULL;
Bram Moolenaar1c2fda22005-01-02 11:43:19 +000010577 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000010578 }
10579 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010580 vimvars[i].val = (char_u *)get_tv_number(tv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010581 }
10582 return;
10583 }
10584
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010585 if (tv->v_type == VAR_FUNC)
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010586 {
10587 if (!(vim_strchr((char_u *)"wbs", name[0]) != NULL && name[1] == ':')
10588 && !ASCII_ISUPPER((name[0] != NUL && name[1] == ':')
10589 ? name[2] : name[0]))
10590 {
10591 EMSG2(_("E999: Funcref variable name must start with a capital: %s"), name);
10592 return;
10593 }
10594 if (function_exists(name))
10595 {
10596 EMSG2(_("E999: Variable name conflicts with existing function: %s"), name);
10597 return;
10598 }
10599 }
10600
Bram Moolenaar071d4272004-06-13 20:20:40 +000010601 v = find_var(name, TRUE);
10602 if (v != NULL) /* existing variable, only need to free string */
10603 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010604 if (v->tv.v_type != tv->v_type
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010605 && !((v->tv.v_type == VAR_STRING
10606 || v->tv.v_type == VAR_NUMBER)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010607 && (tv->v_type == VAR_STRING
10608 || tv->v_type == VAR_NUMBER)))
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010609 {
10610 EMSG2(_("E999: Variable type mismatch for: %s"), name);
10611 return;
10612 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010613 clear_tv(&v->tv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010614 }
10615 else /* add a new variable */
10616 {
10617 gap = find_var_ga(name, &varname);
10618 if (gap == NULL) /* illegal name */
10619 {
10620 EMSG2(_("E461: Illegal variable name: %s"), name);
10621 return;
10622 }
10623
10624 /* Try to use an empty entry */
10625 for (i = gap->ga_len; --i >= 0; )
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010626 if (VAR_GAP_ENTRY(i, gap).v_name == NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000010627 break;
10628 if (i < 0) /* need to allocate more room */
10629 {
10630 if (ga_grow(gap, 1) == FAIL)
10631 return;
10632 i = gap->ga_len;
10633 }
10634 v = &VAR_GAP_ENTRY(i, gap);
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010635 if ((v->v_name = vim_strsave(varname)) == NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000010636 return;
10637 if (i == gap->ga_len)
Bram Moolenaar071d4272004-06-13 20:20:40 +000010638 ++gap->ga_len;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010639 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010640 if (copy || tv->v_type == VAR_NUMBER)
10641 copy_tv(tv, &v->tv);
Bram Moolenaar1c2fda22005-01-02 11:43:19 +000010642 else
10643 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010644 v->tv = *tv;
10645 init_tv(tv);
Bram Moolenaar1c2fda22005-01-02 11:43:19 +000010646 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000010647}
10648
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010649/*
10650 * Copy the values from typeval "from" to typeval "to".
10651 * When needed allocates string or increases reference count.
10652 * Does not make a copy of a list!
10653 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000010654 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010655copy_tv(from, to)
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010656 typeval *from;
10657 typeval *to;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010658{
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010659 to->v_type = from->v_type;
10660 switch (from->v_type)
10661 {
10662 case VAR_NUMBER:
10663 to->vval.v_number = from->vval.v_number;
10664 break;
10665 case VAR_STRING:
10666 case VAR_FUNC:
10667 if (from->vval.v_string == NULL)
10668 to->vval.v_string = NULL;
10669 else
10670 to->vval.v_string = vim_strsave(from->vval.v_string);
10671 break;
10672 case VAR_LIST:
10673 if (from->vval.v_list == NULL)
10674 to->vval.v_list = NULL;
10675 else
10676 {
10677 to->vval.v_list = from->vval.v_list;
10678 ++to->vval.v_list->lv_refcount;
10679 }
10680 break;
10681 default:
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010682 EMSG2(_(e_intern2), "copy_tv()");
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010683 break;
10684 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000010685}
10686
10687/*
10688 * ":echo expr1 ..." print each argument separated with a space, add a
10689 * newline at the end.
10690 * ":echon expr1 ..." print each argument plain.
10691 */
10692 void
10693ex_echo(eap)
10694 exarg_T *eap;
10695{
10696 char_u *arg = eap->arg;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010697 typeval rettv;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010698 char_u *tofree;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010699 char_u *p;
10700 int needclr = TRUE;
10701 int atstart = TRUE;
10702
10703 if (eap->skip)
10704 ++emsg_skip;
10705 while (*arg != NUL && *arg != '|' && *arg != '\n' && !got_int)
10706 {
10707 p = arg;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010708 if (eval1(&arg, &rettv, !eap->skip) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000010709 {
10710 /*
10711 * Report the invalid expression unless the expression evaluation
10712 * has been cancelled due to an aborting error, an interrupt, or an
10713 * exception.
10714 */
10715 if (!aborting())
10716 EMSG2(_(e_invexpr2), p);
10717 break;
10718 }
10719 if (!eap->skip)
10720 {
10721 if (atstart)
10722 {
10723 atstart = FALSE;
10724 /* Call msg_start() after eval1(), evaluating the expression
10725 * may cause a message to appear. */
10726 if (eap->cmdidx == CMD_echo)
10727 msg_start();
10728 }
10729 else if (eap->cmdidx == CMD_echo)
10730 msg_puts_attr((char_u *)" ", echo_attr);
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010731 for (p = tv2string(&rettv, &tofree); *p != NUL && !got_int; ++p)
Bram Moolenaar071d4272004-06-13 20:20:40 +000010732 if (*p == '\n' || *p == '\r' || *p == TAB)
10733 {
10734 if (*p != TAB && needclr)
10735 {
10736 /* remove any text still there from the command */
10737 msg_clr_eos();
10738 needclr = FALSE;
10739 }
10740 msg_putchar_attr(*p, echo_attr);
10741 }
10742 else
10743 {
10744#ifdef FEAT_MBYTE
10745 if (has_mbyte)
10746 {
10747 int i = (*mb_ptr2len_check)(p);
10748
10749 (void)msg_outtrans_len_attr(p, i, echo_attr);
10750 p += i - 1;
10751 }
10752 else
10753#endif
10754 (void)msg_outtrans_len_attr(p, 1, echo_attr);
10755 }
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010756 vim_free(tofree);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010757 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010758 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010759 arg = skipwhite(arg);
10760 }
10761 eap->nextcmd = check_nextcmd(arg);
10762
10763 if (eap->skip)
10764 --emsg_skip;
10765 else
10766 {
10767 /* remove text that may still be there from the command */
10768 if (needclr)
10769 msg_clr_eos();
10770 if (eap->cmdidx == CMD_echo)
10771 msg_end();
10772 }
10773}
10774
10775/*
10776 * ":echohl {name}".
10777 */
10778 void
10779ex_echohl(eap)
10780 exarg_T *eap;
10781{
10782 int id;
10783
10784 id = syn_name2id(eap->arg);
10785 if (id == 0)
10786 echo_attr = 0;
10787 else
10788 echo_attr = syn_id2attr(id);
10789}
10790
10791/*
10792 * ":execute expr1 ..." execute the result of an expression.
10793 * ":echomsg expr1 ..." Print a message
10794 * ":echoerr expr1 ..." Print an error
10795 * Each gets spaces around each argument and a newline at the end for
10796 * echo commands
10797 */
10798 void
10799ex_execute(eap)
10800 exarg_T *eap;
10801{
10802 char_u *arg = eap->arg;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010803 typeval rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010804 int ret = OK;
10805 char_u *p;
10806 garray_T ga;
10807 int len;
10808 int save_did_emsg;
10809
10810 ga_init2(&ga, 1, 80);
10811
10812 if (eap->skip)
10813 ++emsg_skip;
10814 while (*arg != NUL && *arg != '|' && *arg != '\n')
10815 {
10816 p = arg;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010817 if (eval1(&arg, &rettv, !eap->skip) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000010818 {
10819 /*
10820 * Report the invalid expression unless the expression evaluation
10821 * has been cancelled due to an aborting error, an interrupt, or an
10822 * exception.
10823 */
10824 if (!aborting())
10825 EMSG2(_(e_invexpr2), p);
10826 ret = FAIL;
10827 break;
10828 }
10829
10830 if (!eap->skip)
10831 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010832 p = get_tv_string(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010833 len = (int)STRLEN(p);
10834 if (ga_grow(&ga, len + 2) == FAIL)
10835 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010836 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010837 ret = FAIL;
10838 break;
10839 }
10840 if (ga.ga_len)
Bram Moolenaar071d4272004-06-13 20:20:40 +000010841 ((char_u *)(ga.ga_data))[ga.ga_len++] = ' ';
Bram Moolenaar071d4272004-06-13 20:20:40 +000010842 STRCPY((char_u *)(ga.ga_data) + ga.ga_len, p);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010843 ga.ga_len += len;
10844 }
10845
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010846 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010847 arg = skipwhite(arg);
10848 }
10849
10850 if (ret != FAIL && ga.ga_data != NULL)
10851 {
10852 if (eap->cmdidx == CMD_echomsg)
10853 MSG_ATTR(ga.ga_data, echo_attr);
10854 else if (eap->cmdidx == CMD_echoerr)
10855 {
10856 /* We don't want to abort following commands, restore did_emsg. */
10857 save_did_emsg = did_emsg;
10858 EMSG((char_u *)ga.ga_data);
10859 if (!force_abort)
10860 did_emsg = save_did_emsg;
10861 }
10862 else if (eap->cmdidx == CMD_execute)
10863 do_cmdline((char_u *)ga.ga_data,
10864 eap->getline, eap->cookie, DOCMD_NOWAIT|DOCMD_VERBOSE);
10865 }
10866
10867 ga_clear(&ga);
10868
10869 if (eap->skip)
10870 --emsg_skip;
10871
10872 eap->nextcmd = check_nextcmd(arg);
10873}
10874
10875/*
10876 * Skip over the name of an option: "&option", "&g:option" or "&l:option".
10877 * "arg" points to the "&" or '+' when called, to "option" when returning.
10878 * Returns NULL when no option name found. Otherwise pointer to the char
10879 * after the option name.
10880 */
10881 static char_u *
10882find_option_end(arg, opt_flags)
10883 char_u **arg;
10884 int *opt_flags;
10885{
10886 char_u *p = *arg;
10887
10888 ++p;
10889 if (*p == 'g' && p[1] == ':')
10890 {
10891 *opt_flags = OPT_GLOBAL;
10892 p += 2;
10893 }
10894 else if (*p == 'l' && p[1] == ':')
10895 {
10896 *opt_flags = OPT_LOCAL;
10897 p += 2;
10898 }
10899 else
10900 *opt_flags = 0;
10901
10902 if (!ASCII_ISALPHA(*p))
10903 return NULL;
10904 *arg = p;
10905
10906 if (p[0] == 't' && p[1] == '_' && p[2] != NUL && p[3] != NUL)
10907 p += 4; /* termcap option */
10908 else
10909 while (ASCII_ISALPHA(*p))
10910 ++p;
10911 return p;
10912}
10913
10914/*
10915 * ":function"
10916 */
10917 void
10918ex_function(eap)
10919 exarg_T *eap;
10920{
10921 char_u *theline;
10922 int j;
10923 int c;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010924 int saved_did_emsg;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010925 char_u *name = NULL;
10926 char_u *p;
10927 char_u *arg;
10928 garray_T newargs;
10929 garray_T newlines;
10930 int varargs = FALSE;
10931 int mustend = FALSE;
10932 int flags = 0;
10933 ufunc_T *fp;
10934 int indent;
10935 int nesting;
10936 char_u *skip_until = NULL;
10937 static char_u e_funcexts[] = N_("E122: Function %s already exists, add ! to replace it");
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010938 VAR v;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010939
10940 /*
10941 * ":function" without argument: list functions.
10942 */
10943 if (ends_excmd(*eap->arg))
10944 {
10945 if (!eap->skip)
10946 for (fp = firstfunc; fp != NULL && !got_int; fp = fp->next)
10947 list_func_head(fp, FALSE);
10948 eap->nextcmd = check_nextcmd(eap->arg);
10949 return;
10950 }
10951
10952 p = eap->arg;
10953 name = trans_function_name(&p, eap->skip, FALSE);
10954 if (name == NULL && !eap->skip)
10955 {
10956 /*
10957 * Return on an invalid expression in braces, unless the expression
10958 * evaluation has been cancelled due to an aborting error, an
10959 * interrupt, or an exception.
10960 */
10961 if (!aborting())
10962 return;
10963 else
10964 eap->skip = TRUE;
10965 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000010966 /* An error in a function call during evaluation of an expression in magic
10967 * braces should not cause the function not to be defined. */
10968 saved_did_emsg = did_emsg;
10969 did_emsg = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010970
10971 /*
10972 * ":function func" with only function name: list function.
10973 */
10974 if (vim_strchr(p, '(') == NULL)
10975 {
10976 if (!ends_excmd(*skipwhite(p)))
10977 {
10978 EMSG(_(e_trailing));
10979 goto erret_name;
10980 }
10981 eap->nextcmd = check_nextcmd(p);
10982 if (eap->nextcmd != NULL)
10983 *p = NUL;
10984 if (!eap->skip && !got_int)
10985 {
10986 fp = find_func(name);
10987 if (fp != NULL)
10988 {
10989 list_func_head(fp, TRUE);
10990 for (j = 0; j < fp->lines.ga_len && !got_int; ++j)
10991 {
10992 msg_putchar('\n');
10993 msg_outnum((long)(j + 1));
10994 if (j < 9)
10995 msg_putchar(' ');
10996 if (j < 99)
10997 msg_putchar(' ');
10998 msg_prt_line(FUNCLINE(fp, j));
10999 out_flush(); /* show a line at a time */
11000 ui_breakcheck();
11001 }
11002 if (!got_int)
11003 {
11004 msg_putchar('\n');
11005 msg_puts((char_u *)" endfunction");
11006 }
11007 }
11008 else
11009 EMSG2(_("E123: Undefined function: %s"), eap->arg);
11010 }
11011 goto erret_name;
11012 }
11013
11014 /*
11015 * ":function name(arg1, arg2)" Define function.
11016 */
11017 p = skipwhite(p);
11018 if (*p != '(')
11019 {
11020 if (!eap->skip)
11021 {
11022 EMSG2(_("E124: Missing '(': %s"), eap->arg);
11023 goto erret_name;
11024 }
11025 /* attempt to continue by skipping some text */
11026 if (vim_strchr(p, '(') != NULL)
11027 p = vim_strchr(p, '(');
11028 }
11029 p = skipwhite(p + 1);
11030
11031 ga_init2(&newargs, (int)sizeof(char_u *), 3);
11032 ga_init2(&newlines, (int)sizeof(char_u *), 3);
11033
11034 /*
11035 * Isolate the arguments: "arg1, arg2, ...)"
11036 */
11037 while (*p != ')')
11038 {
11039 if (p[0] == '.' && p[1] == '.' && p[2] == '.')
11040 {
11041 varargs = TRUE;
11042 p += 3;
11043 mustend = TRUE;
11044 }
11045 else
11046 {
11047 arg = p;
11048 while (ASCII_ISALNUM(*p) || *p == '_')
11049 ++p;
11050 if (arg == p || isdigit(*arg)
11051 || (p - arg == 9 && STRNCMP(arg, "firstline", 9) == 0)
11052 || (p - arg == 8 && STRNCMP(arg, "lastline", 8) == 0))
11053 {
11054 if (!eap->skip)
11055 EMSG2(_("E125: Illegal argument: %s"), arg);
11056 break;
11057 }
11058 if (ga_grow(&newargs, 1) == FAIL)
11059 goto erret;
11060 c = *p;
11061 *p = NUL;
11062 arg = vim_strsave(arg);
11063 if (arg == NULL)
11064 goto erret;
11065 ((char_u **)(newargs.ga_data))[newargs.ga_len] = arg;
11066 *p = c;
11067 newargs.ga_len++;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011068 if (*p == ',')
11069 ++p;
11070 else
11071 mustend = TRUE;
11072 }
11073 p = skipwhite(p);
11074 if (mustend && *p != ')')
11075 {
11076 if (!eap->skip)
11077 EMSG2(_(e_invarg2), eap->arg);
11078 break;
11079 }
11080 }
11081 ++p; /* skip the ')' */
11082
11083 /* find extra arguments "range" and "abort" */
11084 for (;;)
11085 {
11086 p = skipwhite(p);
11087 if (STRNCMP(p, "range", 5) == 0)
11088 {
11089 flags |= FC_RANGE;
11090 p += 5;
11091 }
11092 else if (STRNCMP(p, "abort", 5) == 0)
11093 {
11094 flags |= FC_ABORT;
11095 p += 5;
11096 }
11097 else
11098 break;
11099 }
11100
11101 if (*p != NUL && *p != '"' && *p != '\n' && !eap->skip && !did_emsg)
11102 EMSG(_(e_trailing));
11103
11104 /*
11105 * Read the body of the function, until ":endfunction" is found.
11106 */
11107 if (KeyTyped)
11108 {
11109 /* Check if the function already exists, don't let the user type the
11110 * whole function before telling him it doesn't work! For a script we
11111 * need to skip the body to be able to find what follows. */
11112 if (!eap->skip && !eap->forceit && find_func(name) != NULL)
11113 EMSG2(_(e_funcexts), name);
11114
11115 msg_putchar('\n'); /* don't overwrite the function name */
11116 cmdline_row = msg_row;
11117 }
11118
11119 indent = 2;
11120 nesting = 0;
11121 for (;;)
11122 {
11123 msg_scroll = TRUE;
11124 need_wait_return = FALSE;
11125 if (eap->getline == NULL)
11126 theline = getcmdline(':', 0L, indent);
11127 else
11128 theline = eap->getline(':', eap->cookie, indent);
11129 if (KeyTyped)
11130 lines_left = Rows - 1;
11131 if (theline == NULL)
11132 {
11133 EMSG(_("E126: Missing :endfunction"));
11134 goto erret;
11135 }
11136
11137 if (skip_until != NULL)
11138 {
11139 /* between ":append" and "." and between ":python <<EOF" and "EOF"
11140 * don't check for ":endfunc". */
11141 if (STRCMP(theline, skip_until) == 0)
11142 {
11143 vim_free(skip_until);
11144 skip_until = NULL;
11145 }
11146 }
11147 else
11148 {
11149 /* skip ':' and blanks*/
11150 for (p = theline; vim_iswhite(*p) || *p == ':'; ++p)
11151 ;
11152
11153 /* Check for "endfunction" (should be more strict...). */
11154 if (STRNCMP(p, "endf", 4) == 0 && nesting-- == 0)
11155 {
11156 vim_free(theline);
11157 break;
11158 }
11159
11160 /* Increase indent inside "if", "while", and "try", decrease
11161 * at "end". */
11162 if (indent > 2 && STRNCMP(p, "end", 3) == 0)
11163 indent -= 2;
11164 else if (STRNCMP(p, "if", 2) == 0 || STRNCMP(p, "wh", 2) == 0
11165 || STRNCMP(p, "try", 3) == 0)
11166 indent += 2;
11167
11168 /* Check for defining a function inside this function. */
11169 if (STRNCMP(p, "fu", 2) == 0)
11170 {
11171 p = skipwhite(skiptowhite(p));
11172 p += eval_fname_script(p);
11173 if (ASCII_ISALPHA(*p))
11174 {
11175 vim_free(trans_function_name(&p, TRUE, FALSE));
11176 if (*skipwhite(p) == '(')
11177 {
11178 ++nesting;
11179 indent += 2;
11180 }
11181 }
11182 }
11183
11184 /* Check for ":append" or ":insert". */
11185 p = skip_range(p, NULL);
11186 if ((p[0] == 'a' && (!ASCII_ISALPHA(p[1]) || p[1] == 'p'))
11187 || (p[0] == 'i'
11188 && (!ASCII_ISALPHA(p[1]) || (p[1] == 'n'
11189 && (!ASCII_ISALPHA(p[2]) || (p[2] == 's'))))))
11190 skip_until = vim_strsave((char_u *)".");
11191
11192 /* Check for ":python <<EOF", ":tcl <<EOF", etc. */
11193 arg = skipwhite(skiptowhite(p));
11194 if (arg[0] == '<' && arg[1] =='<'
11195 && ((p[0] == 'p' && p[1] == 'y'
11196 && (!ASCII_ISALPHA(p[2]) || p[2] == 't'))
11197 || (p[0] == 'p' && p[1] == 'e'
11198 && (!ASCII_ISALPHA(p[2]) || p[2] == 'r'))
11199 || (p[0] == 't' && p[1] == 'c'
11200 && (!ASCII_ISALPHA(p[2]) || p[2] == 'l'))
11201 || (p[0] == 'r' && p[1] == 'u' && p[2] == 'b'
11202 && (!ASCII_ISALPHA(p[3]) || p[3] == 'y'))
Bram Moolenaar325b7a22004-07-05 15:58:32 +000011203 || (p[0] == 'm' && p[1] == 'z'
11204 && (!ASCII_ISALPHA(p[2]) || p[2] == 's'))
Bram Moolenaar071d4272004-06-13 20:20:40 +000011205 ))
11206 {
11207 /* ":python <<" continues until a dot, like ":append" */
11208 p = skipwhite(arg + 2);
11209 if (*p == NUL)
11210 skip_until = vim_strsave((char_u *)".");
11211 else
11212 skip_until = vim_strsave(p);
11213 }
11214 }
11215
11216 /* Add the line to the function. */
11217 if (ga_grow(&newlines, 1) == FAIL)
11218 goto erret;
11219 ((char_u **)(newlines.ga_data))[newlines.ga_len] = theline;
11220 newlines.ga_len++;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011221 }
11222
11223 /* Don't define the function when skipping commands or when an error was
11224 * detected. */
11225 if (eap->skip || did_emsg)
11226 goto erret;
11227
11228 /*
11229 * If there are no errors, add the function
11230 */
Bram Moolenaar49cd9572005-01-03 21:06:01 +000011231 v = find_var(name, FALSE);
11232 if (v != NULL && v->tv.v_type == VAR_FUNC)
11233 {
11234 EMSG2(_("E999: Function name conflicts with variable: %s"), name);
11235 goto erret;
11236 }
11237
Bram Moolenaar071d4272004-06-13 20:20:40 +000011238 fp = find_func(name);
11239 if (fp != NULL)
11240 {
11241 if (!eap->forceit)
11242 {
11243 EMSG2(_(e_funcexts), name);
11244 goto erret;
11245 }
11246 if (fp->calls)
11247 {
11248 EMSG2(_("E127: Cannot redefine function %s: It is in use"), name);
11249 goto erret;
11250 }
11251 /* redefine existing function */
11252 ga_clear_strings(&(fp->args));
11253 ga_clear_strings(&(fp->lines));
11254 vim_free(name);
11255 }
11256 else
11257 {
11258 fp = (ufunc_T *)alloc((unsigned)sizeof(ufunc_T));
11259 if (fp == NULL)
11260 goto erret;
11261 /* insert the new function in the function list */
11262 fp->next = firstfunc;
11263 firstfunc = fp;
11264 fp->name = name;
11265 }
11266 fp->args = newargs;
11267 fp->lines = newlines;
11268 fp->varargs = varargs;
11269 fp->flags = flags;
11270 fp->calls = 0;
11271 fp->script_ID = current_SID;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011272 did_emsg |= saved_did_emsg;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011273 vim_free(skip_until);
11274 return;
11275
11276erret:
11277 vim_free(skip_until);
11278 ga_clear_strings(&newargs);
11279 ga_clear_strings(&newlines);
11280erret_name:
11281 vim_free(name);
Bram Moolenaar071d4272004-06-13 20:20:40 +000011282 did_emsg |= saved_did_emsg;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011283}
11284
11285/*
11286 * Get a function name, translating "<SID>" and "<SNR>".
11287 * Returns the function name in allocated memory, or NULL for failure.
11288 * Advances "pp" to just after the function name (if no error).
11289 */
11290 static char_u *
11291trans_function_name(pp, skip, internal)
11292 char_u **pp;
11293 int skip; /* only find the end, don't evaluate */
11294 int internal; /* TRUE if internal function name OK */
11295{
11296 char_u *name;
11297 char_u *start;
11298 char_u *end;
11299 int lead;
11300 char_u sid_buf[20];
11301 char_u *temp_string = NULL;
11302 char_u *expr_start, *expr_end;
11303 int len;
11304
11305 /* A name starting with "<SID>" or "<SNR>" is local to a script. */
11306 start = *pp;
11307 lead = eval_fname_script(start);
11308 if (lead > 0)
11309 start += lead;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011310 end = find_name_end(start, &expr_start, &expr_end, FALSE);
Bram Moolenaar071d4272004-06-13 20:20:40 +000011311 if (end == start)
11312 {
11313 if (!skip)
11314 EMSG(_("E129: Function name required"));
11315 return NULL;
11316 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000011317 if (expr_start != NULL && !skip)
11318 {
11319 /* expand magic curlies */
11320 temp_string = make_expanded_name(start, expr_start, expr_end, end);
11321 if (temp_string == NULL)
11322 {
11323 /*
11324 * Report an invalid expression in braces, unless the expression
11325 * evaluation has been cancelled due to an aborting error, an
11326 * interrupt, or an exception.
11327 */
11328 if (!aborting())
11329 EMSG2(_(e_invarg2), start);
11330 else
11331 *pp = end;
11332 return NULL;
11333 }
11334 start = temp_string;
11335 len = (int)STRLEN(temp_string);
11336 }
11337 else
Bram Moolenaar071d4272004-06-13 20:20:40 +000011338 len = (int)(end - start);
11339
11340 /*
11341 * Copy the function name to allocated memory.
11342 * Accept <SID>name() inside a script, translate into <SNR>123_name().
11343 * Accept <SNR>123_name() outside a script.
11344 */
11345 if (skip)
11346 lead = 0; /* do nothing */
11347 else if (lead > 0)
11348 {
11349 lead = 3;
11350 if (eval_fname_sid(*pp)) /* If it's "<SID>" */
11351 {
11352 if (current_SID <= 0)
11353 {
11354 EMSG(_(e_usingsid));
11355 return NULL;
11356 }
11357 sprintf((char *)sid_buf, "%ld_", (long)current_SID);
11358 lead += (int)STRLEN(sid_buf);
11359 }
11360 }
11361 else if (!internal && !ASCII_ISUPPER(*start))
11362 {
11363 EMSG2(_("E128: Function name must start with a capital: %s"), start);
11364 return NULL;
11365 }
11366 name = alloc((unsigned)(len + lead + 1));
11367 if (name != NULL)
11368 {
11369 if (lead > 0)
11370 {
11371 name[0] = K_SPECIAL;
11372 name[1] = KS_EXTRA;
11373 name[2] = (int)KE_SNR;
11374 if (eval_fname_sid(*pp)) /* If it's "<SID>" */
11375 STRCPY(name + 3, sid_buf);
11376 }
11377 mch_memmove(name + lead, start, (size_t)len);
11378 name[len + lead] = NUL;
11379 }
11380 *pp = end;
11381
11382 vim_free(temp_string);
11383 return name;
11384}
11385
11386/*
11387 * Return 5 if "p" starts with "<SID>" or "<SNR>" (ignoring case).
11388 * Return 2 if "p" starts with "s:".
11389 * Return 0 otherwise.
11390 */
11391 static int
11392eval_fname_script(p)
11393 char_u *p;
11394{
11395 if (p[0] == '<' && (STRNICMP(p + 1, "SID>", 4) == 0
11396 || STRNICMP(p + 1, "SNR>", 4) == 0))
11397 return 5;
11398 if (p[0] == 's' && p[1] == ':')
11399 return 2;
11400 return 0;
11401}
11402
11403/*
11404 * Return TRUE if "p" starts with "<SID>" or "s:".
11405 * Only works if eval_fname_script() returned non-zero for "p"!
11406 */
11407 static int
11408eval_fname_sid(p)
11409 char_u *p;
11410{
11411 return (*p == 's' || TOUPPER_ASC(p[2]) == 'I');
11412}
11413
11414/*
11415 * List the head of the function: "name(arg1, arg2)".
11416 */
11417 static void
11418list_func_head(fp, indent)
11419 ufunc_T *fp;
11420 int indent;
11421{
11422 int j;
11423
11424 msg_start();
11425 if (indent)
11426 MSG_PUTS(" ");
11427 MSG_PUTS("function ");
11428 if (fp->name[0] == K_SPECIAL)
11429 {
11430 MSG_PUTS_ATTR("<SNR>", hl_attr(HLF_8));
11431 msg_puts(fp->name + 3);
11432 }
11433 else
11434 msg_puts(fp->name);
11435 msg_putchar('(');
11436 for (j = 0; j < fp->args.ga_len; ++j)
11437 {
11438 if (j)
11439 MSG_PUTS(", ");
11440 msg_puts(FUNCARG(fp, j));
11441 }
11442 if (fp->varargs)
11443 {
11444 if (j)
11445 MSG_PUTS(", ");
11446 MSG_PUTS("...");
11447 }
11448 msg_putchar(')');
11449}
11450
11451/*
11452 * Find a function by name, return pointer to it in ufuncs.
11453 * Return NULL for unknown function.
11454 */
11455 static ufunc_T *
11456find_func(name)
11457 char_u *name;
11458{
11459 ufunc_T *fp;
11460
11461 for (fp = firstfunc; fp != NULL; fp = fp->next)
11462 if (STRCMP(name, fp->name) == 0)
11463 break;
11464 return fp;
11465}
11466
Bram Moolenaar49cd9572005-01-03 21:06:01 +000011467/*
11468 * Return TRUE if a function "name" exists.
11469 */
11470 static int
11471function_exists(name)
11472 char_u *name;
11473{
11474 char_u *p = name;
11475 int n = FALSE;
11476
11477 p = trans_function_name(&p, FALSE, TRUE);
11478 if (p != NULL)
11479 {
11480 if (ASCII_ISUPPER(*p) || p[0] == K_SPECIAL)
11481 n = (find_func(p) != NULL);
11482 else if (ASCII_ISLOWER(*p))
11483 n = (find_internal_func(p) >= 0);
11484 vim_free(p);
11485 }
11486 return n;
11487}
11488
Bram Moolenaar071d4272004-06-13 20:20:40 +000011489#if defined(FEAT_CMDL_COMPL) || defined(PROTO)
11490
11491/*
11492 * Function given to ExpandGeneric() to obtain the list of user defined
11493 * function names.
11494 */
11495 char_u *
11496get_user_func_name(xp, idx)
11497 expand_T *xp;
11498 int idx;
11499{
11500 static ufunc_T *fp = NULL;
11501
11502 if (idx == 0)
11503 fp = firstfunc;
11504 if (fp != NULL)
11505 {
11506 if (STRLEN(fp->name) + 4 >= IOSIZE)
11507 return fp->name; /* prevents overflow */
11508
11509 cat_func_name(IObuff, fp);
11510 if (xp->xp_context != EXPAND_USER_FUNC)
11511 {
11512 STRCAT(IObuff, "(");
11513 if (!fp->varargs && fp->args.ga_len == 0)
11514 STRCAT(IObuff, ")");
11515 }
11516
11517 fp = fp->next;
11518 return IObuff;
11519 }
11520 return NULL;
11521}
11522
11523#endif /* FEAT_CMDL_COMPL */
11524
11525/*
11526 * Copy the function name of "fp" to buffer "buf".
11527 * "buf" must be able to hold the function name plus three bytes.
11528 * Takes care of script-local function names.
11529 */
11530 static void
11531cat_func_name(buf, fp)
11532 char_u *buf;
11533 ufunc_T *fp;
11534{
11535 if (fp->name[0] == K_SPECIAL)
11536 {
11537 STRCPY(buf, "<SNR>");
11538 STRCAT(buf, fp->name + 3);
11539 }
11540 else
11541 STRCPY(buf, fp->name);
11542}
11543
11544/*
11545 * ":delfunction {name}"
11546 */
11547 void
11548ex_delfunction(eap)
11549 exarg_T *eap;
11550{
11551 ufunc_T *fp = NULL, *pfp;
11552 char_u *p;
11553 char_u *name;
11554
11555 p = eap->arg;
11556 name = trans_function_name(&p, eap->skip, FALSE);
11557 if (name == NULL)
11558 return;
11559 if (!ends_excmd(*skipwhite(p)))
11560 {
11561 vim_free(name);
11562 EMSG(_(e_trailing));
11563 return;
11564 }
11565 eap->nextcmd = check_nextcmd(p);
11566 if (eap->nextcmd != NULL)
11567 *p = NUL;
11568
11569 if (!eap->skip)
11570 fp = find_func(name);
11571 vim_free(name);
11572
11573 if (!eap->skip)
11574 {
11575 if (fp == NULL)
11576 {
11577 EMSG2(_("E130: Undefined function: %s"), eap->arg);
11578 return;
11579 }
11580 if (fp->calls)
11581 {
11582 EMSG2(_("E131: Cannot delete function %s: It is in use"), eap->arg);
11583 return;
11584 }
11585
11586 /* clear this function */
11587 vim_free(fp->name);
11588 ga_clear_strings(&(fp->args));
11589 ga_clear_strings(&(fp->lines));
11590
11591 /* remove the function from the function list */
11592 if (firstfunc == fp)
11593 firstfunc = fp->next;
11594 else
11595 {
11596 for (pfp = firstfunc; pfp != NULL; pfp = pfp->next)
11597 if (pfp->next == fp)
11598 {
11599 pfp->next = fp->next;
11600 break;
11601 }
11602 }
11603 vim_free(fp);
11604 }
11605}
11606
11607/*
11608 * Call a user function.
11609 */
11610 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011611call_user_func(fp, argcount, argvars, rettv, firstline, lastline)
Bram Moolenaar071d4272004-06-13 20:20:40 +000011612 ufunc_T *fp; /* pointer to function */
11613 int argcount; /* nr of args */
Bram Moolenaar49cd9572005-01-03 21:06:01 +000011614 typeval *argvars; /* arguments */
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011615 typeval *rettv; /* return value */
Bram Moolenaar071d4272004-06-13 20:20:40 +000011616 linenr_T firstline; /* first line of range */
11617 linenr_T lastline; /* last line of range */
11618{
11619 char_u *save_sourcing_name;
11620 linenr_T save_sourcing_lnum;
11621 scid_T save_current_SID;
11622 struct funccall fc;
11623 struct funccall *save_fcp = current_funccal;
11624 int save_did_emsg;
11625 static int depth = 0;
11626
11627 /* If depth of calling is getting too high, don't execute the function */
11628 if (depth >= p_mfd)
11629 {
11630 EMSG(_("E132: Function call depth is higher than 'maxfuncdepth'"));
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011631 rettv->v_type = VAR_NUMBER;
11632 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011633 return;
11634 }
11635 ++depth;
11636
11637 line_breakcheck(); /* check for CTRL-C hit */
11638
11639 /* set local variables */
Bram Moolenaar49cd9572005-01-03 21:06:01 +000011640 vars_init(&fc.l_vars);
Bram Moolenaar071d4272004-06-13 20:20:40 +000011641 fc.func = fp;
11642 fc.argcount = argcount;
11643 fc.argvars = argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011644 fc.rettv = rettv;
11645 rettv->vval.v_number = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011646 fc.linenr = 0;
11647 fc.returned = FALSE;
11648 fc.level = ex_nesting_level;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000011649 fc.a0_var.tv.v_type = VAR_NUMBER;
11650 fc.a0_var.tv.vval.v_number = argcount - fp->args.ga_len;
11651 fc.a0_var.v_name = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011652 current_funccal = &fc;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000011653 fc.firstline.tv.v_type = VAR_NUMBER;
11654 fc.firstline.tv.vval.v_number = firstline;
11655 fc.firstline.v_name = NULL;
11656 fc.lastline.tv.v_type = VAR_NUMBER;
11657 fc.lastline.tv.vval.v_number = lastline;
11658 fc.lastline.v_name = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011659 /* Check if this function has a breakpoint. */
11660 fc.breakpoint = dbg_find_breakpoint(FALSE, fp->name, (linenr_T)0);
11661 fc.dbg_tick = debug_tick;
11662
11663 /* Don't redraw while executing the function. */
11664 ++RedrawingDisabled;
11665 save_sourcing_name = sourcing_name;
11666 save_sourcing_lnum = sourcing_lnum;
11667 sourcing_lnum = 1;
11668 sourcing_name = alloc((unsigned)((save_sourcing_name == NULL ? 0
11669 : STRLEN(save_sourcing_name)) + STRLEN(fp->name) + 13));
11670 if (sourcing_name != NULL)
11671 {
11672 if (save_sourcing_name != NULL
11673 && STRNCMP(save_sourcing_name, "function ", 9) == 0)
11674 sprintf((char *)sourcing_name, "%s..", save_sourcing_name);
11675 else
11676 STRCPY(sourcing_name, "function ");
11677 cat_func_name(sourcing_name + STRLEN(sourcing_name), fp);
11678
11679 if (p_verbose >= 12)
11680 {
11681 ++no_wait_return;
11682 msg_scroll = TRUE; /* always scroll up, don't overwrite */
11683 msg_str((char_u *)_("calling %s"), sourcing_name);
11684 if (p_verbose >= 14)
11685 {
11686 int i;
11687 char_u buf[MSG_BUF_LEN];
11688
11689 msg_puts((char_u *)"(");
11690 for (i = 0; i < argcount; ++i)
11691 {
11692 if (i > 0)
11693 msg_puts((char_u *)", ");
Bram Moolenaar49cd9572005-01-03 21:06:01 +000011694 if (argvars[i].v_type == VAR_NUMBER)
11695 msg_outnum((long)argvars[i].vval.v_number);
Bram Moolenaar071d4272004-06-13 20:20:40 +000011696 else
11697 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011698 trunc_string(get_tv_string(&argvars[i]),
Bram Moolenaar071d4272004-06-13 20:20:40 +000011699 buf, MSG_BUF_LEN);
11700 msg_puts((char_u *)"\"");
11701 msg_puts(buf);
11702 msg_puts((char_u *)"\"");
11703 }
11704 }
11705 msg_puts((char_u *)")");
11706 }
11707 msg_puts((char_u *)"\n"); /* don't overwrite this either */
11708 cmdline_row = msg_row;
11709 --no_wait_return;
11710 }
11711 }
11712 save_current_SID = current_SID;
11713 current_SID = fp->script_ID;
11714 save_did_emsg = did_emsg;
11715 did_emsg = FALSE;
11716
11717 /* call do_cmdline() to execute the lines */
11718 do_cmdline(NULL, get_func_line, (void *)&fc,
11719 DOCMD_NOWAIT|DOCMD_VERBOSE|DOCMD_REPEAT);
11720
11721 --RedrawingDisabled;
11722
11723 /* when the function was aborted because of an error, return -1 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011724 if ((did_emsg && (fp->flags & FC_ABORT)) || rettv->v_type == VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +000011725 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011726 clear_tv(rettv);
11727 rettv->v_type = VAR_NUMBER;
11728 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011729 }
11730
11731 /* when being verbose, mention the return value */
11732 if (p_verbose >= 12)
11733 {
11734 char_u *sn, *val;
11735
11736 ++no_wait_return;
11737 msg_scroll = TRUE; /* always scroll up, don't overwrite */
11738
11739 /* Make sure the output fits in IObuff. */
11740 sn = sourcing_name;
11741 if (STRLEN(sourcing_name) > IOSIZE / 2 - 50)
11742 sn = sourcing_name + STRLEN(sourcing_name) - (IOSIZE / 2 - 50);
11743
11744 if (aborting())
11745 smsg((char_u *)_("%s aborted"), sn);
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011746 else if (fc.rettv->v_type == VAR_NUMBER)
Bram Moolenaar071d4272004-06-13 20:20:40 +000011747 smsg((char_u *)_("%s returning #%ld"), sn,
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011748 (long)fc.rettv->vval.v_number);
11749 else if (fc.rettv->v_type == VAR_STRING)
Bram Moolenaar071d4272004-06-13 20:20:40 +000011750 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011751 val = get_tv_string(fc.rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000011752 if (STRLEN(val) > IOSIZE / 2 - 50)
11753 val = val + STRLEN(val) - (IOSIZE / 2 - 50);
11754 smsg((char_u *)_("%s returning \"%s\""), sn, val);
11755 }
11756 msg_puts((char_u *)"\n"); /* don't overwrite this either */
11757 cmdline_row = msg_row;
11758 --no_wait_return;
11759 }
11760
11761 vim_free(sourcing_name);
11762 sourcing_name = save_sourcing_name;
11763 sourcing_lnum = save_sourcing_lnum;
11764 current_SID = save_current_SID;
11765
11766 if (p_verbose >= 12 && sourcing_name != NULL)
11767 {
11768 ++no_wait_return;
11769 msg_scroll = TRUE; /* always scroll up, don't overwrite */
11770 msg_str((char_u *)_("continuing in %s"), sourcing_name);
11771 msg_puts((char_u *)"\n"); /* don't overwrite this either */
11772 cmdline_row = msg_row;
11773 --no_wait_return;
11774 }
11775
11776 did_emsg |= save_did_emsg;
11777 current_funccal = save_fcp;
11778
Bram Moolenaar49cd9572005-01-03 21:06:01 +000011779 vars_clear(&fc.l_vars); /* free all local variables */
Bram Moolenaar071d4272004-06-13 20:20:40 +000011780 --depth;
11781}
11782
11783/*
11784 * ":return [expr]"
11785 */
11786 void
11787ex_return(eap)
11788 exarg_T *eap;
11789{
11790 char_u *arg = eap->arg;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011791 typeval rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011792 int returning = FALSE;
11793
11794 if (current_funccal == NULL)
11795 {
11796 EMSG(_("E133: :return not inside a function"));
11797 return;
11798 }
11799
11800 if (eap->skip)
11801 ++emsg_skip;
11802
11803 eap->nextcmd = NULL;
11804 if ((*arg != NUL && *arg != '|' && *arg != '\n')
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011805 && eval0(arg, &rettv, &eap->nextcmd, !eap->skip) != FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000011806 {
11807 if (!eap->skip)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011808 returning = do_return(eap, FALSE, TRUE, &rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000011809 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011810 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000011811 }
11812 /* It's safer to return also on error. */
11813 else if (!eap->skip)
11814 {
11815 /*
11816 * Return unless the expression evaluation has been cancelled due to an
11817 * aborting error, an interrupt, or an exception.
11818 */
11819 if (!aborting())
11820 returning = do_return(eap, FALSE, TRUE, NULL);
11821 }
11822
11823 /* When skipping or the return gets pending, advance to the next command
11824 * in this line (!returning). Otherwise, ignore the rest of the line.
11825 * Following lines will be ignored by get_func_line(). */
11826 if (returning)
11827 eap->nextcmd = NULL;
11828 else if (eap->nextcmd == NULL) /* no argument */
11829 eap->nextcmd = check_nextcmd(arg);
11830
11831 if (eap->skip)
11832 --emsg_skip;
11833}
11834
11835/*
11836 * Return from a function. Possibly makes the return pending. Also called
11837 * for a pending return at the ":endtry" or after returning from an extra
11838 * do_cmdline(). "reanimate" is used in the latter case. "is_cmd" is set
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011839 * when called due to a ":return" command. "rettv" may point to a typeval
11840 * with the return rettv. Returns TRUE when the return can be carried out,
Bram Moolenaar071d4272004-06-13 20:20:40 +000011841 * FALSE when the return gets pending.
11842 */
11843 int
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011844do_return(eap, reanimate, is_cmd, rettv)
Bram Moolenaar071d4272004-06-13 20:20:40 +000011845 exarg_T *eap;
11846 int reanimate;
11847 int is_cmd;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011848 void *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011849{
11850 int idx;
11851 struct condstack *cstack = eap->cstack;
11852
11853 if (reanimate)
11854 /* Undo the return. */
11855 current_funccal->returned = FALSE;
11856
11857 /*
11858 * Cleanup (and inactivate) conditionals, but stop when a try conditional
11859 * not in its finally clause (which then is to be executed next) is found.
11860 * In this case, make the ":return" pending for execution at the ":endtry".
11861 * Otherwise, return normally.
11862 */
11863 idx = cleanup_conditionals(eap->cstack, 0, TRUE);
11864 if (idx >= 0)
11865 {
11866 cstack->cs_pending[idx] = CSTP_RETURN;
11867
11868 if (!is_cmd && !reanimate)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011869 /* A pending return again gets pending. "rettv" points to an
11870 * allocated variable with the rettv of the original ":return"'s
Bram Moolenaar071d4272004-06-13 20:20:40 +000011871 * argument if present or is NULL else. */
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011872 cstack->cs_rettv[idx] = rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011873 else
11874 {
11875 /* When undoing a return in order to make it pending, get the stored
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011876 * return rettv. */
Bram Moolenaar071d4272004-06-13 20:20:40 +000011877 if (reanimate)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011878 rettv = current_funccal->rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011879
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011880 if (rettv != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000011881 {
11882 /* Store the value of the pending return. */
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011883 if ((cstack->cs_rettv[idx] = alloc_tv()) != NULL)
11884 *(typeval *)cstack->cs_rettv[idx] = *(typeval *)rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011885 else
11886 EMSG(_(e_outofmem));
11887 }
11888 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011889 cstack->cs_rettv[idx] = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011890
11891 if (reanimate)
11892 {
11893 /* The pending return value could be overwritten by a ":return"
11894 * without argument in a finally clause; reset the default
11895 * return value. */
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011896 current_funccal->rettv->v_type = VAR_NUMBER;
11897 current_funccal->rettv->vval.v_number = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011898 }
11899 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011900 report_make_pending(CSTP_RETURN, rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000011901 }
11902 else
11903 {
11904 current_funccal->returned = TRUE;
11905
11906 /* If the return is carried out now, store the return value. For
11907 * a return immediately after reanimation, the value is already
11908 * there. */
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011909 if (!reanimate && rettv != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000011910 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011911 clear_tv(current_funccal->rettv);
11912 *current_funccal->rettv = *(typeval *)rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011913 if (!is_cmd)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011914 vim_free(rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000011915 }
11916 }
11917
11918 return idx < 0;
11919}
11920
11921/*
11922 * Free the variable with a pending return value.
11923 */
11924 void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011925discard_pending_return(rettv)
11926 void *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011927{
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011928 free_tv((typeval *)rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000011929}
11930
11931/*
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011932 * Generate a return command for producing the value of "rettv". The result
Bram Moolenaar071d4272004-06-13 20:20:40 +000011933 * is an allocated string. Used by report_pending() for verbose messages.
11934 */
11935 char_u *
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011936get_return_cmd(rettv)
11937 void *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011938{
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011939 char_u *s;
11940 char_u *tofree = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011941
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011942 if (rettv == NULL)
11943 s = (char_u *)"";
Bram Moolenaar071d4272004-06-13 20:20:40 +000011944 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011945 s = tv2string((typeval *)rettv, &tofree);
11946
11947 STRCPY(IObuff, ":return ");
11948 STRNCPY(IObuff + 8, s, IOSIZE - 8);
11949 if (STRLEN(s) + 8 >= IOSIZE)
11950 STRCPY(IObuff + IOSIZE - 4, "...");
11951 vim_free(tofree);
11952 return vim_strsave(IObuff);
Bram Moolenaar071d4272004-06-13 20:20:40 +000011953}
11954
11955/*
11956 * Get next function line.
11957 * Called by do_cmdline() to get the next line.
11958 * Returns allocated string, or NULL for end of function.
11959 */
11960/* ARGSUSED */
11961 char_u *
11962get_func_line(c, cookie, indent)
11963 int c; /* not used */
11964 void *cookie;
11965 int indent; /* not used */
11966{
11967 struct funccall *fcp = (struct funccall *)cookie;
11968 char_u *retval;
11969 garray_T *gap; /* growarray with function lines */
11970
11971 /* If breakpoints have been added/deleted need to check for it. */
11972 if (fcp->dbg_tick != debug_tick)
11973 {
11974 fcp->breakpoint = dbg_find_breakpoint(FALSE, fcp->func->name,
11975 sourcing_lnum);
11976 fcp->dbg_tick = debug_tick;
11977 }
11978
11979 gap = &fcp->func->lines;
11980 if ((fcp->func->flags & FC_ABORT) && did_emsg && !aborted_in_try())
11981 retval = NULL;
11982 else if (fcp->returned || fcp->linenr >= gap->ga_len)
11983 retval = NULL;
11984 else
11985 {
11986 retval = vim_strsave(((char_u **)(gap->ga_data))[fcp->linenr++]);
11987 sourcing_lnum = fcp->linenr;
11988 }
11989
11990 /* Did we encounter a breakpoint? */
11991 if (fcp->breakpoint != 0 && fcp->breakpoint <= sourcing_lnum)
11992 {
11993 dbg_breakpoint(fcp->func->name, sourcing_lnum);
11994 /* Find next breakpoint. */
11995 fcp->breakpoint = dbg_find_breakpoint(FALSE, fcp->func->name,
11996 sourcing_lnum);
11997 fcp->dbg_tick = debug_tick;
11998 }
11999
12000 return retval;
12001}
12002
12003/*
12004 * Return TRUE if the currently active function should be ended, because a
12005 * return was encountered or an error occured. Used inside a ":while".
12006 */
12007 int
12008func_has_ended(cookie)
12009 void *cookie;
12010{
12011 struct funccall *fcp = (struct funccall *)cookie;
12012
12013 /* Ignore the "abort" flag if the abortion behavior has been changed due to
12014 * an error inside a try conditional. */
12015 return (((fcp->func->flags & FC_ABORT) && did_emsg && !aborted_in_try())
12016 || fcp->returned);
12017}
12018
12019/*
12020 * return TRUE if cookie indicates a function which "abort"s on errors.
12021 */
12022 int
12023func_has_abort(cookie)
12024 void *cookie;
12025{
12026 return ((struct funccall *)cookie)->func->flags & FC_ABORT;
12027}
12028
12029#if defined(FEAT_VIMINFO) || defined(FEAT_SESSION)
12030typedef enum
12031{
12032 VAR_FLAVOUR_DEFAULT,
12033 VAR_FLAVOUR_SESSION,
12034 VAR_FLAVOUR_VIMINFO
12035} var_flavour_T;
12036
12037static var_flavour_T var_flavour __ARGS((char_u *varname));
12038
12039 static var_flavour_T
12040var_flavour(varname)
12041 char_u *varname;
12042{
12043 char_u *p = varname;
12044
12045 if (ASCII_ISUPPER(*p))
12046 {
12047 while (*(++p))
12048 if (ASCII_ISLOWER(*p))
12049 return VAR_FLAVOUR_SESSION;
12050 return VAR_FLAVOUR_VIMINFO;
12051 }
12052 else
12053 return VAR_FLAVOUR_DEFAULT;
12054}
12055#endif
12056
12057#if defined(FEAT_VIMINFO) || defined(PROTO)
12058/*
12059 * Restore global vars that start with a capital from the viminfo file
12060 */
12061 int
12062read_viminfo_varlist(virp, writing)
12063 vir_T *virp;
12064 int writing;
12065{
12066 char_u *tab;
12067 int is_string = FALSE;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +000012068 typeval tv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012069
12070 if (!writing && (find_viminfo_parameter('!') != NULL))
12071 {
12072 tab = vim_strchr(virp->vir_line + 1, '\t');
12073 if (tab != NULL)
12074 {
12075 *tab++ = '\0'; /* isolate the variable name */
12076 if (*tab == 'S') /* string var */
12077 is_string = TRUE;
12078
12079 tab = vim_strchr(tab, '\t');
12080 if (tab != NULL)
12081 {
Bram Moolenaar071d4272004-06-13 20:20:40 +000012082 if (is_string)
12083 {
Bram Moolenaar3d60ec22005-01-05 22:19:46 +000012084 tv.v_type = VAR_STRING;
12085 tv.vval.v_string = viminfo_readstring(virp,
Bram Moolenaar071d4272004-06-13 20:20:40 +000012086 (int)(tab - virp->vir_line + 1), TRUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +000012087 }
12088 else
12089 {
Bram Moolenaar3d60ec22005-01-05 22:19:46 +000012090 tv.v_type = VAR_NUMBER;
12091 tv.vval.v_number = atol((char *)tab + 1);
Bram Moolenaar071d4272004-06-13 20:20:40 +000012092 }
Bram Moolenaar3d60ec22005-01-05 22:19:46 +000012093 set_var(virp->vir_line + 1, &tv, FALSE);
12094 if (is_string)
12095 vim_free(tv.vval.v_string);
Bram Moolenaar071d4272004-06-13 20:20:40 +000012096 }
12097 }
12098 }
12099
12100 return viminfo_readline(virp);
12101}
12102
12103/*
12104 * Write global vars that start with a capital to the viminfo file
12105 */
12106 void
12107write_viminfo_varlist(fp)
12108 FILE *fp;
12109{
12110 garray_T *gap = &variables; /* global variable */
12111 VAR this_var;
12112 int i;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012113 char *s;
12114 char_u *tofree;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012115
12116 if (find_viminfo_parameter('!') == NULL)
12117 return;
12118
12119 fprintf(fp, _("\n# global variables:\n"));
12120 for (i = gap->ga_len; --i >= 0; )
12121 {
12122 this_var = &VAR_GAP_ENTRY(i, gap);
Bram Moolenaar49cd9572005-01-03 21:06:01 +000012123 if (this_var->v_name != NULL
12124 && var_flavour(this_var->v_name) == VAR_FLAVOUR_VIMINFO)
Bram Moolenaar071d4272004-06-13 20:20:40 +000012125 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012126 switch (this_var->tv.v_type)
12127 {
12128 case VAR_STRING: s = "STR"; break;
12129 case VAR_NUMBER: s = "NUM"; break;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +000012130 default: continue;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012131 }
12132 fprintf(fp, "!%s\t%s\t", this_var->v_name, s);
12133 viminfo_writestring(fp, tv2string(&this_var->tv, &tofree));
12134 vim_free(tofree);
Bram Moolenaar071d4272004-06-13 20:20:40 +000012135 }
12136 }
12137}
12138#endif
12139
12140#if defined(FEAT_SESSION) || defined(PROTO)
12141 int
12142store_session_globals(fd)
12143 FILE *fd;
12144{
12145 garray_T *gap = &variables; /* global variable */
12146 VAR this_var;
12147 int i;
12148 char_u *p, *t;
12149
12150 for (i = gap->ga_len; --i >= 0; )
12151 {
12152 this_var = &VAR_GAP_ENTRY(i, gap);
Bram Moolenaar3d60ec22005-01-05 22:19:46 +000012153 if (this_var->v_name != NULL
12154 && (this_var->tv.v_type == VAR_NUMBER
12155 || this_var->tv.v_type == VAR_STRING)
12156 && var_flavour(this_var->v_name) == VAR_FLAVOUR_SESSION)
Bram Moolenaar071d4272004-06-13 20:20:40 +000012157 {
Bram Moolenaar3d60ec22005-01-05 22:19:46 +000012158 /* Escape special characters with a backslash. Turn a LF and
12159 * CR into \n and \r. */
12160 p = vim_strsave_escaped(get_var_string(this_var),
Bram Moolenaar071d4272004-06-13 20:20:40 +000012161 (char_u *)"\\\"\n\r");
Bram Moolenaar3d60ec22005-01-05 22:19:46 +000012162 if (p == NULL) /* out of memory */
12163 continue;
12164 for (t = p; *t != NUL; ++t)
12165 if (*t == '\n')
12166 *t = 'n';
12167 else if (*t == '\r')
12168 *t = 'r';
12169 if ((fprintf(fd, "let %s = %c%s%c",
12170 this_var->v_name,
12171 (this_var->tv.v_type == VAR_STRING) ? '"' : ' ',
12172 p,
12173 (this_var->tv.v_type == VAR_STRING) ? '"' : ' ') < 0)
12174 || put_eol(fd) == FAIL)
12175 {
Bram Moolenaar071d4272004-06-13 20:20:40 +000012176 vim_free(p);
Bram Moolenaar3d60ec22005-01-05 22:19:46 +000012177 return FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012178 }
Bram Moolenaar3d60ec22005-01-05 22:19:46 +000012179 vim_free(p);
Bram Moolenaar071d4272004-06-13 20:20:40 +000012180 }
12181 }
12182 return OK;
12183}
12184#endif
12185
12186#endif /* FEAT_EVAL */
12187
12188#if defined(FEAT_MODIFY_FNAME) || defined(FEAT_EVAL) || defined(PROTO)
12189
12190
12191#ifdef WIN3264
12192/*
12193 * Functions for ":8" filename modifier: get 8.3 version of a filename.
12194 */
12195static int get_short_pathname __ARGS((char_u **fnamep, char_u **bufp, int *fnamelen));
12196static int shortpath_for_invalid_fname __ARGS((char_u **fname, char_u **bufp, int *fnamelen));
12197static int shortpath_for_partial __ARGS((char_u **fnamep, char_u **bufp, int *fnamelen));
12198
12199/*
12200 * Get the short pathname of a file.
12201 * Returns 1 on success. *fnamelen is 0 for nonexistant path.
12202 */
12203 static int
12204get_short_pathname(fnamep, bufp, fnamelen)
12205 char_u **fnamep;
12206 char_u **bufp;
12207 int *fnamelen;
12208{
12209 int l,len;
12210 char_u *newbuf;
12211
12212 len = *fnamelen;
12213
12214 l = GetShortPathName(*fnamep, *fnamep, len);
12215 if (l > len - 1)
12216 {
12217 /* If that doesn't work (not enough space), then save the string
12218 * and try again with a new buffer big enough
12219 */
12220 newbuf = vim_strnsave(*fnamep, l);
12221 if (newbuf == NULL)
12222 return 0;
12223
12224 vim_free(*bufp);
12225 *fnamep = *bufp = newbuf;
12226
12227 l = GetShortPathName(*fnamep,*fnamep,l+1);
12228
12229 /* Really should always succeed, as the buffer is big enough */
12230 }
12231
12232 *fnamelen = l;
12233 return 1;
12234}
12235
12236/*
12237 * Create a short path name. Returns the length of the buffer it needs.
12238 * Doesn't copy over the end of the buffer passed in.
12239 */
12240 static int
12241shortpath_for_invalid_fname(fname, bufp, fnamelen)
12242 char_u **fname;
12243 char_u **bufp;
12244 int *fnamelen;
12245{
12246 char_u *s, *p, *pbuf2, *pbuf3;
12247 char_u ch;
12248 int l,len,len2,plen,slen;
12249
12250 /* Make a copy */
12251 len2 = *fnamelen;
12252 pbuf2 = vim_strnsave(*fname, len2);
12253 pbuf3 = NULL;
12254
12255 s = pbuf2 + len2 - 1; /* Find the end */
12256 slen = 1;
12257 plen = len2;
12258
12259 l = 0;
Bram Moolenaar1cd871b2004-12-19 22:46:22 +000012260 if (after_pathsep(pbuf2, s + 1))
Bram Moolenaar071d4272004-06-13 20:20:40 +000012261 {
12262 --s;
12263 ++slen;
12264 --plen;
12265 }
12266
12267 do
12268 {
12269 /* Go back one path-seperator */
Bram Moolenaar1cd871b2004-12-19 22:46:22 +000012270 while (s > pbuf2 && !after_pathsep(pbuf2, s + 1))
Bram Moolenaar071d4272004-06-13 20:20:40 +000012271 {
12272 --s;
12273 ++slen;
12274 --plen;
12275 }
12276 if (s <= pbuf2)
12277 break;
12278
12279 /* Remeber the character that is about to be blatted */
12280 ch = *s;
12281 *s = 0; /* get_short_pathname requires a null-terminated string */
12282
12283 /* Try it in situ */
12284 p = pbuf2;
12285 if (!get_short_pathname(&p, &pbuf3, &plen))
12286 {
12287 vim_free(pbuf2);
12288 return -1;
12289 }
12290 *s = ch; /* Preserve the string */
12291 } while (plen == 0);
12292
12293 if (plen > 0)
12294 {
12295 /* Remeber the length of the new string. */
12296 *fnamelen = len = plen + slen;
12297 vim_free(*bufp);
12298 if (len > len2)
12299 {
12300 /* If there's not enough space in the currently allocated string,
12301 * then copy it to a buffer big enough.
12302 */
12303 *fname= *bufp = vim_strnsave(p, len);
12304 if (*fname == NULL)
12305 return -1;
12306 }
12307 else
12308 {
12309 /* Transfer pbuf2 to being the main buffer (it's big enough) */
12310 *fname = *bufp = pbuf2;
12311 if (p != pbuf2)
12312 strncpy(*fname, p, plen);
12313 pbuf2 = NULL;
12314 }
12315 /* Concat the next bit */
12316 strncpy(*fname + plen, s, slen);
12317 (*fname)[len] = '\0';
12318 }
12319 vim_free(pbuf3);
12320 vim_free(pbuf2);
12321 return 0;
12322}
12323
12324/*
12325 * Get a pathname for a partial path.
12326 */
12327 static int
12328shortpath_for_partial(fnamep, bufp, fnamelen)
12329 char_u **fnamep;
12330 char_u **bufp;
12331 int *fnamelen;
12332{
12333 int sepcount, len, tflen;
12334 char_u *p;
12335 char_u *pbuf, *tfname;
12336 int hasTilde;
12337
12338 /* Count up the path seperators from the RHS.. so we know which part
12339 * of the path to return.
12340 */
12341 sepcount = 0;
Bram Moolenaar1cd871b2004-12-19 22:46:22 +000012342 for (p = *fnamep; p < *fnamep + *fnamelen; mb_ptr_adv(p))
Bram Moolenaar071d4272004-06-13 20:20:40 +000012343 if (vim_ispathsep(*p))
12344 ++sepcount;
12345
12346 /* Need full path first (use expand_env() to remove a "~/") */
12347 hasTilde = (**fnamep == '~');
12348 if (hasTilde)
12349 pbuf = tfname = expand_env_save(*fnamep);
12350 else
12351 pbuf = tfname = FullName_save(*fnamep, FALSE);
12352
12353 len = tflen = STRLEN(tfname);
12354
12355 if (!get_short_pathname(&tfname, &pbuf, &len))
12356 return -1;
12357
12358 if (len == 0)
12359 {
12360 /* Don't have a valid filename, so shorten the rest of the
12361 * path if we can. This CAN give us invalid 8.3 filenames, but
12362 * there's not a lot of point in guessing what it might be.
12363 */
12364 len = tflen;
12365 if (shortpath_for_invalid_fname(&tfname, &pbuf, &len) == -1)
12366 return -1;
12367 }
12368
12369 /* Count the paths backward to find the beginning of the desired string. */
12370 for (p = tfname + len - 1; p >= tfname; --p)
Bram Moolenaar1cd871b2004-12-19 22:46:22 +000012371 {
12372#ifdef FEAT_MBYTE
12373 if (has_mbyte)
12374 p -= mb_head_off(tfname, p);
12375#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000012376 if (vim_ispathsep(*p))
12377 {
12378 if (sepcount == 0 || (hasTilde && sepcount == 1))
12379 break;
12380 else
12381 sepcount --;
12382 }
Bram Moolenaar1cd871b2004-12-19 22:46:22 +000012383 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000012384 if (hasTilde)
12385 {
12386 --p;
12387 if (p >= tfname)
12388 *p = '~';
12389 else
12390 return -1;
12391 }
12392 else
12393 ++p;
12394
12395 /* Copy in the string - p indexes into tfname - allocated at pbuf */
12396 vim_free(*bufp);
12397 *fnamelen = (int)STRLEN(p);
12398 *bufp = pbuf;
12399 *fnamep = p;
12400
12401 return 0;
12402}
12403#endif /* WIN3264 */
12404
12405/*
12406 * Adjust a filename, according to a string of modifiers.
12407 * *fnamep must be NUL terminated when called. When returning, the length is
12408 * determined by *fnamelen.
12409 * Returns valid flags.
12410 * When there is an error, *fnamep is set to NULL.
12411 */
12412 int
12413modify_fname(src, usedlen, fnamep, bufp, fnamelen)
12414 char_u *src; /* string with modifiers */
12415 int *usedlen; /* characters after src that are used */
12416 char_u **fnamep; /* file name so far */
12417 char_u **bufp; /* buffer for allocated file name or NULL */
12418 int *fnamelen; /* length of fnamep */
12419{
12420 int valid = 0;
12421 char_u *tail;
12422 char_u *s, *p, *pbuf;
12423 char_u dirname[MAXPATHL];
12424 int c;
12425 int has_fullname = 0;
12426#ifdef WIN3264
12427 int has_shortname = 0;
12428#endif
12429
12430repeat:
12431 /* ":p" - full path/file_name */
12432 if (src[*usedlen] == ':' && src[*usedlen + 1] == 'p')
12433 {
12434 has_fullname = 1;
12435
12436 valid |= VALID_PATH;
12437 *usedlen += 2;
12438
12439 /* Expand "~/path" for all systems and "~user/path" for Unix and VMS */
12440 if ((*fnamep)[0] == '~'
12441#if !defined(UNIX) && !(defined(VMS) && defined(USER_HOME))
12442 && ((*fnamep)[1] == '/'
12443# ifdef BACKSLASH_IN_FILENAME
12444 || (*fnamep)[1] == '\\'
12445# endif
12446 || (*fnamep)[1] == NUL)
12447
12448#endif
12449 )
12450 {
12451 *fnamep = expand_env_save(*fnamep);
12452 vim_free(*bufp); /* free any allocated file name */
12453 *bufp = *fnamep;
12454 if (*fnamep == NULL)
12455 return -1;
12456 }
12457
12458 /* When "/." or "/.." is used: force expansion to get rid of it. */
Bram Moolenaar1cd871b2004-12-19 22:46:22 +000012459 for (p = *fnamep; *p != NUL; mb_ptr_adv(p))
Bram Moolenaar071d4272004-06-13 20:20:40 +000012460 {
12461 if (vim_ispathsep(*p)
12462 && p[1] == '.'
12463 && (p[2] == NUL
12464 || vim_ispathsep(p[2])
12465 || (p[2] == '.'
12466 && (p[3] == NUL || vim_ispathsep(p[3])))))
12467 break;
12468 }
12469
12470 /* FullName_save() is slow, don't use it when not needed. */
12471 if (*p != NUL || !vim_isAbsName(*fnamep))
12472 {
12473 *fnamep = FullName_save(*fnamep, *p != NUL);
12474 vim_free(*bufp); /* free any allocated file name */
12475 *bufp = *fnamep;
12476 if (*fnamep == NULL)
12477 return -1;
12478 }
12479
12480 /* Append a path separator to a directory. */
12481 if (mch_isdir(*fnamep))
12482 {
12483 /* Make room for one or two extra characters. */
12484 *fnamep = vim_strnsave(*fnamep, (int)STRLEN(*fnamep) + 2);
12485 vim_free(*bufp); /* free any allocated file name */
12486 *bufp = *fnamep;
12487 if (*fnamep == NULL)
12488 return -1;
12489 add_pathsep(*fnamep);
12490 }
12491 }
12492
12493 /* ":." - path relative to the current directory */
12494 /* ":~" - path relative to the home directory */
12495 /* ":8" - shortname path - postponed till after */
12496 while (src[*usedlen] == ':'
12497 && ((c = src[*usedlen + 1]) == '.' || c == '~' || c == '8'))
12498 {
12499 *usedlen += 2;
12500 if (c == '8')
12501 {
12502#ifdef WIN3264
12503 has_shortname = 1; /* Postpone this. */
12504#endif
12505 continue;
12506 }
12507 pbuf = NULL;
12508 /* Need full path first (use expand_env() to remove a "~/") */
12509 if (!has_fullname)
12510 {
12511 if (c == '.' && **fnamep == '~')
12512 p = pbuf = expand_env_save(*fnamep);
12513 else
12514 p = pbuf = FullName_save(*fnamep, FALSE);
12515 }
12516 else
12517 p = *fnamep;
12518
12519 has_fullname = 0;
12520
12521 if (p != NULL)
12522 {
12523 if (c == '.')
12524 {
12525 mch_dirname(dirname, MAXPATHL);
12526 s = shorten_fname(p, dirname);
12527 if (s != NULL)
12528 {
12529 *fnamep = s;
12530 if (pbuf != NULL)
12531 {
12532 vim_free(*bufp); /* free any allocated file name */
12533 *bufp = pbuf;
12534 pbuf = NULL;
12535 }
12536 }
12537 }
12538 else
12539 {
12540 home_replace(NULL, p, dirname, MAXPATHL, TRUE);
12541 /* Only replace it when it starts with '~' */
12542 if (*dirname == '~')
12543 {
12544 s = vim_strsave(dirname);
12545 if (s != NULL)
12546 {
12547 *fnamep = s;
12548 vim_free(*bufp);
12549 *bufp = s;
12550 }
12551 }
12552 }
12553 vim_free(pbuf);
12554 }
12555 }
12556
12557 tail = gettail(*fnamep);
12558 *fnamelen = (int)STRLEN(*fnamep);
12559
12560 /* ":h" - head, remove "/file_name", can be repeated */
12561 /* Don't remove the first "/" or "c:\" */
12562 while (src[*usedlen] == ':' && src[*usedlen + 1] == 'h')
12563 {
12564 valid |= VALID_HEAD;
12565 *usedlen += 2;
12566 s = get_past_head(*fnamep);
Bram Moolenaar1cd871b2004-12-19 22:46:22 +000012567 while (tail > s && after_pathsep(s, tail))
Bram Moolenaar071d4272004-06-13 20:20:40 +000012568 --tail;
12569 *fnamelen = (int)(tail - *fnamep);
12570#ifdef VMS
12571 if (*fnamelen > 0)
12572 *fnamelen += 1; /* the path separator is part of the path */
12573#endif
Bram Moolenaar1cd871b2004-12-19 22:46:22 +000012574 while (tail > s && !after_pathsep(s, tail))
12575 mb_ptr_back(*fnamep, tail);
Bram Moolenaar071d4272004-06-13 20:20:40 +000012576 }
12577
12578 /* ":8" - shortname */
12579 if (src[*usedlen] == ':' && src[*usedlen + 1] == '8')
12580 {
12581 *usedlen += 2;
12582#ifdef WIN3264
12583 has_shortname = 1;
12584#endif
12585 }
12586
12587#ifdef WIN3264
12588 /* Check shortname after we have done 'heads' and before we do 'tails'
12589 */
12590 if (has_shortname)
12591 {
12592 pbuf = NULL;
12593 /* Copy the string if it is shortened by :h */
12594 if (*fnamelen < (int)STRLEN(*fnamep))
12595 {
12596 p = vim_strnsave(*fnamep, *fnamelen);
12597 if (p == 0)
12598 return -1;
12599 vim_free(*bufp);
12600 *bufp = *fnamep = p;
12601 }
12602
12603 /* Split into two implementations - makes it easier. First is where
12604 * there isn't a full name already, second is where there is.
12605 */
12606 if (!has_fullname && !vim_isAbsName(*fnamep))
12607 {
12608 if (shortpath_for_partial(fnamep, bufp, fnamelen) == -1)
12609 return -1;
12610 }
12611 else
12612 {
12613 int l;
12614
12615 /* Simple case, already have the full-name
12616 * Nearly always shorter, so try first time. */
12617 l = *fnamelen;
12618 if (!get_short_pathname(fnamep, bufp, &l))
12619 return -1;
12620
12621 if (l == 0)
12622 {
12623 /* Couldn't find the filename.. search the paths.
12624 */
12625 l = *fnamelen;
12626 if (shortpath_for_invalid_fname(fnamep, bufp, &l ) == -1)
12627 return -1;
12628 }
12629 *fnamelen = l;
12630 }
12631 }
12632#endif /* WIN3264 */
12633
12634 /* ":t" - tail, just the basename */
12635 if (src[*usedlen] == ':' && src[*usedlen + 1] == 't')
12636 {
12637 *usedlen += 2;
12638 *fnamelen -= (int)(tail - *fnamep);
12639 *fnamep = tail;
12640 }
12641
12642 /* ":e" - extension, can be repeated */
12643 /* ":r" - root, without extension, can be repeated */
12644 while (src[*usedlen] == ':'
12645 && (src[*usedlen + 1] == 'e' || src[*usedlen + 1] == 'r'))
12646 {
12647 /* find a '.' in the tail:
12648 * - for second :e: before the current fname
12649 * - otherwise: The last '.'
12650 */
12651 if (src[*usedlen + 1] == 'e' && *fnamep > tail)
12652 s = *fnamep - 2;
12653 else
12654 s = *fnamep + *fnamelen - 1;
12655 for ( ; s > tail; --s)
12656 if (s[0] == '.')
12657 break;
12658 if (src[*usedlen + 1] == 'e') /* :e */
12659 {
12660 if (s > tail)
12661 {
12662 *fnamelen += (int)(*fnamep - (s + 1));
12663 *fnamep = s + 1;
12664#ifdef VMS
12665 /* cut version from the extension */
12666 s = *fnamep + *fnamelen - 1;
12667 for ( ; s > *fnamep; --s)
12668 if (s[0] == ';')
12669 break;
12670 if (s > *fnamep)
12671 *fnamelen = s - *fnamep;
12672#endif
12673 }
12674 else if (*fnamep <= tail)
12675 *fnamelen = 0;
12676 }
12677 else /* :r */
12678 {
12679 if (s > tail) /* remove one extension */
12680 *fnamelen = (int)(s - *fnamep);
12681 }
12682 *usedlen += 2;
12683 }
12684
12685 /* ":s?pat?foo?" - substitute */
12686 /* ":gs?pat?foo?" - global substitute */
12687 if (src[*usedlen] == ':'
12688 && (src[*usedlen + 1] == 's'
12689 || (src[*usedlen + 1] == 'g' && src[*usedlen + 2] == 's')))
12690 {
12691 char_u *str;
12692 char_u *pat;
12693 char_u *sub;
12694 int sep;
12695 char_u *flags;
12696 int didit = FALSE;
12697
12698 flags = (char_u *)"";
12699 s = src + *usedlen + 2;
12700 if (src[*usedlen + 1] == 'g')
12701 {
12702 flags = (char_u *)"g";
12703 ++s;
12704 }
12705
12706 sep = *s++;
12707 if (sep)
12708 {
12709 /* find end of pattern */
12710 p = vim_strchr(s, sep);
12711 if (p != NULL)
12712 {
12713 pat = vim_strnsave(s, (int)(p - s));
12714 if (pat != NULL)
12715 {
12716 s = p + 1;
12717 /* find end of substitution */
12718 p = vim_strchr(s, sep);
12719 if (p != NULL)
12720 {
12721 sub = vim_strnsave(s, (int)(p - s));
12722 str = vim_strnsave(*fnamep, *fnamelen);
12723 if (sub != NULL && str != NULL)
12724 {
12725 *usedlen = (int)(p + 1 - src);
12726 s = do_string_sub(str, pat, sub, flags);
12727 if (s != NULL)
12728 {
12729 *fnamep = s;
12730 *fnamelen = (int)STRLEN(s);
12731 vim_free(*bufp);
12732 *bufp = s;
12733 didit = TRUE;
12734 }
12735 }
12736 vim_free(sub);
12737 vim_free(str);
12738 }
12739 vim_free(pat);
12740 }
12741 }
12742 /* after using ":s", repeat all the modifiers */
12743 if (didit)
12744 goto repeat;
12745 }
12746 }
12747
12748 return valid;
12749}
12750
12751/*
12752 * Perform a substitution on "str" with pattern "pat" and substitute "sub".
12753 * "flags" can be "g" to do a global substitute.
12754 * Returns an allocated string, NULL for error.
12755 */
12756 char_u *
12757do_string_sub(str, pat, sub, flags)
12758 char_u *str;
12759 char_u *pat;
12760 char_u *sub;
12761 char_u *flags;
12762{
12763 int sublen;
12764 regmatch_T regmatch;
12765 int i;
12766 int do_all;
12767 char_u *tail;
12768 garray_T ga;
12769 char_u *ret;
12770 char_u *save_cpo;
12771
12772 /* Make 'cpoptions' empty, so that the 'l' flag doesn't work here */
12773 save_cpo = p_cpo;
12774 p_cpo = (char_u *)"";
12775
12776 ga_init2(&ga, 1, 200);
12777
12778 do_all = (flags[0] == 'g');
12779
12780 regmatch.rm_ic = p_ic;
12781 regmatch.regprog = vim_regcomp(pat, RE_MAGIC + RE_STRING);
12782 if (regmatch.regprog != NULL)
12783 {
12784 tail = str;
12785 while (vim_regexec_nl(&regmatch, str, (colnr_T)(tail - str)))
12786 {
12787 /*
12788 * Get some space for a temporary buffer to do the substitution
12789 * into. It will contain:
12790 * - The text up to where the match is.
12791 * - The substituted text.
12792 * - The text after the match.
12793 */
12794 sublen = vim_regsub(&regmatch, sub, tail, FALSE, TRUE, FALSE);
12795 if (ga_grow(&ga, (int)(STRLEN(tail) + sublen -
12796 (regmatch.endp[0] - regmatch.startp[0]))) == FAIL)
12797 {
12798 ga_clear(&ga);
12799 break;
12800 }
12801
12802 /* copy the text up to where the match is */
12803 i = (int)(regmatch.startp[0] - tail);
12804 mch_memmove((char_u *)ga.ga_data + ga.ga_len, tail, (size_t)i);
12805 /* add the substituted text */
12806 (void)vim_regsub(&regmatch, sub, (char_u *)ga.ga_data
12807 + ga.ga_len + i, TRUE, TRUE, FALSE);
12808 ga.ga_len += i + sublen - 1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012809 /* avoid getting stuck on a match with an empty string */
12810 if (tail == regmatch.endp[0])
12811 {
12812 if (*tail == NUL)
12813 break;
12814 *((char_u *)ga.ga_data + ga.ga_len) = *tail++;
12815 ++ga.ga_len;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012816 }
12817 else
12818 {
12819 tail = regmatch.endp[0];
12820 if (*tail == NUL)
12821 break;
12822 }
12823 if (!do_all)
12824 break;
12825 }
12826
12827 if (ga.ga_data != NULL)
12828 STRCPY((char *)ga.ga_data + ga.ga_len, tail);
12829
12830 vim_free(regmatch.regprog);
12831 }
12832
12833 ret = vim_strsave(ga.ga_data == NULL ? str : (char_u *)ga.ga_data);
12834 ga_clear(&ga);
12835 p_cpo = save_cpo;
12836
12837 return ret;
12838}
12839
12840#endif /* defined(FEAT_MODIFY_FNAME) || defined(FEAT_EVAL) */