blob: 5a3f70a1c862c782413752abbda120da62a79a82 [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));
Bram Moolenaar8a283e52005-01-06 23:28:25 +0000323static int list_equal __ARGS((listvar *l1, listvar *l2, int ic));
324static int tv_equal __ARGS((typeval *tv1, typeval *tv2, int ic));
Bram Moolenaar49cd9572005-01-03 21:06:01 +0000325static listitem *list_find __ARGS((listvar *l, long n));
Bram Moolenaar8a283e52005-01-06 23:28:25 +0000326static listitem *list_find_ext __ARGS((listvar *l, long *ip));
Bram Moolenaar49cd9572005-01-03 21:06:01 +0000327static void list_append __ARGS((listvar *l, listitem *item));
328static int list_append_tv __ARGS((listvar *l, typeval *tv));
Bram Moolenaar8a283e52005-01-06 23:28:25 +0000329static int list_insert_tv __ARGS((listvar *l, typeval *tv, listitem *item));
330static int list_extend __ARGS((listvar *l1, listvar *l2, listitem *bef));
331static int list_concat __ARGS((listvar *l1, listvar *l2, typeval *tv));
Bram Moolenaar49cd9572005-01-03 21:06:01 +0000332static listvar *list_copy __ARGS((listvar *orig, int deep));
Bram Moolenaar8a283e52005-01-06 23:28:25 +0000333static void list_getrem __ARGS((listvar *l, listitem *item, listitem *item2));
Bram Moolenaar49cd9572005-01-03 21:06:01 +0000334static char_u *list2string __ARGS((typeval *tv));
Bram Moolenaar8a283e52005-01-06 23:28:25 +0000335static char_u *tv2string __ARGS((typeval *tv, char_u **tofree, char_u *numbuf));
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000336static int get_env_tv __ARGS((char_u **arg, typeval *rettv, int evaluate));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000337static int find_internal_func __ARGS((char_u *name));
Bram Moolenaar49cd9572005-01-03 21:06:01 +0000338static char_u *deref_func_name __ARGS((char_u *name, int *lenp));
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000339static 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));
340static 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));
341static void f_append __ARGS((typeval *argvars, typeval *rettv));
342static void f_argc __ARGS((typeval *argvars, typeval *rettv));
343static void f_argidx __ARGS((typeval *argvars, typeval *rettv));
344static void f_argv __ARGS((typeval *argvars, typeval *rettv));
345static void f_browse __ARGS((typeval *argvars, typeval *rettv));
346static void f_browsedir __ARGS((typeval *argvars, typeval *rettv));
Bram Moolenaar49cd9572005-01-03 21:06:01 +0000347static buf_T *find_buffer __ARGS((typeval *avar));
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000348static void f_bufexists __ARGS((typeval *argvars, typeval *rettv));
349static void f_buflisted __ARGS((typeval *argvars, typeval *rettv));
350static void f_bufloaded __ARGS((typeval *argvars, typeval *rettv));
351static buf_T *get_buf_tv __ARGS((typeval *tv));
352static void f_bufname __ARGS((typeval *argvars, typeval *rettv));
353static void f_bufnr __ARGS((typeval *argvars, typeval *rettv));
354static void f_bufwinnr __ARGS((typeval *argvars, typeval *rettv));
355static void f_byte2line __ARGS((typeval *argvars, typeval *rettv));
356static void f_byteidx __ARGS((typeval *argvars, typeval *rettv));
Bram Moolenaar8a283e52005-01-06 23:28:25 +0000357static void f_call __ARGS((typeval *argvars, typeval *rettv));
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000358static void f_char2nr __ARGS((typeval *argvars, typeval *rettv));
359static void f_cindent __ARGS((typeval *argvars, typeval *rettv));
360static void f_col __ARGS((typeval *argvars, typeval *rettv));
361static void f_confirm __ARGS((typeval *argvars, typeval *rettv));
362static void f_copy __ARGS((typeval *argvars, typeval *rettv));
Bram Moolenaar8a283e52005-01-06 23:28:25 +0000363static void f_count __ARGS((typeval *argvars, typeval *rettv));
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000364static void f_cscope_connection __ARGS((typeval *argvars, typeval *rettv));
365static void f_cursor __ARGS((typeval *argsvars, typeval *rettv));
366static void f_deepcopy __ARGS((typeval *argvars, typeval *rettv));
367static void f_delete __ARGS((typeval *argvars, typeval *rettv));
368static void f_did_filetype __ARGS((typeval *argvars, typeval *rettv));
369static void f_diff_filler __ARGS((typeval *argvars, typeval *rettv));
370static void f_diff_hlID __ARGS((typeval *argvars, typeval *rettv));
371static void f_escape __ARGS((typeval *argvars, typeval *rettv));
372static void f_eventhandler __ARGS((typeval *argvars, typeval *rettv));
373static void f_executable __ARGS((typeval *argvars, typeval *rettv));
374static void f_exists __ARGS((typeval *argvars, typeval *rettv));
375static void f_expand __ARGS((typeval *argvars, typeval *rettv));
Bram Moolenaar8a283e52005-01-06 23:28:25 +0000376static void f_extend __ARGS((typeval *argvars, typeval *rettv));
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000377static void f_filereadable __ARGS((typeval *argvars, typeval *rettv));
378static void f_filewritable __ARGS((typeval *argvars, typeval *rettv));
379static void f_finddir __ARGS((typeval *argvars, typeval *rettv));
380static void f_findfile __ARGS((typeval *argvars, typeval *rettv));
381static void f_findfilendir __ARGS((typeval *argvars, typeval *rettv, int dir));
382static void f_fnamemodify __ARGS((typeval *argvars, typeval *rettv));
383static void f_foldclosed __ARGS((typeval *argvars, typeval *rettv));
384static void f_foldclosedend __ARGS((typeval *argvars, typeval *rettv));
385static void foldclosed_both __ARGS((typeval *argvars, typeval *rettv, int end));
386static void f_foldlevel __ARGS((typeval *argvars, typeval *rettv));
387static void f_foldtext __ARGS((typeval *argvars, typeval *rettv));
388static void f_foldtextresult __ARGS((typeval *argvars, typeval *rettv));
389static void f_foreground __ARGS((typeval *argvars, typeval *rettv));
390static void f_function __ARGS((typeval *argvars, typeval *rettv));
391static void f_getbufvar __ARGS((typeval *argvars, typeval *rettv));
392static void f_getchar __ARGS((typeval *argvars, typeval *rettv));
393static void f_getcharmod __ARGS((typeval *argvars, typeval *rettv));
394static void f_getcmdline __ARGS((typeval *argvars, typeval *rettv));
395static void f_getcmdpos __ARGS((typeval *argvars, typeval *rettv));
396static void f_getcwd __ARGS((typeval *argvars, typeval *rettv));
397static void f_getfontname __ARGS((typeval *argvars, typeval *rettv));
398static void f_getfperm __ARGS((typeval *argvars, typeval *rettv));
399static void f_getfsize __ARGS((typeval *argvars, typeval *rettv));
400static void f_getftime __ARGS((typeval *argvars, typeval *rettv));
401static void f_getftype __ARGS((typeval *argvars, typeval *rettv));
402static void f_getline __ARGS((typeval *argvars, typeval *rettv));
403static void f_getreg __ARGS((typeval *argvars, typeval *rettv));
404static void f_getregtype __ARGS((typeval *argvars, typeval *rettv));
405static void f_getwinposx __ARGS((typeval *argvars, typeval *rettv));
406static void f_getwinposy __ARGS((typeval *argvars, typeval *rettv));
407static void f_getwinvar __ARGS((typeval *argvars, typeval *rettv));
408static void f_glob __ARGS((typeval *argvars, typeval *rettv));
409static void f_globpath __ARGS((typeval *argvars, typeval *rettv));
410static void f_has __ARGS((typeval *argvars, typeval *rettv));
411static void f_hasmapto __ARGS((typeval *argvars, typeval *rettv));
412static void f_histadd __ARGS((typeval *argvars, typeval *rettv));
413static void f_histdel __ARGS((typeval *argvars, typeval *rettv));
414static void f_histget __ARGS((typeval *argvars, typeval *rettv));
415static void f_histnr __ARGS((typeval *argvars, typeval *rettv));
416static void f_hlexists __ARGS((typeval *argvars, typeval *rettv));
417static void f_hlID __ARGS((typeval *argvars, typeval *rettv));
418static void f_hostname __ARGS((typeval *argvars, typeval *rettv));
419static void f_iconv __ARGS((typeval *argvars, typeval *rettv));
420static void f_indent __ARGS((typeval *argvars, typeval *rettv));
421static void f_insert __ARGS((typeval *argvars, typeval *rettv));
422static void f_isdirectory __ARGS((typeval *argvars, typeval *rettv));
Bram Moolenaar8a283e52005-01-06 23:28:25 +0000423static void f_index __ARGS((typeval *argvars, typeval *rettv));
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000424static void f_input __ARGS((typeval *argvars, typeval *rettv));
425static void f_inputdialog __ARGS((typeval *argvars, typeval *rettv));
426static void f_inputrestore __ARGS((typeval *argvars, typeval *rettv));
427static void f_inputsave __ARGS((typeval *argvars, typeval *rettv));
428static void f_inputsecret __ARGS((typeval *argvars, typeval *rettv));
429static void f_last_buffer_nr __ARGS((typeval *argvars, typeval *rettv));
430static void f_len __ARGS((typeval *argvars, typeval *rettv));
431static void f_libcall __ARGS((typeval *argvars, typeval *rettv));
432static void f_libcallnr __ARGS((typeval *argvars, typeval *rettv));
433static void libcall_common __ARGS((typeval *argvars, typeval *rettv, int type));
434static void f_line __ARGS((typeval *argvars, typeval *rettv));
435static void f_line2byte __ARGS((typeval *argvars, typeval *rettv));
436static void f_lispindent __ARGS((typeval *argvars, typeval *rettv));
437static void f_localtime __ARGS((typeval *argvars, typeval *rettv));
438static void f_maparg __ARGS((typeval *argvars, typeval *rettv));
439static void f_mapcheck __ARGS((typeval *argvars, typeval *rettv));
440static void get_maparg __ARGS((typeval *argvars, typeval *rettv, int exact));
441static void f_match __ARGS((typeval *argvars, typeval *rettv));
442static void f_matchend __ARGS((typeval *argvars, typeval *rettv));
443static void f_matchstr __ARGS((typeval *argvars, typeval *rettv));
444static void f_mode __ARGS((typeval *argvars, typeval *rettv));
445static void f_nextnonblank __ARGS((typeval *argvars, typeval *rettv));
446static void f_nr2char __ARGS((typeval *argvars, typeval *rettv));
447static void f_prevnonblank __ARGS((typeval *argvars, typeval *rettv));
448static void f_setbufvar __ARGS((typeval *argvars, typeval *rettv));
449static void f_setcmdpos __ARGS((typeval *argvars, typeval *rettv));
450static void f_setwinvar __ARGS((typeval *argvars, typeval *rettv));
451static void f_remove __ARGS((typeval *argvars, typeval *rettv));
452static void f_rename __ARGS((typeval *argvars, typeval *rettv));
Bram Moolenaar8a283e52005-01-06 23:28:25 +0000453static void f_repeat __ARGS((typeval *argvars, typeval *rettv));
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000454static void f_resolve __ARGS((typeval *argvars, typeval *rettv));
455static void f_search __ARGS((typeval *argvars, typeval *rettv));
456static void f_searchpair __ARGS((typeval *argvars, typeval *rettv));
Bram Moolenaar49cd9572005-01-03 21:06:01 +0000457static int get_search_arg __ARGS((typeval *varp, int *flagsp));
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000458static void f_remote_expr __ARGS((typeval *argvars, typeval *rettv));
459static void f_remote_foreground __ARGS((typeval *argvars, typeval *rettv));
460static void f_remote_peek __ARGS((typeval *argvars, typeval *rettv));
461static void f_remote_read __ARGS((typeval *argvars, typeval *rettv));
462static void f_remote_send __ARGS((typeval *argvars, typeval *rettv));
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000463static void f_server2client __ARGS((typeval *argvars, typeval *rettv));
464static void f_serverlist __ARGS((typeval *argvars, typeval *rettv));
465static void f_setline __ARGS((typeval *argvars, typeval *rettv));
466static void f_setreg __ARGS((typeval *argvars, typeval *rettv));
467static void f_simplify __ARGS((typeval *argvars, typeval *rettv));
468static void find_some_match __ARGS((typeval *argvars, typeval *rettv, int start));
469static void f_strftime __ARGS((typeval *argvars, typeval *rettv));
470static void f_stridx __ARGS((typeval *argvars, typeval *rettv));
471static void f_string __ARGS((typeval *argvars, typeval *rettv));
472static void f_strlen __ARGS((typeval *argvars, typeval *rettv));
473static void f_strpart __ARGS((typeval *argvars, typeval *rettv));
474static void f_strridx __ARGS((typeval *argvars, typeval *rettv));
475static void f_strtrans __ARGS((typeval *argvars, typeval *rettv));
476static void f_synID __ARGS((typeval *argvars, typeval *rettv));
477static void f_synIDattr __ARGS((typeval *argvars, typeval *rettv));
478static void f_synIDtrans __ARGS((typeval *argvars, typeval *rettv));
479static void f_system __ARGS((typeval *argvars, typeval *rettv));
480static void f_submatch __ARGS((typeval *argvars, typeval *rettv));
481static void f_substitute __ARGS((typeval *argvars, typeval *rettv));
482static void f_tempname __ARGS((typeval *argvars, typeval *rettv));
483static void f_tolower __ARGS((typeval *argvars, typeval *rettv));
484static void f_toupper __ARGS((typeval *argvars, typeval *rettv));
485static void f_tr __ARGS((typeval *argvars, typeval *rettv));
486static void f_type __ARGS((typeval *argvars, typeval *rettv));
487static void f_virtcol __ARGS((typeval *argvars, typeval *rettv));
488static void f_visualmode __ARGS((typeval *argvars, typeval *rettv));
489static void f_winbufnr __ARGS((typeval *argvars, typeval *rettv));
490static void f_wincol __ARGS((typeval *argvars, typeval *rettv));
491static void f_winheight __ARGS((typeval *argvars, typeval *rettv));
492static void f_winline __ARGS((typeval *argvars, typeval *rettv));
493static void f_winnr __ARGS((typeval *argvars, typeval *rettv));
494static void f_winrestcmd __ARGS((typeval *argvars, typeval *rettv));
495static void f_winwidth __ARGS((typeval *argvars, typeval *rettv));
Bram Moolenaar49cd9572005-01-03 21:06:01 +0000496static win_T *find_win_by_nr __ARGS((typeval *vp));
497static pos_T *var2fpos __ARGS((typeval *varp, int lnum));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000498static int get_env_len __ARGS((char_u **arg));
499static int get_id_len __ARGS((char_u **arg));
500static int get_func_len __ARGS((char_u **arg, char_u **alias, int evaluate));
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000501static 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 +0000502static int eval_isnamec __ARGS((int c));
503static int find_vim_var __ARGS((char_u *name, int len));
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000504static int get_var_tv __ARGS((char_u *name, int len, typeval *rettv));
505static typeval *alloc_tv __ARGS((void));
506static typeval *alloc_string_tv __ARGS((char_u *string));
507static void free_tv __ARGS((typeval *varp));
508static void clear_tv __ARGS((typeval *varp));
509static void init_tv __ARGS((typeval *varp));
510static long get_tv_number __ARGS((typeval *varp));
511static linenr_T get_tv_lnum __ARGS((typeval *argvars));
512static char_u *get_tv_string __ARGS((typeval *varp));
513static char_u *get_tv_string_buf __ARGS((typeval *varp, char_u *buf));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000514static VAR find_var __ARGS((char_u *name, int writing));
515static VAR find_var_in_ga __ARGS((garray_T *gap, char_u *varname));
516static garray_T *find_var_ga __ARGS((char_u *name, char_u **varname));
Bram Moolenaar49cd9572005-01-03 21:06:01 +0000517static void clear_var __ARGS((VAR v));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000518static void list_one_var __ARGS((VAR v, char_u *prefix));
519static void list_vim_var __ARGS((int i));
520static void list_one_var_a __ARGS((char_u *prefix, char_u *name, int type, char_u *string));
Bram Moolenaar49cd9572005-01-03 21:06:01 +0000521static void set_var __ARGS((char_u *name, typeval *varp, int copy));
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000522static void copy_tv __ARGS((typeval *from, typeval *to));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000523static char_u *find_option_end __ARGS((char_u **arg, int *opt_flags));
524static char_u *trans_function_name __ARGS((char_u **pp, int skip, int internal));
525static int eval_fname_script __ARGS((char_u *p));
526static int eval_fname_sid __ARGS((char_u *p));
527static void list_func_head __ARGS((ufunc_T *fp, int indent));
528static void cat_func_name __ARGS((char_u *buf, ufunc_T *fp));
529static ufunc_T *find_func __ARGS((char_u *name));
Bram Moolenaar49cd9572005-01-03 21:06:01 +0000530static int function_exists __ARGS((char_u *name));
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000531static 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 +0000532
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000533#define get_var_string(p) get_tv_string(&(p)->tv)
534#define get_var_string_buf(p, b) get_tv_string_buf(&(p)->tv, (b))
535#define get_var_number(p) get_tv_number(&((p)->tv))
Bram Moolenaar071d4272004-06-13 20:20:40 +0000536
Bram Moolenaar071d4272004-06-13 20:20:40 +0000537static 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 +0000538
Bram Moolenaar3d60ec22005-01-05 22:19:46 +0000539static int ex_let_vars __ARGS((char_u *arg, typeval *tv, int copy, int semicolon, int var_count, char_u *nextchars));
540static char_u *skip_var_list __ARGS((char_u *arg, int *var_count, int *semicolon));
541static char_u *skip_var_one __ARGS((char_u *arg));
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000542static void list_all_vars __ARGS((void));
543static char_u *list_arg_vars __ARGS((exarg_T *eap, char_u *arg));
544static char_u *ex_let_one __ARGS((char_u *arg, typeval *tv, int copy, char_u *endchars));
545static 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 +0000546static void list_add_watch __ARGS((listvar *l, listwatch *lw));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000547
548/*
549 * Set an internal variable to a string value. Creates the variable if it does
550 * not already exist.
551 */
552 void
553set_internal_string_var(name, value)
554 char_u *name;
555 char_u *value;
556{
Bram Moolenaar49cd9572005-01-03 21:06:01 +0000557 char_u *val;
558 typeval *tvp;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000559
560 val = vim_strsave(value);
561 if (val != NULL)
562 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000563 tvp = alloc_string_tv(val);
Bram Moolenaar49cd9572005-01-03 21:06:01 +0000564 if (tvp != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000565 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +0000566 set_var(name, tvp, FALSE);
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000567 free_tv(tvp);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000568 }
569 }
570}
571
572# if defined(FEAT_MBYTE) || defined(PROTO)
573 int
574eval_charconvert(enc_from, enc_to, fname_from, fname_to)
575 char_u *enc_from;
576 char_u *enc_to;
577 char_u *fname_from;
578 char_u *fname_to;
579{
580 int err = FALSE;
581
582 set_vim_var_string(VV_CC_FROM, enc_from, -1);
583 set_vim_var_string(VV_CC_TO, enc_to, -1);
584 set_vim_var_string(VV_FNAME_IN, fname_from, -1);
585 set_vim_var_string(VV_FNAME_OUT, fname_to, -1);
586 if (eval_to_bool(p_ccv, &err, NULL, FALSE))
587 err = TRUE;
588 set_vim_var_string(VV_CC_FROM, NULL, -1);
589 set_vim_var_string(VV_CC_TO, NULL, -1);
590 set_vim_var_string(VV_FNAME_IN, NULL, -1);
591 set_vim_var_string(VV_FNAME_OUT, NULL, -1);
592
593 if (err)
594 return FAIL;
595 return OK;
596}
597# endif
598
599# if defined(FEAT_POSTSCRIPT) || defined(PROTO)
600 int
601eval_printexpr(fname, args)
602 char_u *fname;
603 char_u *args;
604{
605 int err = FALSE;
606
607 set_vim_var_string(VV_FNAME_IN, fname, -1);
608 set_vim_var_string(VV_CMDARG, args, -1);
609 if (eval_to_bool(p_pexpr, &err, NULL, FALSE))
610 err = TRUE;
611 set_vim_var_string(VV_FNAME_IN, NULL, -1);
612 set_vim_var_string(VV_CMDARG, NULL, -1);
613
614 if (err)
615 {
616 mch_remove(fname);
617 return FAIL;
618 }
619 return OK;
620}
621# endif
622
623# if defined(FEAT_DIFF) || defined(PROTO)
624 void
625eval_diff(origfile, newfile, outfile)
626 char_u *origfile;
627 char_u *newfile;
628 char_u *outfile;
629{
630 int err = FALSE;
631
632 set_vim_var_string(VV_FNAME_IN, origfile, -1);
633 set_vim_var_string(VV_FNAME_NEW, newfile, -1);
634 set_vim_var_string(VV_FNAME_OUT, outfile, -1);
635 (void)eval_to_bool(p_dex, &err, NULL, FALSE);
636 set_vim_var_string(VV_FNAME_IN, NULL, -1);
637 set_vim_var_string(VV_FNAME_NEW, NULL, -1);
638 set_vim_var_string(VV_FNAME_OUT, NULL, -1);
639}
640
641 void
642eval_patch(origfile, difffile, outfile)
643 char_u *origfile;
644 char_u *difffile;
645 char_u *outfile;
646{
647 int err;
648
649 set_vim_var_string(VV_FNAME_IN, origfile, -1);
650 set_vim_var_string(VV_FNAME_DIFF, difffile, -1);
651 set_vim_var_string(VV_FNAME_OUT, outfile, -1);
652 (void)eval_to_bool(p_pex, &err, NULL, FALSE);
653 set_vim_var_string(VV_FNAME_IN, NULL, -1);
654 set_vim_var_string(VV_FNAME_DIFF, NULL, -1);
655 set_vim_var_string(VV_FNAME_OUT, NULL, -1);
656}
657# endif
658
659/*
660 * Top level evaluation function, returning a boolean.
661 * Sets "error" to TRUE if there was an error.
662 * Return TRUE or FALSE.
663 */
664 int
665eval_to_bool(arg, error, nextcmd, skip)
666 char_u *arg;
667 int *error;
668 char_u **nextcmd;
669 int skip; /* only parse, don't execute */
670{
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000671 typeval tv;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000672 int retval = FALSE;
673
674 if (skip)
675 ++emsg_skip;
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000676 if (eval0(arg, &tv, nextcmd, !skip) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000677 *error = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000678 else
679 {
680 *error = FALSE;
681 if (!skip)
682 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000683 retval = (get_tv_number(&tv) != 0);
684 clear_tv(&tv);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000685 }
686 }
687 if (skip)
688 --emsg_skip;
689
690 return retval;
691}
692
693/*
694 * Top level evaluation function, returning a string. If "skip" is TRUE,
695 * only parsing to "nextcmd" is done, without reporting errors. Return
696 * pointer to allocated memory, or NULL for failure or when "skip" is TRUE.
697 */
698 char_u *
699eval_to_string_skip(arg, nextcmd, skip)
700 char_u *arg;
701 char_u **nextcmd;
702 int skip; /* only parse, don't execute */
703{
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000704 typeval tv;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000705 char_u *retval;
706
707 if (skip)
708 ++emsg_skip;
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000709 if (eval0(arg, &tv, nextcmd, !skip) == FAIL || skip)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000710 retval = NULL;
711 else
712 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000713 retval = vim_strsave(get_tv_string(&tv));
714 clear_tv(&tv);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000715 }
716 if (skip)
717 --emsg_skip;
718
719 return retval;
720}
721
722/*
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000723 * Skip over an expression at "*pp".
724 * Return FAIL for an error, OK otherwise.
725 */
726 int
727skip_expr(pp)
728 char_u **pp;
729{
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000730 typeval rettv;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000731
732 *pp = skipwhite(*pp);
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000733 return eval1(pp, &rettv, FALSE);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000734}
735
736/*
Bram Moolenaar071d4272004-06-13 20:20:40 +0000737 * Top level evaluation function, returning a string.
738 * Return pointer to allocated memory, or NULL for failure.
739 */
740 char_u *
741eval_to_string(arg, nextcmd)
742 char_u *arg;
743 char_u **nextcmd;
744{
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000745 typeval tv;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000746 char_u *retval;
747
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000748 if (eval0(arg, &tv, nextcmd, TRUE) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000749 retval = NULL;
750 else
751 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000752 retval = vim_strsave(get_tv_string(&tv));
753 clear_tv(&tv);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000754 }
755
756 return retval;
757}
758
759/*
760 * Call eval_to_string() with "sandbox" set and not using local variables.
761 */
762 char_u *
763eval_to_string_safe(arg, nextcmd)
764 char_u *arg;
765 char_u **nextcmd;
766{
767 char_u *retval;
768 void *save_funccalp;
769
770 save_funccalp = save_funccal();
771 ++sandbox;
772 retval = eval_to_string(arg, nextcmd);
773 --sandbox;
774 restore_funccal(save_funccalp);
775 return retval;
776}
777
778#if 0 /* not used */
779/*
780 * Top level evaluation function, returning a string.
781 * Advances "arg" to the first non-blank after the evaluated expression.
782 * Return pointer to allocated memory, or NULL for failure.
783 * Doesn't give error messages.
784 */
785 char_u *
786eval_arg_to_string(arg)
787 char_u **arg;
788{
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000789 typeval rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000790 char_u *retval;
791 int ret;
792
793 ++emsg_off;
794
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000795 ret = eval1(arg, &rettv, TRUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000796 if (ret == FAIL)
797 retval = NULL;
798 else
799 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000800 retval = vim_strsave(get_tv_string(&rettv));
801 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000802 }
803
804 --emsg_off;
805
806 return retval;
807}
808#endif
809
810/*
811 * Top level evaluation function, returning a number.
812 * Evaluates "expr" silently.
813 * Returns -1 for an error.
814 */
815 int
816eval_to_number(expr)
817 char_u *expr;
818{
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000819 typeval rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000820 int retval;
821 char_u *p = expr;
822
823 ++emsg_off;
824
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000825 if (eval1(&p, &rettv, TRUE) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000826 retval = -1;
827 else
828 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000829 retval = get_tv_number(&rettv);
830 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000831 }
832 --emsg_off;
833
834 return retval;
835}
836
837#if (defined(FEAT_USR_CMDS) && defined(FEAT_CMDL_COMPL)) || defined(PROTO)
838/*
839 * Call some vimL function and return the result as a string
840 * Uses argv[argc] for the function arguments.
841 */
842 char_u *
843call_vim_function(func, argc, argv, safe)
844 char_u *func;
845 int argc;
846 char_u **argv;
847 int safe; /* use the sandbox */
848{
849 char_u *retval = NULL;
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000850 typeval rettv;
Bram Moolenaar49cd9572005-01-03 21:06:01 +0000851 typeval *argvars;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000852 long n;
853 int len;
854 int i;
855 int doesrange;
856 void *save_funccalp = NULL;
857
Bram Moolenaar49cd9572005-01-03 21:06:01 +0000858 argvars = (typeval *)alloc((unsigned)(argc * sizeof(typeval)));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000859 if (argvars == NULL)
860 return NULL;
861
862 for (i = 0; i < argc; i++)
863 {
Bram Moolenaarcfbc5ee2004-07-02 15:38:35 +0000864 /* Pass a NULL or empty argument as an empty string */
865 if (argv[i] == NULL || *argv[i] == NUL)
866 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +0000867 argvars[i].v_type = VAR_STRING;
868 argvars[i].vval.v_string = (char_u *)"";
Bram Moolenaarcfbc5ee2004-07-02 15:38:35 +0000869 continue;
870 }
871
Bram Moolenaar071d4272004-06-13 20:20:40 +0000872 /* Recognize a number argument, the others must be strings. */
873 vim_str2nr(argv[i], NULL, &len, TRUE, TRUE, &n, NULL);
874 if (len != 0 && len == (int)STRLEN(argv[i]))
875 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +0000876 argvars[i].v_type = VAR_NUMBER;
877 argvars[i].vval.v_number = n;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000878 }
879 else
880 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +0000881 argvars[i].v_type = VAR_STRING;
882 argvars[i].vval.v_string = argv[i];
Bram Moolenaar071d4272004-06-13 20:20:40 +0000883 }
884 }
885
886 if (safe)
887 {
888 save_funccalp = save_funccal();
889 ++sandbox;
890 }
891
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000892 rettv.v_type = VAR_UNKNOWN; /* clear_tv() uses this */
893 if (call_func(func, (int)STRLEN(func), &rettv, argc, argvars,
Bram Moolenaar071d4272004-06-13 20:20:40 +0000894 curwin->w_cursor.lnum, curwin->w_cursor.lnum,
895 &doesrange, TRUE) == OK)
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000896 retval = vim_strsave(get_tv_string(&rettv));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000897
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000898 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000899 vim_free(argvars);
900
901 if (safe)
902 {
903 --sandbox;
904 restore_funccal(save_funccalp);
905 }
906 return retval;
907}
908#endif
909
910/*
911 * Save the current function call pointer, and set it to NULL.
912 * Used when executing autocommands and for ":source".
913 */
914 void *
915save_funccal()
916{
917 struct funccall *fc;
918
919 fc = current_funccal;
920 current_funccal = NULL;
921 return (void *)fc;
922}
923
924 void
925restore_funccal(fc)
926 void *fc;
927{
928 current_funccal = (struct funccall *)fc;
929}
930
931#ifdef FEAT_FOLDING
932/*
933 * Evaluate 'foldexpr'. Returns the foldlevel, and any character preceding
934 * it in "*cp". Doesn't give error messages.
935 */
936 int
937eval_foldexpr(arg, cp)
938 char_u *arg;
939 int *cp;
940{
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000941 typeval tv;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000942 int retval;
943 char_u *s;
944
945 ++emsg_off;
946 ++sandbox;
947 *cp = NUL;
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000948 if (eval0(arg, &tv, NULL, TRUE) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000949 retval = 0;
950 else
951 {
952 /* If the result is a number, just return the number. */
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000953 if (tv.v_type == VAR_NUMBER)
954 retval = tv.vval.v_number;
955 else if (tv.v_type == VAR_UNKNOWN
956 || tv.vval.v_string == NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000957 retval = 0;
958 else
959 {
960 /* If the result is a string, check if there is a non-digit before
961 * the number. */
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000962 s = tv.vval.v_string;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000963 if (!VIM_ISDIGIT(*s) && *s != '-')
964 *cp = *s++;
965 retval = atol((char *)s);
966 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000967 clear_tv(&tv);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000968 }
969 --emsg_off;
970 --sandbox;
971
972 return retval;
973}
974#endif
975
Bram Moolenaar071d4272004-06-13 20:20:40 +0000976/*
977 * Expands out the 'magic' {}'s in a variable/function name.
978 * Note that this can call itself recursively, to deal with
979 * constructs like foo{bar}{baz}{bam}
980 * The four pointer arguments point to "foo{expre}ss{ion}bar"
981 * "in_start" ^
982 * "expr_start" ^
983 * "expr_end" ^
984 * "in_end" ^
985 *
986 * Returns a new allocated string, which the caller must free.
987 * Returns NULL for failure.
988 */
989 static char_u *
990make_expanded_name(in_start, expr_start, expr_end, in_end)
991 char_u *in_start;
992 char_u *expr_start;
993 char_u *expr_end;
994 char_u *in_end;
995{
996 char_u c1;
997 char_u *retval = NULL;
998 char_u *temp_result;
999 char_u *nextcmd = NULL;
1000
1001 if (expr_end == NULL || in_end == NULL)
1002 return NULL;
1003 *expr_start = NUL;
1004 *expr_end = NUL;
1005 c1 = *in_end;
1006 *in_end = NUL;
1007
1008 temp_result = eval_to_string(expr_start + 1, &nextcmd);
1009 if (temp_result != NULL && nextcmd == NULL)
1010 {
1011 retval = alloc((unsigned)(STRLEN(temp_result) + (expr_start - in_start)
1012 + (in_end - expr_end) + 1));
1013
1014 if (retval != NULL)
1015 {
1016 STRCPY(retval, in_start);
1017 STRCAT(retval, temp_result);
1018 STRCAT(retval, expr_end + 1);
1019 }
1020 }
1021 vim_free(temp_result);
1022
1023 *in_end = c1; /* put char back for error messages */
1024 *expr_start = '{';
1025 *expr_end = '}';
1026
1027 if (retval != NULL)
1028 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001029 temp_result = find_name_end(retval, &expr_start, &expr_end, FALSE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001030 if (expr_start != NULL)
1031 {
1032 /* Further expansion! */
1033 temp_result = make_expanded_name(retval, expr_start,
1034 expr_end, temp_result);
1035 vim_free(retval);
1036 retval = temp_result;
1037 }
1038 }
1039
1040 return retval;
1041
1042}
Bram Moolenaar071d4272004-06-13 20:20:40 +00001043
1044/*
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001045 * ":let" list all variable values
1046 * ":let var1 var2" list variable values
1047 * ":let var = expr" assignment command.
1048 * ":let [var1, var2] = expr" unpack list.
Bram Moolenaar071d4272004-06-13 20:20:40 +00001049 */
1050 void
1051ex_let(eap)
1052 exarg_T *eap;
1053{
1054 char_u *arg = eap->arg;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001055 char_u *expr = NULL;
1056 typeval rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001057 int i;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001058 int var_count = 0;
1059 int semicolon = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001060
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001061 expr = skip_var_list(arg, &var_count, &semicolon);
1062 if (expr == NULL)
1063 return;
1064 expr = vim_strchr(expr, '=');
1065 if (expr == NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001066 {
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001067 if (*arg == '[')
1068 EMSG(_(e_invarg));
1069 else if (!ends_excmd(*arg))
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001070 /* ":let var1 var2" */
1071 arg = list_arg_vars(eap, arg);
1072 else if (!eap->skip)
1073 /* ":let" */
1074 list_all_vars();
Bram Moolenaar071d4272004-06-13 20:20:40 +00001075 eap->nextcmd = check_nextcmd(arg);
1076 }
1077 else
1078 {
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001079 expr = skipwhite(expr + 1);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001080
Bram Moolenaar071d4272004-06-13 20:20:40 +00001081 if (eap->skip)
1082 ++emsg_skip;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001083 i = eval0(expr, &rettv, &eap->nextcmd, !eap->skip);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001084 if (eap->skip)
1085 {
1086 if (i != FAIL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001087 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001088 --emsg_skip;
1089 }
1090 else if (i != FAIL)
1091 {
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001092 (void)ex_let_vars(eap->arg, &rettv, FALSE, semicolon, var_count,
1093 (char_u *)"=");
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001094 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001095 }
1096 }
1097}
1098
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001099/*
1100 * Assign the typevalue "tv" to the variable or variables at "arg_start".
1101 * Handles both "var" with any type and "[var, var; var]" with a list type.
1102 * Returns OK or FAIL;
1103 */
1104 static int
1105ex_let_vars(arg_start, tv, copy, semicolon, var_count, nextchars)
1106 char_u *arg_start;
1107 typeval *tv;
1108 int copy; /* copy values from "tv", don't move */
1109 int semicolon; /* from skip_var_list() */
1110 int var_count; /* from skip_var_list() */
1111 char_u *nextchars; /* characters that must follow or NULL */
1112{
1113 char_u *arg = arg_start;
1114 listvar *l;
1115 int i;
1116 listitem *item;
1117 typeval ltv;
1118
1119 if (*arg != '[')
1120 {
1121 /*
1122 * ":let var = expr" or ":for var in list"
1123 */
1124 if (ex_let_one(arg, tv, copy, nextchars) == NULL)
1125 return FAIL;
1126 return OK;
1127 }
1128
1129 /*
1130 * ":let [v1, v2] = list" or ":for [v1, v2] in listlist"
1131 */
1132 l = tv->vval.v_list;
1133 if (tv->v_type != VAR_LIST || l == NULL)
1134 {
1135 EMSG(_(e_listreq));
1136 return FAIL;
1137 }
1138
1139 i = list_len(l);
1140 if (semicolon == 0 && var_count < i)
1141 {
1142 EMSG(_("E999: Less targets than List items"));
1143 return FAIL;
1144 }
1145 if (var_count - semicolon > i)
1146 {
1147 EMSG(_("E999: More targets than List items"));
1148 return FAIL;
1149 }
1150
1151 item = l->lv_first;
1152 while (*arg != ']')
1153 {
1154 arg = skipwhite(arg + 1);
1155 arg = ex_let_one(arg, &item->li_tv, TRUE, (char_u *)",;]");
1156 item = item->li_next;
1157 if (arg == NULL)
1158 return FAIL;
1159
1160 arg = skipwhite(arg);
1161 if (*arg == ';')
1162 {
1163 /* Put the rest of the list (may be empty) in the var after ';'.
1164 * Create a new list for this. */
1165 l = list_alloc();
1166 if (l == NULL)
1167 return FAIL;
1168 while (item != NULL)
1169 {
1170 list_append_tv(l, &item->li_tv);
1171 item = item->li_next;
1172 }
1173
1174 ltv.v_type = VAR_LIST;
1175 ltv.vval.v_list = l;
1176 l->lv_refcount = 1;
1177
1178 arg = ex_let_one(skipwhite(arg + 1), &ltv, FALSE, (char_u *)"]");
1179 clear_tv(&ltv);
1180 if (arg == NULL)
1181 return FAIL;
1182 break;
1183 }
1184 else if (*arg != ',' && *arg != ']')
1185 {
1186 EMSG2(_(e_intern2), "ex_let_vars()");
1187 return FAIL;
1188 }
1189 }
1190
1191 return OK;
1192}
1193
1194/*
1195 * Skip over assignable variable "var" or list of variables "[var, var]".
1196 * Used for ":let varvar = expr" and ":for varvar in expr".
1197 * For "[var, var]" increment "*var_count" for each variable.
1198 * for "[var, var; var]" set "semicolon".
1199 * Return NULL for an error.
1200 */
1201 static char_u *
1202skip_var_list(arg, var_count, semicolon)
1203 char_u *arg;
1204 int *var_count;
1205 int *semicolon;
1206{
1207 char_u *p, *s;
1208
1209 if (*arg == '[')
1210 {
1211 /* "[var, var]": find the matching ']'. */
1212 p = arg;
1213 while (1)
1214 {
1215 p = skipwhite(p + 1); /* skip whites after '[', ';' or ',' */
1216 s = skip_var_one(p);
1217 if (s == p)
1218 {
1219 EMSG2(_(e_invarg2), p);
1220 return NULL;
1221 }
1222 ++*var_count;
1223
1224 p = skipwhite(s);
1225 if (*p == ']')
1226 break;
1227 else if (*p == ';')
1228 {
1229 if (*semicolon == 1)
1230 {
1231 EMSG(_("Double ; in list of variables"));
1232 return NULL;
1233 }
1234 *semicolon = 1;
1235 }
1236 else if (*p != ',')
1237 {
1238 EMSG2(_(e_invarg2), p);
1239 return NULL;
1240 }
1241 }
1242 return p + 1;
1243 }
1244 else
1245 return skip_var_one(arg);
1246}
1247
1248 static char_u *
1249skip_var_one(arg)
1250 char_u *arg;
1251{
1252 if (vim_strchr((char_u *)"$@&", *arg) != NULL)
1253 ++arg;
1254 return find_name_end(arg, NULL, NULL, TRUE);
1255}
1256
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001257 static void
1258list_all_vars()
1259{
1260 int i;
1261
1262 /*
1263 * List all variables.
1264 */
1265 for (i = 0; i < variables.ga_len && !got_int; ++i)
1266 if (VAR_ENTRY(i).v_name != NULL)
1267 list_one_var(&VAR_ENTRY(i), (char_u *)"");
1268 for (i = 0; i < curbuf->b_vars.ga_len && !got_int; ++i)
1269 if (BVAR_ENTRY(i).v_name != NULL)
1270 list_one_var(&BVAR_ENTRY(i), (char_u *)"b:");
1271 for (i = 0; i < curwin->w_vars.ga_len && !got_int; ++i)
1272 if (WVAR_ENTRY(i).v_name != NULL)
1273 list_one_var(&WVAR_ENTRY(i), (char_u *)"w:");
1274 for (i = 0; i < VV_LEN && !got_int; ++i)
1275 if (vimvars[i].type == VAR_NUMBER || vimvars[i].val != NULL)
1276 list_vim_var(i);
1277}
1278
1279/*
1280 * List variables in "arg".
1281 */
1282 static char_u *
1283list_arg_vars(eap, arg)
1284 exarg_T *eap;
1285 char_u *arg;
1286{
1287 int error = FALSE;
1288 char_u *temp_string = NULL;
1289 int arg_len;
1290 char_u *expr_start;
1291 char_u *expr_end;
1292 char_u *name_end;
1293 int c1 = 0, c2;
1294 int i;
1295 VAR varp;
1296 char_u *name;
1297
1298 while (!ends_excmd(*arg) && !got_int)
1299 {
1300 /* Find the end of the name. */
1301 name_end = find_name_end(arg, &expr_start, &expr_end, FALSE);
1302
1303 if (!vim_iswhite(*name_end) && !ends_excmd(*name_end))
1304 {
1305 emsg_severe = TRUE;
1306 EMSG(_(e_trailing));
1307 break;
1308 }
1309 if (!error && !eap->skip)
1310 {
1311 if (expr_start != NULL)
1312 {
1313 temp_string = make_expanded_name(arg, expr_start,
1314 expr_end, name_end);
1315 if (temp_string == NULL)
1316 {
1317 /*
1318 * Report an invalid expression in braces, unless
1319 * the expression evaluation has been cancelled due
1320 * to an aborting error, an interrupt, or an
1321 * exception.
1322 */
1323 if (!aborting())
1324 {
1325 emsg_severe = TRUE;
1326 EMSG2(_(e_invarg2), arg);
1327 break;
1328 }
1329 error = TRUE;
1330 arg = skipwhite(name_end);
1331 continue;
1332 }
1333 arg = temp_string;
1334 arg_len = STRLEN(temp_string);
1335 }
1336 else
1337 {
1338 c1 = *name_end;
1339 *name_end = NUL;
1340 arg_len = (int)(name_end - arg);
1341 }
1342 i = find_vim_var(arg, arg_len);
1343 if (i >= 0)
1344 list_vim_var(i);
1345 else if (STRCMP("b:changedtick", arg) == 0)
1346 {
1347 char_u numbuf[NUMBUFLEN];
1348
1349 sprintf((char *)numbuf, "%ld",
1350 (long)curbuf->b_changedtick);
1351 list_one_var_a((char_u *)"b:", (char_u *)"changedtick",
1352 VAR_NUMBER, numbuf);
1353 }
1354 else
1355 {
1356 varp = find_var(arg, FALSE);
1357 if (varp == NULL)
1358 {
1359 /* Skip further arguments but do continue to
1360 * search for a trailing command. */
1361 EMSG2(_("E106: Unknown variable: \"%s\""), arg);
1362 error = TRUE;
1363 }
1364 else
1365 {
1366 name = vim_strchr(arg, ':');
1367 if (name != NULL)
1368 {
1369 /* "a:" vars have no name stored, use whole arg */
1370 if (arg[0] == 'a' && arg[1] == ':')
1371 c2 = NUL;
1372 else
1373 {
1374 c2 = *++name;
1375 *name = NUL;
1376 }
1377 list_one_var(varp, arg);
1378 if (c2 != NUL)
1379 *name = c2;
1380 }
1381 else
1382 list_one_var(varp, (char_u *)"");
1383 }
1384 }
1385 if (expr_start != NULL)
1386 vim_free(temp_string);
1387 else
1388 *name_end = c1;
1389 }
1390 arg = skipwhite(name_end);
1391 }
1392
1393 return arg;
1394}
1395
1396/*
1397 * Set one item of ":let var = expr" or ":let [v1, v2] = list" to its value.
1398 * Returns a pointer to the char just after the var name.
1399 * Returns NULL if there is an error.
1400 */
1401 static char_u *
1402ex_let_one(arg, tv, copy, endchars)
1403 char_u *arg; /* points to variable name */
1404 typeval *tv; /* value to assign to variable */
1405 int copy; /* copy value from "tv" */
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001406 char_u *endchars; /* valid chars after variable name or NULL */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001407{
1408 int c1;
1409 char_u *name;
1410 char_u *p;
1411 char_u *arg_end = NULL;
1412 int len;
1413 int opt_flags;
1414
1415 /*
1416 * ":let $VAR = expr": Set environment variable.
1417 */
1418 if (*arg == '$')
1419 {
1420 /* Find the end of the name. */
1421 ++arg;
1422 name = arg;
1423 len = get_env_len(&arg);
1424 if (len == 0)
1425 EMSG2(_(e_invarg2), name - 1);
1426 else
1427 {
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001428 if (endchars != NULL
1429 && vim_strchr(endchars, *skipwhite(arg)) == NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001430 EMSG(_(e_letunexp));
1431 else
1432 {
1433 c1 = name[len];
1434 name[len] = NUL;
1435 p = get_tv_string(tv);
1436 vim_setenv(name, p);
1437 if (STRICMP(name, "HOME") == 0)
1438 init_homedir();
1439 else if (didset_vim && STRICMP(name, "VIM") == 0)
1440 didset_vim = FALSE;
1441 else if (didset_vimruntime && STRICMP(name, "VIMRUNTIME") == 0)
1442 didset_vimruntime = FALSE;
1443 name[len] = c1;
1444 arg_end = arg;
1445 }
1446 }
1447 }
1448
1449 /*
1450 * ":let &option = expr": Set option value.
1451 * ":let &l:option = expr": Set local option value.
1452 * ":let &g:option = expr": Set global option value.
1453 */
1454 else if (*arg == '&')
1455 {
1456 /* Find the end of the name. */
1457 p = find_option_end(&arg, &opt_flags);
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001458 if (p == NULL || (endchars != NULL
1459 && vim_strchr(endchars, *skipwhite(p)) == NULL))
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001460 EMSG(_(e_letunexp));
1461 else
1462 {
1463 c1 = *p;
1464 *p = NUL;
1465 set_option_value(arg, get_tv_number(tv),
1466 get_tv_string(tv), opt_flags);
1467 *p = c1;
1468 arg_end = p;
1469 }
1470 }
1471
1472 /*
1473 * ":let @r = expr": Set register contents.
1474 */
1475 else if (*arg == '@')
1476 {
1477 ++arg;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001478 if (endchars != NULL
1479 && vim_strchr(endchars, *skipwhite(arg + 1)) == NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001480 EMSG(_(e_letunexp));
1481 else
1482 {
1483 write_reg_contents(*arg == '@' ? '"' : *arg,
1484 get_tv_string(tv), -1, FALSE);
1485 arg_end = arg + 1;
1486 }
1487 }
1488
1489 /*
1490 * ":let var = expr": Set internal variable.
1491 */
1492 else if (eval_isnamec(*arg) && !VIM_ISDIGIT(*arg))
1493 {
1494 char_u *exp_name = NULL;
1495 char_u *expr_start, *expr_end;
1496
1497 /* Find the end of the name. */
1498 p = find_name_end(arg, &expr_start, &expr_end, FALSE);
1499 if (expr_start != NULL)
1500 {
1501 exp_name = make_expanded_name(arg, expr_start, expr_end, p);
1502 arg = exp_name;
1503 }
1504
1505 if (arg == NULL)
1506 {
1507 /* Report an invalid expression in braces, unless the
1508 * expression evaluation has been cancelled due to an
1509 * aborting error, an interrupt, or an exception. */
1510 if (!aborting())
1511 EMSG2(_(e_invarg2), arg);
1512 }
1513 else if (*p == '[')
1514 arg_end = set_var_idx(arg, p, tv, copy, endchars);
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001515 else if (endchars != NULL
1516 && vim_strchr(endchars, *skipwhite(p)) == NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001517 EMSG(_(e_letunexp));
1518 else if (STRNCMP(arg, "b:changedtick", 13) == 0
1519 && !eval_isnamec(arg[13]))
1520 EMSG2(_(e_readonlyvar), arg);
1521 else
1522 {
1523 c1 = *p;
1524 *p = NUL;
1525 set_var(arg, tv, copy);
1526 *p = c1;
1527 arg_end = p;
1528 }
1529
1530 vim_free(exp_name);
1531 }
1532
1533 else
1534 EMSG2(_(e_invarg2), arg);
1535
1536 return arg_end;
1537}
1538
1539/*
1540 * Set a variable with an index: "name[expr]", "name[expr][expr]", etc.
1541 * Only works if "name" is an existing List.
1542 * "ip" points to the first '['.
1543 * Returns a pointer to just after the last used ']'; NULL for error.
1544 */
1545 static char_u *
1546set_var_idx(name, ip, rettv, copy, endchars)
1547 char_u *name;
1548 char_u *ip;
1549 typeval *rettv;
1550 int copy;
1551 char_u *endchars;
1552{
1553 VAR v;
1554 int c1;
1555 char_u *p;
1556 typeval var1;
1557 typeval *tv;
1558 long n;
1559 listitem *item;
1560
1561 c1 = *ip;
1562 *ip = NUL;
1563 v = find_var(name, TRUE);
1564 if (v == NULL)
1565 EMSG2(_(e_undefvar), name);
1566 *ip = c1;
1567 if (v == NULL)
1568 return NULL;
1569
1570 tv = &v->tv;
1571 for (p = ip; *p == '['; p = skipwhite(p + 1))
1572 {
1573 if (tv->v_type != VAR_LIST || tv->vval.v_list == NULL)
1574 {
1575 EMSG(_("E999: Can only index a List"));
1576 p = NULL;
1577 break;
1578 }
1579 p = skipwhite(p + 1);
1580 if (eval1(&p, &var1, TRUE) == FAIL) /* recursive! */
1581 {
1582 p = NULL;
1583 break;
1584 }
1585 if (*p != ']')
1586 {
1587 EMSG(_(e_missbrac));
1588 clear_tv(&var1);
1589 p = NULL;
1590 break;
1591 }
1592 n = get_tv_number(&var1);
1593 clear_tv(&var1);
1594 item = list_find(tv->vval.v_list, n);
1595 if (item == NULL)
1596 {
1597 EMSGN(_(e_listidx), n);
1598 p = NULL;
1599 break;
1600 }
1601 tv = &item->li_tv;
1602 }
1603
1604 if (p != NULL)
1605 {
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001606 if (endchars != NULL && vim_strchr(endchars, *p) == NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001607 {
1608 EMSG(_(e_letunexp));
1609 p = NULL;
1610 }
1611 else
1612 {
1613 clear_tv(tv);
1614 if (copy)
1615 copy_tv(tv, rettv);
1616 else
1617 {
1618 *tv = *rettv;
1619 init_tv(rettv);
1620 }
1621 }
1622 }
1623 return p;
1624}
1625
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001626/*
1627 * Add a watcher to a list.
1628 */
1629 static void
1630list_add_watch(l, lw)
1631 listvar *l;
1632 listwatch *lw;
1633{
1634 lw->lw_next = l->lv_watch;
1635 l->lv_watch = lw;
1636}
1637
1638/*
1639 * Remove a watches from a list.
1640 * No warning when it isn't found...
1641 */
1642 static void
1643list_rem_watch(l, lwrem)
1644 listvar *l;
1645 listwatch *lwrem;
1646{
1647 listwatch *lw, **lwp;
1648
1649 lwp = &l->lv_watch;
1650 for (lw = l->lv_watch; lw != NULL; lw = lw->lw_next)
1651 {
1652 if (lw == lwrem)
1653 {
1654 *lwp = lw->lw_next;
1655 break;
1656 }
1657 lwp = &lw->lw_next;
1658 }
1659}
1660
1661/*
1662 * Just before removing an item from a list: advance watchers to the next
1663 * item.
1664 */
1665 static void
1666list_fix_watch(l, item)
1667 listvar *l;
1668 listitem *item;
1669{
1670 listwatch *lw;
1671
1672 for (lw = l->lv_watch; lw != NULL; lw = lw->lw_next)
1673 if (lw->lw_item == item)
1674 lw->lw_item = item->li_next;
1675}
1676
1677/*
1678 * Evaluate the expression used in a ":for var in expr" command.
1679 * "arg" points to "var".
1680 * Set "*errp" to TRUE for an error, FALSE otherwise;
1681 * Return a pointer that holds the info. Null when there is an error.
1682 */
1683 void *
1684eval_for_line(arg, errp, nextcmdp, skip)
1685 char_u *arg;
1686 int *errp;
1687 char_u **nextcmdp;
1688 int skip;
1689{
1690 forinfo *fi;
1691 char_u *expr;
1692 typeval tv;
1693 listvar *l;
1694
1695 *errp = TRUE; /* default: there is an error */
1696
1697 fi = (forinfo *)alloc_clear(sizeof(forinfo));
1698 if (fi == NULL)
1699 return NULL;
1700
1701 expr = skip_var_list(arg, &fi->fi_varcount, &fi->fi_semicolon);
1702 if (expr == NULL)
1703 return fi;
1704
1705 expr = skipwhite(expr);
1706 if (expr[0] != 'i' || expr[1] != 'n' || !vim_iswhite(expr[2]))
1707 {
1708 EMSG(_("E999: Missing \"in\" after :for"));
1709 return fi;
1710 }
1711
1712 if (skip)
1713 ++emsg_skip;
1714 if (eval0(skipwhite(expr + 2), &tv, nextcmdp, !skip) == OK)
1715 {
1716 *errp = FALSE;
1717 if (!skip)
1718 {
1719 l = tv.vval.v_list;
1720 if (tv.v_type != VAR_LIST || l == NULL)
1721 EMSG(_(e_listreq));
1722 else
1723 {
1724 fi->fi_list = l;
1725 list_add_watch(l, &fi->fi_lw);
1726 fi->fi_lw.lw_item = l->lv_first;
1727 }
1728 }
1729 }
1730 if (skip)
1731 --emsg_skip;
1732
1733 return fi;
1734}
1735
1736/*
1737 * Use the first item in a ":for" list. Advance to the next.
1738 * Assign the values to the variable (list). "arg" points to the first one.
1739 * Return TRUE when a valid item was found, FALSE when at end of list or
1740 * something wrong.
1741 */
1742 int
1743next_for_item(fi_void, arg)
1744 void *fi_void;
1745 char_u *arg;
1746{
1747 forinfo *fi = (forinfo *)fi_void;
1748 int result;
1749 listitem *item;
1750
1751 item = fi->fi_lw.lw_item;
1752 if (item == NULL)
1753 result = FALSE;
1754 else
1755 {
1756 fi->fi_lw.lw_item = item->li_next;
1757 result = (ex_let_vars(arg, &item->li_tv, TRUE,
1758 fi->fi_semicolon, fi->fi_varcount, NULL) == OK);
1759 }
1760 return result;
1761}
1762
1763/*
1764 * Free the structure used to store info used by ":for".
1765 */
1766 void
1767free_for_info(fi_void)
1768 void *fi_void;
1769{
1770 forinfo *fi = (forinfo *)fi_void;
1771
1772 if (fi->fi_list != NULL)
1773 list_rem_watch(fi->fi_list, &fi->fi_lw);
1774 vim_free(fi);
1775}
1776
Bram Moolenaar071d4272004-06-13 20:20:40 +00001777#if defined(FEAT_CMDL_COMPL) || defined(PROTO)
1778
1779 void
1780set_context_for_expression(xp, arg, cmdidx)
1781 expand_T *xp;
1782 char_u *arg;
1783 cmdidx_T cmdidx;
1784{
1785 int got_eq = FALSE;
1786 int c;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001787 char_u *p;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001788
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001789 if (cmdidx == CMD_let)
1790 {
1791 xp->xp_context = EXPAND_USER_VARS;
1792 if (vim_strchr(arg, '=') == NULL)
1793 {
1794 /* ":let var1 var2 ...": find last space. */
1795 for (p = arg + STRLEN(arg); p > arg; )
1796 {
1797 xp->xp_pattern = p;
1798 p = mb_ptr_back(arg, p);
1799 if (vim_iswhite(*p))
1800 break;
1801 }
1802 return;
1803 }
1804 }
1805 else
1806 xp->xp_context = cmdidx == CMD_call ? EXPAND_FUNCTIONS
1807 : EXPAND_EXPRESSION;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001808 while ((xp->xp_pattern = vim_strpbrk(arg,
1809 (char_u *)"\"'+-*/%.=!?~|&$([<>,#")) != NULL)
1810 {
1811 c = *xp->xp_pattern;
1812 if (c == '&')
1813 {
1814 c = xp->xp_pattern[1];
1815 if (c == '&')
1816 {
1817 ++xp->xp_pattern;
1818 xp->xp_context = cmdidx != CMD_let || got_eq
1819 ? EXPAND_EXPRESSION : EXPAND_NOTHING;
1820 }
1821 else if (c != ' ')
1822 xp->xp_context = EXPAND_SETTINGS;
1823 }
1824 else if (c == '$')
1825 {
1826 /* environment variable */
1827 xp->xp_context = EXPAND_ENV_VARS;
1828 }
1829 else if (c == '=')
1830 {
1831 got_eq = TRUE;
1832 xp->xp_context = EXPAND_EXPRESSION;
1833 }
1834 else if (c == '<'
1835 && xp->xp_context == EXPAND_FUNCTIONS
1836 && vim_strchr(xp->xp_pattern, '(') == NULL)
1837 {
1838 /* Function name can start with "<SNR>" */
1839 break;
1840 }
1841 else if (cmdidx != CMD_let || got_eq)
1842 {
1843 if (c == '"') /* string */
1844 {
1845 while ((c = *++xp->xp_pattern) != NUL && c != '"')
1846 if (c == '\\' && xp->xp_pattern[1] != NUL)
1847 ++xp->xp_pattern;
1848 xp->xp_context = EXPAND_NOTHING;
1849 }
1850 else if (c == '\'') /* literal string */
1851 {
1852 while ((c = *++xp->xp_pattern) != NUL && c != '\'')
1853 /* skip */ ;
1854 xp->xp_context = EXPAND_NOTHING;
1855 }
1856 else if (c == '|')
1857 {
1858 if (xp->xp_pattern[1] == '|')
1859 {
1860 ++xp->xp_pattern;
1861 xp->xp_context = EXPAND_EXPRESSION;
1862 }
1863 else
1864 xp->xp_context = EXPAND_COMMANDS;
1865 }
1866 else
1867 xp->xp_context = EXPAND_EXPRESSION;
1868 }
1869 else
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001870 /* Doesn't look like something valid, expand as an expression
1871 * anyway. */
1872 xp->xp_context = EXPAND_EXPRESSION;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001873 arg = xp->xp_pattern;
1874 if (*arg != NUL)
1875 while ((c = *++arg) != NUL && (c == ' ' || c == '\t'))
1876 /* skip */ ;
1877 }
1878 xp->xp_pattern = arg;
1879}
1880
1881#endif /* FEAT_CMDL_COMPL */
1882
1883/*
1884 * ":1,25call func(arg1, arg2)" function call.
1885 */
1886 void
1887ex_call(eap)
1888 exarg_T *eap;
1889{
1890 char_u *arg = eap->arg;
1891 char_u *startarg;
1892 char_u *alias;
1893 char_u *name;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001894 typeval rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001895 int len;
1896 linenr_T lnum;
1897 int doesrange;
1898 int failed = FALSE;
1899
1900 name = arg;
1901 len = get_func_len(&arg, &alias, !eap->skip);
1902 if (len == 0)
1903 goto end;
1904 if (alias != NULL)
1905 name = alias;
1906
1907 startarg = arg;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001908 rettv.v_type = VAR_UNKNOWN; /* clear_tv() uses this */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001909
1910 if (*startarg != '(')
1911 {
1912 EMSG2(_("E107: Missing braces: %s"), name);
1913 goto end;
1914 }
1915
1916 /*
1917 * When skipping, evaluate the function once, to find the end of the
1918 * arguments.
1919 * When the function takes a range, this is discovered after the first
1920 * call, and the loop is broken.
1921 */
1922 if (eap->skip)
1923 {
1924 ++emsg_skip;
1925 lnum = eap->line2; /* do it once, also with an invalid range */
1926 }
1927 else
1928 lnum = eap->line1;
1929 for ( ; lnum <= eap->line2; ++lnum)
1930 {
1931 if (!eap->skip && eap->addr_count > 0)
1932 {
1933 curwin->w_cursor.lnum = lnum;
1934 curwin->w_cursor.col = 0;
1935 }
1936 arg = startarg;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001937 if (get_func_tv(name, len, &rettv, &arg,
Bram Moolenaar071d4272004-06-13 20:20:40 +00001938 eap->line1, eap->line2, &doesrange, !eap->skip) == FAIL)
1939 {
1940 failed = TRUE;
1941 break;
1942 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001943 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001944 if (doesrange || eap->skip)
1945 break;
1946 /* Stop when immediately aborting on error, or when an interrupt
Bram Moolenaar49cd9572005-01-03 21:06:01 +00001947 * occurred or an exception was thrown but not caught.
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001948 * get_func_tv() returned OK, so that the check for trailing
Bram Moolenaar49cd9572005-01-03 21:06:01 +00001949 * characters below is executed. */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001950 if (aborting())
1951 break;
1952 }
1953 if (eap->skip)
1954 --emsg_skip;
1955
1956 if (!failed)
1957 {
1958 /* Check for trailing illegal characters and a following command. */
1959 if (!ends_excmd(*arg))
1960 {
1961 emsg_severe = TRUE;
1962 EMSG(_(e_trailing));
1963 }
1964 else
1965 eap->nextcmd = check_nextcmd(arg);
1966 }
1967
1968end:
1969 if (alias != NULL)
1970 vim_free(alias);
1971}
1972
1973/*
1974 * ":unlet[!] var1 ... " command.
1975 */
1976 void
1977ex_unlet(eap)
1978 exarg_T *eap;
1979{
1980 char_u *arg = eap->arg;
1981 char_u *name_end;
1982 char_u cc;
1983 char_u *expr_start;
1984 char_u *expr_end;
1985 int error = FALSE;
1986
1987 do
1988 {
1989 /* Find the end of the name. */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001990 name_end = find_name_end(arg, &expr_start, &expr_end, FALSE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001991
1992 if (!vim_iswhite(*name_end) && !ends_excmd(*name_end))
1993 {
1994 emsg_severe = TRUE;
1995 EMSG(_(e_trailing));
1996 break;
1997 }
1998
1999 if (!error && !eap->skip)
2000 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00002001 if (expr_start != NULL)
2002 {
2003 char_u *temp_string;
2004
2005 temp_string = make_expanded_name(arg, expr_start,
2006 expr_end, name_end);
2007 if (temp_string == NULL)
2008 {
2009 /*
2010 * Report an invalid expression in braces, unless the
2011 * expression evaluation has been cancelled due to an
2012 * aborting error, an interrupt, or an exception.
2013 */
2014 if (!aborting())
2015 {
2016 emsg_severe = TRUE;
2017 EMSG2(_(e_invarg2), arg);
2018 break;
2019 }
2020 error = TRUE;
2021 }
2022 else
2023 {
2024 if (do_unlet(temp_string) == FAIL && !eap->forceit)
2025 {
2026 EMSG2(_("E108: No such variable: \"%s\""), temp_string);
2027 error = TRUE;
2028 }
2029 vim_free(temp_string);
2030 }
2031 }
2032 else
Bram Moolenaar071d4272004-06-13 20:20:40 +00002033 {
2034 cc = *name_end;
2035 *name_end = NUL;
2036
2037 if (do_unlet(arg) == FAIL && !eap->forceit)
2038 {
2039 EMSG2(_("E108: No such variable: \"%s\""), arg);
2040 error = TRUE;
2041 }
2042
2043 *name_end = cc;
2044 }
2045 }
2046 arg = skipwhite(name_end);
2047 } while (!ends_excmd(*arg));
2048
2049 eap->nextcmd = check_nextcmd(arg);
2050}
2051
2052/*
2053 * "unlet" a variable. Return OK if it existed, FAIL if not.
2054 */
2055 int
2056do_unlet(name)
2057 char_u *name;
2058{
2059 VAR v;
2060
2061 v = find_var(name, TRUE);
2062 if (v != NULL)
2063 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +00002064 clear_var(v);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002065 return OK;
2066 }
2067 return FAIL;
2068}
2069
2070#if (defined(FEAT_MENU) && defined(FEAT_MULTI_LANG)) || defined(PROTO)
2071/*
2072 * Delete all "menutrans_" variables.
2073 */
2074 void
2075del_menutrans_vars()
2076{
2077 int i;
2078
2079 for (i = 0; i < variables.ga_len; ++i)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00002080 if (VAR_ENTRY(i).v_name != NULL
2081 && STRNCMP(VAR_ENTRY(i).v_name, "menutrans_", 10) == 0)
2082 clear_var(&VAR_ENTRY(i));
Bram Moolenaar071d4272004-06-13 20:20:40 +00002083}
2084#endif
2085
2086#if defined(FEAT_CMDL_COMPL) || defined(PROTO)
2087
2088/*
2089 * Local string buffer for the next two functions to store a variable name
2090 * with its prefix. Allocated in cat_prefix_varname(), freed later in
2091 * get_user_var_name().
2092 */
2093
2094static char_u *cat_prefix_varname __ARGS((int prefix, char_u *name));
2095
2096static char_u *varnamebuf = NULL;
2097static int varnamebuflen = 0;
2098
2099/*
2100 * Function to concatenate a prefix and a variable name.
2101 */
2102 static char_u *
2103cat_prefix_varname(prefix, name)
2104 int prefix;
2105 char_u *name;
2106{
2107 int len;
2108
2109 len = (int)STRLEN(name) + 3;
2110 if (len > varnamebuflen)
2111 {
2112 vim_free(varnamebuf);
2113 len += 10; /* some additional space */
2114 varnamebuf = alloc(len);
2115 if (varnamebuf == NULL)
2116 {
2117 varnamebuflen = 0;
2118 return NULL;
2119 }
2120 varnamebuflen = len;
2121 }
2122 *varnamebuf = prefix;
2123 varnamebuf[1] = ':';
2124 STRCPY(varnamebuf + 2, name);
2125 return varnamebuf;
2126}
2127
2128/*
2129 * Function given to ExpandGeneric() to obtain the list of user defined
2130 * (global/buffer/window/built-in) variable names.
2131 */
2132/*ARGSUSED*/
2133 char_u *
2134get_user_var_name(xp, idx)
2135 expand_T *xp;
2136 int idx;
2137{
2138 static int gidx;
2139 static int bidx;
2140 static int widx;
2141 static int vidx;
2142 char_u *name;
2143
2144 if (idx == 0)
2145 gidx = bidx = widx = vidx = 0;
2146 if (gidx < variables.ga_len) /* Global variables */
2147 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +00002148 while ((name = VAR_ENTRY(gidx++).v_name) == NULL
Bram Moolenaar071d4272004-06-13 20:20:40 +00002149 && gidx < variables.ga_len)
2150 /* skip */;
2151 if (name != NULL)
2152 {
2153 if (STRNCMP("g:", xp->xp_pattern, 2) == 0)
2154 return cat_prefix_varname('g', name);
2155 else
2156 return name;
2157 }
2158 }
2159 if (bidx < curbuf->b_vars.ga_len) /* Current buffer variables */
2160 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +00002161 while ((name = BVAR_ENTRY(bidx++).v_name) == NULL
Bram Moolenaar071d4272004-06-13 20:20:40 +00002162 && bidx < curbuf->b_vars.ga_len)
2163 /* skip */;
2164 if (name != NULL)
2165 return cat_prefix_varname('b', name);
2166 }
2167 if (bidx == curbuf->b_vars.ga_len)
2168 {
2169 ++bidx;
2170 return (char_u *)"b:changedtick";
2171 }
2172 if (widx < curwin->w_vars.ga_len) /* Current window variables */
2173 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +00002174 while ((name = WVAR_ENTRY(widx++).v_name) == NULL
Bram Moolenaar071d4272004-06-13 20:20:40 +00002175 && widx < curwin->w_vars.ga_len)
2176 /* skip */;
2177 if (name != NULL)
2178 return cat_prefix_varname('w', name);
2179 }
2180 if (vidx < VV_LEN) /* Built-in variables */
2181 return cat_prefix_varname('v', (char_u *)vimvars[vidx++].name);
2182
2183 vim_free(varnamebuf);
2184 varnamebuf = NULL;
2185 varnamebuflen = 0;
2186 return NULL;
2187}
2188
2189#endif /* FEAT_CMDL_COMPL */
2190
2191/*
2192 * types for expressions.
2193 */
2194typedef enum
2195{
2196 TYPE_UNKNOWN = 0
2197 , TYPE_EQUAL /* == */
2198 , TYPE_NEQUAL /* != */
2199 , TYPE_GREATER /* > */
2200 , TYPE_GEQUAL /* >= */
2201 , TYPE_SMALLER /* < */
2202 , TYPE_SEQUAL /* <= */
2203 , TYPE_MATCH /* =~ */
2204 , TYPE_NOMATCH /* !~ */
2205} exptype_T;
2206
2207/*
2208 * The "evaluate" argument: When FALSE, the argument is only parsed but not
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002209 * executed. The function may return OK, but the rettv will be of type
Bram Moolenaar071d4272004-06-13 20:20:40 +00002210 * VAR_UNKNOWN. The function still returns FAIL for a syntax error.
2211 */
2212
2213/*
2214 * Handle zero level expression.
2215 * This calls eval1() and handles error message and nextcmd.
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002216 * Put the result in "rettv" when returning OK and "evaluate" is TRUE.
Bram Moolenaar071d4272004-06-13 20:20:40 +00002217 * Return OK or FAIL.
2218 */
2219 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002220eval0(arg, rettv, nextcmd, evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002221 char_u *arg;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002222 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002223 char_u **nextcmd;
2224 int evaluate;
2225{
2226 int ret;
2227 char_u *p;
2228
2229 p = skipwhite(arg);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002230 ret = eval1(&p, rettv, evaluate);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002231 if (ret == FAIL || !ends_excmd(*p))
2232 {
2233 if (ret != FAIL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002234 clear_tv(rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002235 /*
2236 * Report the invalid expression unless the expression evaluation has
2237 * been cancelled due to an aborting error, an interrupt, or an
2238 * exception.
2239 */
2240 if (!aborting())
2241 EMSG2(_(e_invexpr2), arg);
2242 ret = FAIL;
2243 }
2244 if (nextcmd != NULL)
2245 *nextcmd = check_nextcmd(p);
2246
2247 return ret;
2248}
2249
2250/*
2251 * Handle top level expression:
2252 * expr1 ? expr0 : expr0
2253 *
2254 * "arg" must point to the first non-white of the expression.
2255 * "arg" is advanced to the next non-white after the recognized expression.
2256 *
2257 * Return OK or FAIL.
2258 */
2259 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002260eval1(arg, rettv, evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002261 char_u **arg;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002262 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002263 int evaluate;
2264{
2265 int result;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00002266 typeval var2;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002267
2268 /*
2269 * Get the first variable.
2270 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002271 if (eval2(arg, rettv, evaluate) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002272 return FAIL;
2273
2274 if ((*arg)[0] == '?')
2275 {
2276 result = FALSE;
2277 if (evaluate)
2278 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002279 if (get_tv_number(rettv) != 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002280 result = TRUE;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002281 clear_tv(rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002282 }
2283
2284 /*
2285 * Get the second variable.
2286 */
2287 *arg = skipwhite(*arg + 1);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002288 if (eval1(arg, rettv, evaluate && result) == FAIL) /* recursive! */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002289 return FAIL;
2290
2291 /*
2292 * Check for the ":".
2293 */
2294 if ((*arg)[0] != ':')
2295 {
2296 EMSG(_("E109: Missing ':' after '?'"));
2297 if (evaluate && result)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002298 clear_tv(rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002299 return FAIL;
2300 }
2301
2302 /*
2303 * Get the third variable.
2304 */
2305 *arg = skipwhite(*arg + 1);
2306 if (eval1(arg, &var2, evaluate && !result) == FAIL) /* recursive! */
2307 {
2308 if (evaluate && result)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002309 clear_tv(rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002310 return FAIL;
2311 }
2312 if (evaluate && !result)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002313 *rettv = var2;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002314 }
2315
2316 return OK;
2317}
2318
2319/*
2320 * Handle first level expression:
2321 * expr2 || expr2 || expr2 logical OR
2322 *
2323 * "arg" must point to the first non-white of the expression.
2324 * "arg" is advanced to the next non-white after the recognized expression.
2325 *
2326 * Return OK or FAIL.
2327 */
2328 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002329eval2(arg, rettv, evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002330 char_u **arg;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002331 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002332 int evaluate;
2333{
Bram Moolenaar49cd9572005-01-03 21:06:01 +00002334 typeval var2;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002335 long result;
2336 int first;
2337
2338 /*
2339 * Get the first variable.
2340 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002341 if (eval3(arg, rettv, evaluate) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002342 return FAIL;
2343
2344 /*
2345 * Repeat until there is no following "||".
2346 */
2347 first = TRUE;
2348 result = FALSE;
2349 while ((*arg)[0] == '|' && (*arg)[1] == '|')
2350 {
2351 if (evaluate && first)
2352 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002353 if (get_tv_number(rettv) != 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002354 result = TRUE;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002355 clear_tv(rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002356 first = FALSE;
2357 }
2358
2359 /*
2360 * Get the second variable.
2361 */
2362 *arg = skipwhite(*arg + 2);
2363 if (eval3(arg, &var2, evaluate && !result) == FAIL)
2364 return FAIL;
2365
2366 /*
2367 * Compute the result.
2368 */
2369 if (evaluate && !result)
2370 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002371 if (get_tv_number(&var2) != 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002372 result = TRUE;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002373 clear_tv(&var2);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002374 }
2375 if (evaluate)
2376 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002377 rettv->v_type = VAR_NUMBER;
2378 rettv->vval.v_number = result;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002379 }
2380 }
2381
2382 return OK;
2383}
2384
2385/*
2386 * Handle second level expression:
2387 * expr3 && expr3 && expr3 logical AND
2388 *
2389 * "arg" must point to the first non-white of the expression.
2390 * "arg" is advanced to the next non-white after the recognized expression.
2391 *
2392 * Return OK or FAIL.
2393 */
2394 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002395eval3(arg, rettv, evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002396 char_u **arg;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002397 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002398 int evaluate;
2399{
Bram Moolenaar49cd9572005-01-03 21:06:01 +00002400 typeval var2;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002401 long result;
2402 int first;
2403
2404 /*
2405 * Get the first variable.
2406 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002407 if (eval4(arg, rettv, evaluate) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002408 return FAIL;
2409
2410 /*
2411 * Repeat until there is no following "&&".
2412 */
2413 first = TRUE;
2414 result = TRUE;
2415 while ((*arg)[0] == '&' && (*arg)[1] == '&')
2416 {
2417 if (evaluate && first)
2418 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002419 if (get_tv_number(rettv) == 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002420 result = FALSE;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002421 clear_tv(rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002422 first = FALSE;
2423 }
2424
2425 /*
2426 * Get the second variable.
2427 */
2428 *arg = skipwhite(*arg + 2);
2429 if (eval4(arg, &var2, evaluate && result) == FAIL)
2430 return FAIL;
2431
2432 /*
2433 * Compute the result.
2434 */
2435 if (evaluate && result)
2436 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002437 if (get_tv_number(&var2) == 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002438 result = FALSE;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002439 clear_tv(&var2);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002440 }
2441 if (evaluate)
2442 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002443 rettv->v_type = VAR_NUMBER;
2444 rettv->vval.v_number = result;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002445 }
2446 }
2447
2448 return OK;
2449}
2450
2451/*
2452 * Handle third level expression:
2453 * var1 == var2
2454 * var1 =~ var2
2455 * var1 != var2
2456 * var1 !~ var2
2457 * var1 > var2
2458 * var1 >= var2
2459 * var1 < var2
2460 * var1 <= var2
Bram Moolenaar8a283e52005-01-06 23:28:25 +00002461 * var1 is var2
2462 * var1 isnot var2
Bram Moolenaar071d4272004-06-13 20:20:40 +00002463 *
2464 * "arg" must point to the first non-white of the expression.
2465 * "arg" is advanced to the next non-white after the recognized expression.
2466 *
2467 * Return OK or FAIL.
2468 */
2469 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002470eval4(arg, rettv, evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002471 char_u **arg;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002472 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002473 int evaluate;
2474{
Bram Moolenaar49cd9572005-01-03 21:06:01 +00002475 typeval var2;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002476 char_u *p;
2477 int i;
2478 exptype_T type = TYPE_UNKNOWN;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00002479 int type_is = FALSE; /* TRUE for "is" and "isnot" */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002480 int len = 2;
2481 long n1, n2;
2482 char_u *s1, *s2;
2483 char_u buf1[NUMBUFLEN], buf2[NUMBUFLEN];
2484 regmatch_T regmatch;
2485 int ic;
2486 char_u *save_cpo;
2487
2488 /*
2489 * Get the first variable.
2490 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002491 if (eval5(arg, rettv, evaluate) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002492 return FAIL;
2493
2494 p = *arg;
2495 switch (p[0])
2496 {
2497 case '=': if (p[1] == '=')
2498 type = TYPE_EQUAL;
2499 else if (p[1] == '~')
2500 type = TYPE_MATCH;
2501 break;
2502 case '!': if (p[1] == '=')
2503 type = TYPE_NEQUAL;
2504 else if (p[1] == '~')
2505 type = TYPE_NOMATCH;
2506 break;
2507 case '>': if (p[1] != '=')
2508 {
2509 type = TYPE_GREATER;
2510 len = 1;
2511 }
2512 else
2513 type = TYPE_GEQUAL;
2514 break;
2515 case '<': if (p[1] != '=')
2516 {
2517 type = TYPE_SMALLER;
2518 len = 1;
2519 }
2520 else
2521 type = TYPE_SEQUAL;
2522 break;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00002523 case 'i': if (p[1] == 's')
2524 {
2525 if (p[2] == 'n' && p[3] == 'o' && p[4] == 't')
2526 len = 5;
2527 if (!vim_isIDc(p[len]))
2528 {
2529 type = len == 2 ? TYPE_EQUAL : TYPE_NEQUAL;
2530 type_is = TRUE;
2531 }
2532 }
2533 break;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002534 }
2535
2536 /*
2537 * If there is a comparitive operator, use it.
2538 */
2539 if (type != TYPE_UNKNOWN)
2540 {
2541 /* extra question mark appended: ignore case */
2542 if (p[len] == '?')
2543 {
2544 ic = TRUE;
2545 ++len;
2546 }
2547 /* extra '#' appended: match case */
2548 else if (p[len] == '#')
2549 {
2550 ic = FALSE;
2551 ++len;
2552 }
2553 /* nothing appened: use 'ignorecase' */
2554 else
2555 ic = p_ic;
2556
2557 /*
2558 * Get the second variable.
2559 */
2560 *arg = skipwhite(p + len);
2561 if (eval5(arg, &var2, evaluate) == FAIL)
2562 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002563 clear_tv(rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002564 return FAIL;
2565 }
2566
2567 if (evaluate)
2568 {
Bram Moolenaar8a283e52005-01-06 23:28:25 +00002569 if (type_is && rettv->v_type != var2.v_type)
2570 {
2571 /* For "is" a different type always means FALSE, for "notis"
2572 * it means TRUE. */
2573 n1 = (type == TYPE_NEQUAL);
2574 }
2575 else if (rettv->v_type == VAR_LIST || var2.v_type == VAR_LIST)
2576 {
2577 if (type_is)
2578 {
2579 n1 = (rettv->v_type == var2.v_type
2580 && rettv->vval.v_list == var2.vval.v_list);
2581 if (type == TYPE_NEQUAL)
2582 n1 = !n1;
2583 }
2584 else if (rettv->v_type != var2.v_type
2585 || (type != TYPE_EQUAL && type != TYPE_NEQUAL))
2586 {
2587 if (rettv->v_type != var2.v_type)
2588 EMSG(_("E999: Can only compare List with List"));
2589 else
2590 EMSG(_("E999: Invalid operation for Lists"));
2591 clear_tv(rettv);
2592 clear_tv(&var2);
2593 return FAIL;
2594 }
2595 else
2596 {
2597 /* Compare two Lists for being equal or unequal. */
2598 n1 = list_equal(rettv->vval.v_list, var2.vval.v_list, ic);
2599 if (type == TYPE_NEQUAL)
2600 n1 = !n1;
2601 }
2602 }
2603
2604 else if (rettv->v_type == VAR_FUNC || var2.v_type == VAR_FUNC)
2605 {
2606 if (rettv->v_type != var2.v_type
2607 || (type != TYPE_EQUAL && type != TYPE_NEQUAL))
2608 {
2609 if (rettv->v_type != var2.v_type)
2610 EMSG(_("E999: Can only compare Funcref with Funcref"));
2611 else
2612 EMSG(_("E999: Invalid operation for Funcrefs"));
2613 clear_tv(rettv);
2614 clear_tv(&var2);
2615 return FAIL;
2616 }
2617 else
2618 {
2619 /* Compare two Funcrefs for being equal or unequal. */
2620 if (rettv->vval.v_string == NULL
2621 || var2.vval.v_string == NULL)
2622 n1 = FALSE;
2623 else
2624 n1 = STRCMP(rettv->vval.v_string,
2625 var2.vval.v_string) == 0;
2626 if (type == TYPE_NEQUAL)
2627 n1 = !n1;
2628 }
2629 }
2630
Bram Moolenaar071d4272004-06-13 20:20:40 +00002631 /*
2632 * If one of the two variables is a number, compare as a number.
2633 * When using "=~" or "!~", always compare as string.
2634 */
Bram Moolenaar8a283e52005-01-06 23:28:25 +00002635 else if ((rettv->v_type == VAR_NUMBER || var2.v_type == VAR_NUMBER)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002636 && type != TYPE_MATCH && type != TYPE_NOMATCH)
2637 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002638 n1 = get_tv_number(rettv);
2639 n2 = get_tv_number(&var2);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002640 switch (type)
2641 {
2642 case TYPE_EQUAL: n1 = (n1 == n2); break;
2643 case TYPE_NEQUAL: n1 = (n1 != n2); break;
2644 case TYPE_GREATER: n1 = (n1 > n2); break;
2645 case TYPE_GEQUAL: n1 = (n1 >= n2); break;
2646 case TYPE_SMALLER: n1 = (n1 < n2); break;
2647 case TYPE_SEQUAL: n1 = (n1 <= n2); break;
2648 case TYPE_UNKNOWN:
2649 case TYPE_MATCH:
2650 case TYPE_NOMATCH: break; /* avoid gcc warning */
2651 }
2652 }
2653 else
2654 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002655 s1 = get_tv_string_buf(rettv, buf1);
2656 s2 = get_tv_string_buf(&var2, buf2);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002657 if (type != TYPE_MATCH && type != TYPE_NOMATCH)
2658 i = ic ? MB_STRICMP(s1, s2) : STRCMP(s1, s2);
2659 else
2660 i = 0;
2661 n1 = FALSE;
2662 switch (type)
2663 {
2664 case TYPE_EQUAL: n1 = (i == 0); break;
2665 case TYPE_NEQUAL: n1 = (i != 0); break;
2666 case TYPE_GREATER: n1 = (i > 0); break;
2667 case TYPE_GEQUAL: n1 = (i >= 0); break;
2668 case TYPE_SMALLER: n1 = (i < 0); break;
2669 case TYPE_SEQUAL: n1 = (i <= 0); break;
2670
2671 case TYPE_MATCH:
2672 case TYPE_NOMATCH:
2673 /* avoid 'l' flag in 'cpoptions' */
2674 save_cpo = p_cpo;
2675 p_cpo = (char_u *)"";
2676 regmatch.regprog = vim_regcomp(s2,
2677 RE_MAGIC + RE_STRING);
2678 regmatch.rm_ic = ic;
2679 if (regmatch.regprog != NULL)
2680 {
2681 n1 = vim_regexec_nl(&regmatch, s1, (colnr_T)0);
2682 vim_free(regmatch.regprog);
2683 if (type == TYPE_NOMATCH)
2684 n1 = !n1;
2685 }
2686 p_cpo = save_cpo;
2687 break;
2688
2689 case TYPE_UNKNOWN: break; /* avoid gcc warning */
2690 }
2691 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002692 clear_tv(rettv);
2693 clear_tv(&var2);
2694 rettv->v_type = VAR_NUMBER;
2695 rettv->vval.v_number = n1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002696 }
2697 }
2698
2699 return OK;
2700}
2701
2702/*
2703 * Handle fourth level expression:
2704 * + number addition
2705 * - number subtraction
2706 * . string concatenation
2707 *
2708 * "arg" must point to the first non-white of the expression.
2709 * "arg" is advanced to the next non-white after the recognized expression.
2710 *
2711 * Return OK or FAIL.
2712 */
2713 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002714eval5(arg, rettv, evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002715 char_u **arg;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002716 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002717 int evaluate;
2718{
Bram Moolenaar49cd9572005-01-03 21:06:01 +00002719 typeval var2;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00002720 typeval var3;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002721 int op;
2722 long n1, n2;
2723 char_u *s1, *s2;
2724 char_u buf1[NUMBUFLEN], buf2[NUMBUFLEN];
2725 char_u *p;
2726
2727 /*
2728 * Get the first variable.
2729 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002730 if (eval6(arg, rettv, evaluate) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002731 return FAIL;
2732
2733 /*
2734 * Repeat computing, until no '+', '-' or '.' is following.
2735 */
2736 for (;;)
2737 {
2738 op = **arg;
2739 if (op != '+' && op != '-' && op != '.')
2740 break;
2741
2742 /*
2743 * Get the second variable.
2744 */
2745 *arg = skipwhite(*arg + 1);
2746 if (eval6(arg, &var2, evaluate) == FAIL)
2747 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002748 clear_tv(rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002749 return FAIL;
2750 }
2751
2752 if (evaluate)
2753 {
2754 /*
2755 * Compute the result.
2756 */
2757 if (op == '.')
2758 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002759 s1 = get_tv_string_buf(rettv, buf1);
2760 s2 = get_tv_string_buf(&var2, buf2);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002761 op = (int)STRLEN(s1);
2762 p = alloc((unsigned)(op + STRLEN(s2) + 1));
2763 if (p != NULL)
2764 {
2765 STRCPY(p, s1);
2766 STRCPY(p + op, s2);
2767 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002768 clear_tv(rettv);
2769 rettv->v_type = VAR_STRING;
2770 rettv->vval.v_string = p;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002771 }
Bram Moolenaar8a283e52005-01-06 23:28:25 +00002772 else if (rettv->v_type == VAR_LIST && var2.v_type == VAR_LIST)
2773 {
2774 /* concatenate Lists */
2775 if (list_concat(rettv->vval.v_list, var2.vval.v_list,
2776 &var3) == FAIL)
2777 {
2778 clear_tv(rettv);
2779 clear_tv(&var2);
2780 return FAIL;
2781 }
2782 clear_tv(rettv);
2783 *rettv = var3;
2784 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00002785 else
2786 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002787 n1 = get_tv_number(rettv);
2788 n2 = get_tv_number(&var2);
2789 clear_tv(rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002790 if (op == '+')
2791 n1 = n1 + n2;
2792 else
2793 n1 = n1 - n2;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002794 rettv->v_type = VAR_NUMBER;
2795 rettv->vval.v_number = n1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002796 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002797 clear_tv(&var2);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002798 }
2799 }
2800 return OK;
2801}
2802
2803/*
2804 * Handle fifth level expression:
2805 * * number multiplication
2806 * / number division
2807 * % number modulo
2808 *
2809 * "arg" must point to the first non-white of the expression.
2810 * "arg" is advanced to the next non-white after the recognized expression.
2811 *
2812 * Return OK or FAIL.
2813 */
2814 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002815eval6(arg, rettv, evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002816 char_u **arg;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002817 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002818 int evaluate;
2819{
Bram Moolenaar49cd9572005-01-03 21:06:01 +00002820 typeval var2;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002821 int op;
2822 long n1, n2;
2823
2824 /*
2825 * Get the first variable.
2826 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002827 if (eval7(arg, rettv, evaluate) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002828 return FAIL;
2829
2830 /*
2831 * Repeat computing, until no '*', '/' or '%' is following.
2832 */
2833 for (;;)
2834 {
2835 op = **arg;
2836 if (op != '*' && op != '/' && op != '%')
2837 break;
2838
2839 if (evaluate)
2840 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002841 n1 = get_tv_number(rettv);
2842 clear_tv(rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002843 }
2844 else
2845 n1 = 0;
2846
2847 /*
2848 * Get the second variable.
2849 */
2850 *arg = skipwhite(*arg + 1);
2851 if (eval7(arg, &var2, evaluate) == FAIL)
2852 return FAIL;
2853
2854 if (evaluate)
2855 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002856 n2 = get_tv_number(&var2);
2857 clear_tv(&var2);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002858
2859 /*
2860 * Compute the result.
2861 */
2862 if (op == '*')
2863 n1 = n1 * n2;
2864 else if (op == '/')
2865 {
2866 if (n2 == 0) /* give an error message? */
2867 n1 = 0x7fffffffL;
2868 else
2869 n1 = n1 / n2;
2870 }
2871 else
2872 {
2873 if (n2 == 0) /* give an error message? */
2874 n1 = 0;
2875 else
2876 n1 = n1 % n2;
2877 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002878 rettv->v_type = VAR_NUMBER;
2879 rettv->vval.v_number = n1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002880 }
2881 }
2882
2883 return OK;
2884}
2885
2886/*
2887 * Handle sixth level expression:
2888 * number number constant
2889 * "string" string contstant
2890 * 'string' literal string contstant
2891 * &option-name option value
2892 * @r register contents
2893 * identifier variable value
2894 * function() function call
2895 * $VAR environment variable
2896 * (expression) nested expression
2897 *
2898 * Also handle:
2899 * ! in front logical NOT
2900 * - in front unary minus
2901 * + in front unary plus (ignored)
2902 * trailing [] subscript in String
2903 *
2904 * "arg" must point to the first non-white of the expression.
2905 * "arg" is advanced to the next non-white after the recognized expression.
2906 *
2907 * Return OK or FAIL.
2908 */
2909 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002910eval7(arg, rettv, evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002911 char_u **arg;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002912 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002913 int evaluate;
2914{
Bram Moolenaar071d4272004-06-13 20:20:40 +00002915 long n;
2916 int len;
2917 char_u *s;
2918 int val;
2919 char_u *start_leader, *end_leader;
2920 int ret = OK;
2921 char_u *alias;
2922
2923 /*
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002924 * Initialise variable so that clear_tv() can't mistake this for a
Bram Moolenaar49cd9572005-01-03 21:06:01 +00002925 * string and free a string that isn't there.
Bram Moolenaar071d4272004-06-13 20:20:40 +00002926 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002927 rettv->v_type = VAR_UNKNOWN;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002928
2929 /*
2930 * Skip '!' and '-' characters. They are handled later.
2931 */
2932 start_leader = *arg;
2933 while (**arg == '!' || **arg == '-' || **arg == '+')
2934 *arg = skipwhite(*arg + 1);
2935 end_leader = *arg;
2936
2937 switch (**arg)
2938 {
2939 /*
2940 * Number constant.
2941 */
2942 case '0':
2943 case '1':
2944 case '2':
2945 case '3':
2946 case '4':
2947 case '5':
2948 case '6':
2949 case '7':
2950 case '8':
2951 case '9':
2952 vim_str2nr(*arg, NULL, &len, TRUE, TRUE, &n, NULL);
2953 *arg += len;
2954 if (evaluate)
2955 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002956 rettv->v_type = VAR_NUMBER;
2957 rettv->vval.v_number = n;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002958 }
2959 break;
2960
2961 /*
2962 * String constant: "string".
2963 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002964 case '"': ret = get_string_tv(arg, rettv, evaluate);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002965 break;
2966
2967 /*
2968 * Literal string constant: 'string'.
2969 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002970 case '\'': ret = get_lit_string_tv(arg, rettv, evaluate);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00002971 break;
2972
2973 /*
2974 * List: [expr, expr]
2975 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002976 case '[': ret = get_list_tv(arg, rettv, evaluate);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002977 break;
2978
2979 /*
2980 * Option value: &name
2981 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002982 case '&': ret = get_option_tv(arg, rettv, evaluate);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002983 break;
2984
2985 /*
2986 * Environment variable: $VAR.
2987 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002988 case '$': ret = get_env_tv(arg, rettv, evaluate);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002989 break;
2990
2991 /*
2992 * Register contents: @r.
2993 */
2994 case '@': ++*arg;
2995 if (evaluate)
2996 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002997 rettv->v_type = VAR_STRING;
2998 rettv->vval.v_string = get_reg_contents(**arg, FALSE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002999 }
3000 if (**arg != NUL)
3001 ++*arg;
3002 break;
3003
3004 /*
3005 * nested expression: (expression).
3006 */
3007 case '(': *arg = skipwhite(*arg + 1);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003008 ret = eval1(arg, rettv, evaluate); /* recursive! */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003009 if (**arg == ')')
3010 ++*arg;
3011 else if (ret == OK)
3012 {
3013 EMSG(_("E110: Missing ')'"));
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003014 clear_tv(rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003015 ret = FAIL;
3016 }
3017 break;
3018
3019 /*
3020 * Must be a variable or function name then.
3021 */
3022 default: s = *arg;
3023 len = get_func_len(arg, &alias, evaluate);
3024 if (alias != NULL)
3025 s = alias;
3026
3027 if (len == 0)
3028 ret = FAIL;
3029 else
3030 {
3031 if (**arg == '(') /* recursive! */
3032 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +00003033 /* If "s" is the name of a variable of type VAR_FUNC
3034 * use its contents. */
3035 s = deref_func_name(s, &len);
3036
3037 /* Invoke the function. */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003038 ret = get_func_tv(s, len, rettv, arg,
Bram Moolenaar071d4272004-06-13 20:20:40 +00003039 curwin->w_cursor.lnum, curwin->w_cursor.lnum,
3040 &len, evaluate);
3041 /* Stop the expression evaluation when immediately
3042 * aborting on error, or when an interrupt occurred or
3043 * an exception was thrown but not caught. */
3044 if (aborting())
3045 {
3046 if (ret == OK)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003047 clear_tv(rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003048 ret = FAIL;
3049 }
3050 }
3051 else if (evaluate)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003052 ret = get_var_tv(s, len, rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003053 }
3054
3055 if (alias != NULL)
3056 vim_free(alias);
3057
3058 break;
3059 }
3060 *arg = skipwhite(*arg);
3061
3062 /*
Bram Moolenaar49cd9572005-01-03 21:06:01 +00003063 * Handle expr[expr] and expr[expr:expr] subscript.
Bram Moolenaar071d4272004-06-13 20:20:40 +00003064 */
Bram Moolenaar49cd9572005-01-03 21:06:01 +00003065 while (**arg == '[' && ret == OK)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003066 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003067 if (eval_index(arg, rettv, evaluate) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003068 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003069 clear_tv(rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003070 return FAIL;
3071 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00003072 }
3073
3074 /*
3075 * Apply logical NOT and unary '-', from right to left, ignore '+'.
3076 */
3077 if (ret == OK && evaluate && end_leader > start_leader)
3078 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003079 val = get_tv_number(rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003080 while (end_leader > start_leader)
3081 {
3082 --end_leader;
3083 if (*end_leader == '!')
3084 val = !val;
3085 else if (*end_leader == '-')
3086 val = -val;
3087 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003088 clear_tv(rettv);
3089 rettv->v_type = VAR_NUMBER;
3090 rettv->vval.v_number = val;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003091 }
3092
3093 return ret;
3094}
3095
3096/*
Bram Moolenaar49cd9572005-01-03 21:06:01 +00003097 * Evaluate an "[expr]" or "[expr:expr]" index.
3098 * "*arg" points to the '['.
3099 * Returns FAIL or OK. "*arg" is advanced to after the ']'.
3100 */
3101 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003102eval_index(arg, rettv, evaluate)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00003103 char_u **arg;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003104 typeval *rettv;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00003105 int evaluate;
3106{
3107 int empty1 = FALSE, empty2 = FALSE;
3108 typeval var1, var2;
3109 long n1, n2 = 0;
3110 long len;
3111 int range;
3112 char_u *s;
3113
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003114 if (rettv->v_type == VAR_FUNC)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00003115 {
3116 EMSG(_("E999: Cannot index a Funcref"));
3117 return FAIL;
3118 }
3119
3120 /*
3121 * Get the (first) variable from inside the [].
3122 */
3123 *arg = skipwhite(*arg + 1);
3124 if (**arg == ':')
3125 empty1 = TRUE;
3126 else if (eval1(arg, &var1, evaluate) == FAIL) /* recursive! */
3127 return FAIL;
3128
3129 /*
3130 * Get the second variable from inside the [:].
3131 */
3132 if (**arg == ':')
3133 {
3134 range = TRUE;
3135 *arg = skipwhite(*arg + 1);
3136 if (**arg == ']')
3137 empty2 = TRUE;
3138 else if (eval1(arg, &var2, evaluate) == FAIL) /* recursive! */
3139 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003140 clear_tv(&var1);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00003141 return FAIL;
3142 }
3143 }
3144 else
3145 range = FALSE;
3146
3147 /* Check for the ']'. */
3148 if (**arg != ']')
3149 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003150 EMSG(_(e_missbrac));
3151 clear_tv(&var1);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00003152 if (range)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003153 clear_tv(&var2);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00003154 return FAIL;
3155 }
3156
3157 if (evaluate)
3158 {
3159 if (empty1)
3160 n1 = 0;
3161 else
3162 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003163 n1 = get_tv_number(&var1);
3164 clear_tv(&var1);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00003165 }
3166 if (range)
3167 {
3168 if (empty2)
3169 n2 = -1;
3170 else
3171 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003172 n2 = get_tv_number(&var2);
3173 clear_tv(&var2);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00003174 }
3175 }
3176
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003177 switch (rettv->v_type)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00003178 {
3179 case VAR_NUMBER:
3180 case VAR_STRING:
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003181 s = get_tv_string(rettv);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00003182 len = (long)STRLEN(s);
3183 if (range)
3184 {
3185 /* The resulting variable is a substring. If the indexes
3186 * are out of range the result is empty. */
3187 if (n1 < 0)
3188 {
3189 n1 = len + n1;
3190 if (n1 < 0)
3191 n1 = 0;
3192 }
3193 if (n2 < 0)
3194 n2 = len + n2;
3195 else if (n2 >= len)
3196 n2 = len;
3197 if (n1 >= len || n2 < 0 || n1 > n2)
3198 s = NULL;
3199 else
3200 s = vim_strnsave(s + n1, (int)(n2 - n1 + 1));
3201 }
3202 else
3203 {
3204 /* The resulting variable is a string of a single
3205 * character. If the index is too big or negative the
3206 * result is empty. */
3207 if (n1 >= len || n1 < 0)
3208 s = NULL;
3209 else
3210 s = vim_strnsave(s + n1, 1);
3211 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003212 clear_tv(rettv);
3213 rettv->v_type = VAR_STRING;
3214 rettv->vval.v_string = s;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00003215 break;
3216
3217 case VAR_LIST:
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003218 len = list_len(rettv->vval.v_list);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00003219 if (n1 < 0)
3220 n1 = len + n1;
3221 if (!empty1 && (n1 < 0 || n1 >= len))
3222 {
3223 EMSGN(_(e_listidx), n1);
3224 return FAIL;
3225 }
3226 if (range)
3227 {
3228 listvar *l;
3229 listitem *item;
3230
3231 if (n2 < 0)
3232 n2 = len + n2;
3233 if (!empty2 && (n2 < 0 || n2 >= len || n2 < n1))
3234 {
3235 EMSGN(_(e_listidx), n2);
3236 return FAIL;
3237 }
3238 l = list_alloc();
3239 if (l == NULL)
3240 return FAIL;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003241 for (item = list_find(rettv->vval.v_list, n1);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00003242 n1 <= n2; ++n1)
3243 {
3244 if (list_append_tv(l, &item->li_tv) == FAIL)
3245 {
3246 list_free(l);
3247 return FAIL;
3248 }
3249 item = item->li_next;
3250 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003251 clear_tv(rettv);
3252 rettv->v_type = VAR_LIST;
3253 rettv->vval.v_list = l;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00003254 }
3255 else
3256 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003257 copy_tv(&list_find(rettv->vval.v_list, n1)->li_tv,
Bram Moolenaar49cd9572005-01-03 21:06:01 +00003258 &var1);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003259 clear_tv(rettv);
3260 *rettv = var1;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00003261 }
3262 break;
3263 }
3264 }
3265
3266 *arg = skipwhite(*arg + 1); /* skip the ']' */
3267 return OK;
3268}
3269
3270/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00003271 * Get an option value.
3272 * "arg" points to the '&' or '+' before the option name.
3273 * "arg" is advanced to character after the option name.
3274 * Return OK or FAIL.
3275 */
3276 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003277get_option_tv(arg, rettv, evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003278 char_u **arg;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003279 typeval *rettv; /* when NULL, only check if option exists */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003280 int evaluate;
3281{
3282 char_u *option_end;
3283 long numval;
3284 char_u *stringval;
3285 int opt_type;
3286 int c;
3287 int working = (**arg == '+'); /* has("+option") */
3288 int ret = OK;
3289 int opt_flags;
3290
3291 /*
3292 * Isolate the option name and find its value.
3293 */
3294 option_end = find_option_end(arg, &opt_flags);
3295 if (option_end == NULL)
3296 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003297 if (rettv != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003298 EMSG2(_("E112: Option name missing: %s"), *arg);
3299 return FAIL;
3300 }
3301
3302 if (!evaluate)
3303 {
3304 *arg = option_end;
3305 return OK;
3306 }
3307
3308 c = *option_end;
3309 *option_end = NUL;
3310 opt_type = get_option_value(*arg, &numval,
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003311 rettv == NULL ? NULL : &stringval, opt_flags);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003312
3313 if (opt_type == -3) /* invalid name */
3314 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003315 if (rettv != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003316 EMSG2(_("E113: Unknown option: %s"), *arg);
3317 ret = FAIL;
3318 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003319 else if (rettv != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003320 {
3321 if (opt_type == -2) /* hidden string option */
3322 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003323 rettv->v_type = VAR_STRING;
3324 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003325 }
3326 else if (opt_type == -1) /* hidden number option */
3327 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003328 rettv->v_type = VAR_NUMBER;
3329 rettv->vval.v_number = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003330 }
3331 else if (opt_type == 1) /* number option */
3332 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003333 rettv->v_type = VAR_NUMBER;
3334 rettv->vval.v_number = numval;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003335 }
3336 else /* string option */
3337 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003338 rettv->v_type = VAR_STRING;
3339 rettv->vval.v_string = stringval;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003340 }
3341 }
3342 else if (working && (opt_type == -2 || opt_type == -1))
3343 ret = FAIL;
3344
3345 *option_end = c; /* put back for error messages */
3346 *arg = option_end;
3347
3348 return ret;
3349}
3350
3351/*
3352 * Allocate a variable for a string constant.
3353 * Return OK or FAIL.
3354 */
3355 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003356get_string_tv(arg, rettv, evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003357 char_u **arg;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003358 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003359 int evaluate;
3360{
3361 char_u *p;
3362 char_u *name;
3363 int i;
3364 int extra = 0;
3365
3366 /*
3367 * Find the end of the string, skipping backslashed characters.
3368 */
Bram Moolenaar1cd871b2004-12-19 22:46:22 +00003369 for (p = *arg + 1; *p && *p != '"'; mb_ptr_adv(p))
Bram Moolenaar071d4272004-06-13 20:20:40 +00003370 {
3371 if (*p == '\\' && p[1] != NUL)
3372 {
3373 ++p;
3374 /* A "\<x>" form occupies at least 4 characters, and produces up
3375 * to 6 characters: reserve space for 2 extra */
3376 if (*p == '<')
3377 extra += 2;
3378 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00003379 }
3380
3381 if (*p != '"')
3382 {
3383 EMSG2(_("E114: Missing quote: %s"), *arg);
3384 return FAIL;
3385 }
3386
3387 /* If only parsing, set *arg and return here */
3388 if (!evaluate)
3389 {
3390 *arg = p + 1;
3391 return OK;
3392 }
3393
3394 /*
3395 * Copy the string into allocated memory, handling backslashed
3396 * characters.
3397 */
3398 name = alloc((unsigned)(p - *arg + extra));
3399 if (name == NULL)
3400 return FAIL;
3401
3402 i = 0;
3403 for (p = *arg + 1; *p && *p != '"'; ++p)
3404 {
3405 if (*p == '\\')
3406 {
3407 switch (*++p)
3408 {
3409 case 'b': name[i++] = BS; break;
3410 case 'e': name[i++] = ESC; break;
3411 case 'f': name[i++] = FF; break;
3412 case 'n': name[i++] = NL; break;
3413 case 'r': name[i++] = CAR; break;
3414 case 't': name[i++] = TAB; break;
3415
3416 case 'X': /* hex: "\x1", "\x12" */
3417 case 'x':
3418 case 'u': /* Unicode: "\u0023" */
3419 case 'U':
3420 if (vim_isxdigit(p[1]))
3421 {
3422 int n, nr;
3423 int c = toupper(*p);
3424
3425 if (c == 'X')
3426 n = 2;
3427 else
3428 n = 4;
3429 nr = 0;
3430 while (--n >= 0 && vim_isxdigit(p[1]))
3431 {
3432 ++p;
3433 nr = (nr << 4) + hex2nr(*p);
3434 }
3435#ifdef FEAT_MBYTE
3436 /* For "\u" store the number according to
3437 * 'encoding'. */
3438 if (c != 'X')
3439 i += (*mb_char2bytes)(nr, name + i);
3440 else
3441#endif
3442 name[i++] = nr;
3443 }
3444 else
3445 name[i++] = *p;
3446 break;
3447
3448 /* octal: "\1", "\12", "\123" */
3449 case '0':
3450 case '1':
3451 case '2':
3452 case '3':
3453 case '4':
3454 case '5':
3455 case '6':
3456 case '7': name[i] = *p - '0';
3457 if (p[1] >= '0' && p[1] <= '7')
3458 {
3459 ++p;
3460 name[i] = (name[i] << 3) + *p - '0';
3461 if (p[1] >= '0' && p[1] <= '7')
3462 {
3463 ++p;
3464 name[i] = (name[i] << 3) + *p - '0';
3465 }
3466 }
3467 ++i;
3468 break;
3469
3470 /* Special key, e.g.: "\<C-W>" */
3471 case '<': extra = trans_special(&p, name + i, TRUE);
3472 if (extra != 0)
3473 {
3474 i += extra;
3475 --p;
3476 break;
3477 }
3478 /* FALLTHROUGH */
3479
3480 default: name[i++] = *p;
3481 break;
3482 }
3483 }
3484 else
3485 name[i++] = *p;
3486
3487#ifdef FEAT_MBYTE
3488 /* For a multi-byte character copy the bytes after the first one. */
3489 if (has_mbyte)
3490 {
3491 int l = (*mb_ptr2len_check)(p);
3492
3493 while (--l > 0)
3494 name[i++] = *++p;
3495 }
3496#endif
3497 }
3498 name[i] = NUL;
3499 *arg = p + 1;
3500
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003501 rettv->v_type = VAR_STRING;
3502 rettv->vval.v_string = name;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003503
3504 return OK;
3505}
3506
3507/*
3508 * Allocate a variable for an backtick-string constant.
3509 * Return OK or FAIL.
3510 */
3511 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003512get_lit_string_tv(arg, rettv, evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003513 char_u **arg;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003514 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003515 int evaluate;
3516{
3517 char_u *p;
3518 char_u *name;
3519
3520 /*
3521 * Find the end of the string.
3522 */
3523 p = vim_strchr(*arg + 1, '\'');
3524 if (p == NULL)
3525 {
3526 EMSG2(_("E115: Missing quote: %s"), *arg);
3527 return FAIL;
3528 }
3529
3530 if (evaluate)
3531 {
3532 /*
3533 * Copy the string into allocated memory.
3534 */
3535 name = vim_strnsave(*arg + 1, (int)(p - (*arg + 1)));
3536 if (name == NULL)
3537 return FAIL;
3538
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003539 rettv->v_type = VAR_STRING;
3540 rettv->vval.v_string = name;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003541 }
3542
3543 *arg = p + 1;
3544
3545 return OK;
3546}
3547
3548/*
Bram Moolenaar49cd9572005-01-03 21:06:01 +00003549 * Allocate a variable for a List and fill it from "*arg".
3550 * Return OK or FAIL.
3551 */
3552 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003553get_list_tv(arg, rettv, evaluate)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00003554 char_u **arg;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003555 typeval *rettv;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00003556 int evaluate;
3557{
3558 listvar *l = NULL;
3559 typeval tv;
3560 listitem *item;
3561
3562 if (evaluate)
3563 {
3564 l = list_alloc();
3565 if (l == NULL)
3566 return FAIL;
3567 }
3568
3569 *arg = skipwhite(*arg + 1);
3570 while (**arg != ']' && **arg != NUL)
3571 {
3572 if (eval1(arg, &tv, evaluate) == FAIL) /* recursive! */
3573 goto failret;
3574 if (evaluate)
3575 {
3576 item = listitem_alloc();
3577 if (item != NULL)
3578 {
3579 item->li_tv = tv;
3580 list_append(l, item);
3581 }
3582 }
3583
3584 if (**arg == ']')
3585 break;
3586 if (**arg != ',')
3587 {
3588 EMSG2(_("E999: Missing comma in list: %s"), *arg);
3589 goto failret;
3590 }
3591 *arg = skipwhite(*arg + 1);
3592 }
3593
3594 if (**arg != ']')
3595 {
3596 EMSG2(_("E999: Missing end of list ']': %s"), *arg);
3597failret:
3598 if (evaluate)
3599 list_free(l);
3600 return FAIL;
3601 }
3602
3603 *arg = skipwhite(*arg + 1);
3604 if (evaluate)
3605 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003606 rettv->v_type = VAR_LIST;
3607 rettv->vval.v_list = l;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00003608 ++l->lv_refcount;
3609 }
3610
3611 return OK;
3612}
3613
3614/*
3615 * Allocate an empty header for a list.
3616 */
3617 static listvar *
3618list_alloc()
3619{
3620 return (listvar *)alloc_clear(sizeof(listvar));
3621}
3622
3623/*
3624 * Unreference a list: decrement the reference count and free it when it
3625 * becomes zero.
3626 */
3627 static void
3628list_unref(l)
3629 listvar *l;
3630{
3631 if (l != NULL && --l->lv_refcount <= 0)
3632 list_free(l);
3633}
3634
3635/*
3636 * Free a list, including all items it points to.
3637 * Ignores the reference count.
3638 */
3639 static void
3640list_free(l)
3641 listvar *l;
3642{
3643 listitem *item;
3644 listitem *next;
3645
3646 for (item = l->lv_first; item != NULL; item = next)
3647 {
3648 next = item->li_next;
3649 listitem_free(item);
3650 }
3651 vim_free(l);
3652}
3653
3654/*
3655 * Allocate a list item.
3656 */
3657 static listitem *
3658listitem_alloc()
3659{
3660 return (listitem *)alloc(sizeof(listitem));
3661}
3662
3663/*
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00003664 * Free a list item. Also clears the value. Does not notify watchers.
Bram Moolenaar49cd9572005-01-03 21:06:01 +00003665 */
3666 static void
3667listitem_free(item)
3668 listitem *item;
3669{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003670 clear_tv(&item->li_tv);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00003671 vim_free(item);
3672}
3673
3674/*
3675 * Get the number of items in a list.
3676 */
3677 static long
3678list_len(l)
3679 listvar *l;
3680{
3681 listitem *item;
3682 long len = 0;
3683
3684 if (l == NULL)
3685 return 0L;
3686 for (item = l->lv_first; item != NULL; item = item->li_next)
3687 ++len;
3688 return len;
3689}
3690
3691/*
Bram Moolenaar8a283e52005-01-06 23:28:25 +00003692 * Return TRUE when two lists have exactly the same values.
3693 */
3694 static int
3695list_equal(l1, l2, ic)
3696 listvar *l1;
3697 listvar *l2;
3698 int ic; /* ignore case for strings */
3699{
3700 listitem *item1, *item2;
3701
3702 for (item1 = l1->lv_first, item2 = l2->lv_first;
3703 item1 != NULL && item2 != NULL;
3704 item1 = item1->li_next, item2 = item2->li_next)
3705 if (!tv_equal(&item1->li_tv, &item2->li_tv, ic))
3706 return FALSE;
3707 return item1 == NULL && item2 == NULL;
3708}
3709
3710/*
3711 * Return TRUE if "tv1" and "tv2" have the same value.
3712 * Compares the items just like "==" would compare them.
3713 */
3714 static int
3715tv_equal(tv1, tv2, ic)
3716 typeval *tv1;
3717 typeval *tv2;
3718 int ic; /* ignore case */
3719{
3720 char_u buf1[NUMBUFLEN], buf2[NUMBUFLEN];
3721
3722 if (tv1->v_type == VAR_LIST || tv2->v_type == VAR_LIST)
3723 {
3724 /* recursive! */
3725 if (tv1->v_type != tv2->v_type
3726 || !list_equal(tv1->vval.v_list, tv2->vval.v_list, ic))
3727 return FALSE;
3728 }
3729 else if (tv1->v_type == VAR_FUNC || tv2->v_type == VAR_FUNC)
3730 {
3731 if (tv1->v_type != tv2->v_type
3732 || tv1->vval.v_string == NULL
3733 || tv2->vval.v_string == NULL
3734 || STRCMP(tv1->vval.v_string, tv2->vval.v_string) != 0)
3735 return FALSE;
3736 }
3737 else if (tv1->v_type == VAR_NUMBER || tv2->v_type == VAR_NUMBER)
3738 {
3739 if (get_tv_number(tv1) != get_tv_number(tv2))
3740 return FALSE;
3741 }
3742 else if (!ic && STRCMP(get_tv_string_buf(tv1, buf1),
3743 get_tv_string_buf(tv2, buf2)) != 0)
3744 return FALSE;
3745 else if (ic && STRICMP(get_tv_string_buf(tv1, buf1),
3746 get_tv_string_buf(tv2, buf2)) != 0)
3747 return FALSE;
3748 return TRUE;
3749}
3750
3751/*
Bram Moolenaar49cd9572005-01-03 21:06:01 +00003752 * Locate item with index "n" in list "l" and return it.
3753 * A negative index is counted from the end; -1 is the last item.
3754 * Returns NULL when "n" is out of range.
3755 */
3756 static listitem *
3757list_find(l, n)
3758 listvar *l;
3759 long n;
3760{
3761 listitem *item;
3762 long idx;
3763
3764 if (l == NULL)
3765 return NULL;
3766 if (n < 0)
3767 {
3768 idx = -1; /* search from the end */
3769 for (item = l->lv_last; item != NULL && idx > n; item = item->li_prev)
3770 --idx;
3771 }
3772 else
3773 {
3774 idx = 0; /* search from the start */
3775 for (item = l->lv_first; item != NULL && idx < n; item = item->li_next)
3776 ++idx;
3777 }
3778 if (idx != n)
3779 return NULL;
3780 return item;
3781}
3782
3783/*
Bram Moolenaar8a283e52005-01-06 23:28:25 +00003784 * Like list_find(), but also find an item just past the end.
3785 * "*ip" is the item to find.
3786 * When found "*ip" is set to zero, when not found "*ip" is non-zero.
3787 * Returns NULL when item not found or item is just past the end.
3788 */
3789 static listitem *
3790list_find_ext(l, ip)
3791 listvar *l;
3792 long *ip;
3793{
3794 long n;
3795 listitem *item;
3796
3797 if (*ip < 0)
3798 {
3799 /* Count from the end: -1 is before last item. */
3800 item = l->lv_last;
3801 for (n = *ip + 1; n < 0 && item != NULL; ++n)
3802 item = item->li_prev;
3803 if (item == NULL)
3804 n = 1; /* error! */
3805 }
3806 else
3807 {
3808 item = l->lv_first;
3809 for (n = *ip; n > 0 && item != NULL; --n)
3810 item = item->li_next;
3811 }
3812 *ip = n;
3813 return item;
3814}
3815
3816/*
Bram Moolenaar49cd9572005-01-03 21:06:01 +00003817 * Append item "item" to the end of list "l".
3818 */
3819 static void
3820list_append(l, item)
3821 listvar *l;
3822 listitem *item;
3823{
3824 if (l->lv_last == NULL)
3825 {
3826 /* empty list */
3827 l->lv_first = item;
3828 l->lv_last = item;
3829 item->li_prev = NULL;
3830 }
3831 else
3832 {
3833 l->lv_last->li_next = item;
3834 item->li_prev = l->lv_last;
3835 l->lv_last = item;
3836 }
3837 item->li_next = NULL;
3838}
3839
3840/*
3841 * Append typeval "tv" to the end of list "l".
Bram Moolenaar8a283e52005-01-06 23:28:25 +00003842 * Return FAIL when out of memory.
Bram Moolenaar49cd9572005-01-03 21:06:01 +00003843 */
3844 static int
3845list_append_tv(l, tv)
3846 listvar *l;
3847 typeval *tv;
3848{
3849 listitem *ni = listitem_alloc();
3850
3851 if (ni == NULL)
3852 return FAIL;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003853 copy_tv(tv, &ni->li_tv);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00003854 list_append(l, ni);
3855 return OK;
3856}
3857
3858/*
Bram Moolenaar8a283e52005-01-06 23:28:25 +00003859 * Insert typeval "tv" in list "l" before "item".
3860 * If "item" is NULL append at the end.
3861 * Return FAIL when out of memory.
3862 */
3863 static int
3864list_insert_tv(l, tv, item)
3865 listvar *l;
3866 typeval *tv;
3867 listitem *item;
3868{
3869 listitem *ni = listitem_alloc();
3870
3871 if (ni == NULL)
3872 return FAIL;
3873 copy_tv(tv, &ni->li_tv);
3874 if (item == NULL)
3875 /* Append new item at end of list. */
3876 list_append(l, ni);
3877 else
3878 {
3879 /* Insert new item before existing item. */
3880 ni->li_prev = item->li_prev;
3881 ni->li_next = item;
3882 if (item->li_prev == NULL)
3883 l->lv_first = ni;
3884 else
3885 item->li_prev->li_next = ni;
3886 item->li_prev = ni;
3887 }
3888 return OK;
3889}
3890
3891/*
3892 * Extend "l1" with "l2".
3893 * If "bef" is NULL append at the end, otherwise insert before this item.
3894 * Returns FAIL when out of memory.
3895 */
3896 static int
3897list_extend(l1, l2, bef)
3898 listvar *l1;
3899 listvar *l2;
3900 listitem *bef;
3901{
3902 listitem *item;
3903
3904 for (item = l2->lv_first; item != NULL; item = item->li_next)
3905 if (list_insert_tv(l1, &item->li_tv, bef) == FAIL)
3906 return FAIL;
3907 return OK;
3908}
3909
3910/*
3911 * Concatenate lists "l1" and "l2" into a new list, stored in "tv".
3912 * Return FAIL when out of memory.
3913 */
3914 static int
3915list_concat(l1, l2, tv)
3916 listvar *l1;
3917 listvar *l2;
3918 typeval *tv;
3919{
3920 listvar *l;
3921
3922 /* make a copy of the first list. */
3923 l = list_copy(l1, FALSE);
3924 if (l == NULL)
3925 return FAIL;
3926 tv->v_type = VAR_LIST;
3927 tv->vval.v_list = l;
3928
3929 /* append all items from the second list */
3930 return list_extend(l, l2, NULL);
3931}
3932
3933/*
Bram Moolenaar49cd9572005-01-03 21:06:01 +00003934 * Make a copy of list "l". Shallow if "deep" is FALSE.
3935 * The refcount of the new list is set to 1.
3936 * Returns NULL when out of memory.
3937 */
3938 static listvar *
3939list_copy(orig, deep)
3940 listvar *orig;
3941 int deep;
3942{
3943 listvar *copy;
3944 listitem *item;
3945 listitem *ni;
3946 static int recurse = 0;
3947
3948 if (orig == NULL)
3949 return NULL;
3950 if (recurse >= VAR_LIST_MAXNEST)
3951 {
3952 EMSG(_("E999: List nested too deep for making a copy"));
3953 return NULL;
3954 }
3955 ++recurse;
3956
3957 copy = list_alloc();
3958 if (copy != NULL)
3959 {
3960 for (item = orig->lv_first; item != NULL; item = item->li_next)
3961 {
3962 ni = listitem_alloc();
3963 if (ni == NULL)
3964 break;
3965 if (deep && item->li_tv.v_type == VAR_LIST)
3966 {
3967 ni->li_tv.v_type = VAR_LIST;
3968 ni->li_tv.vval.v_list = list_copy(item->li_tv.vval.v_list,
3969 TRUE);
3970 if (ni->li_tv.vval.v_list == NULL)
3971 {
3972 vim_free(ni);
3973 break;
3974 }
3975 }
3976 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003977 copy_tv(&item->li_tv, &ni->li_tv);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00003978 list_append(copy, ni);
3979 }
3980 ++copy->lv_refcount;
3981 }
3982
3983 --recurse;
3984 return copy;
3985}
3986
3987/*
Bram Moolenaar8a283e52005-01-06 23:28:25 +00003988 * Remove items "item" to "item2" from list "l".
Bram Moolenaar49cd9572005-01-03 21:06:01 +00003989 */
Bram Moolenaar8a283e52005-01-06 23:28:25 +00003990 static void
3991list_getrem(l, item, item2)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00003992 listvar *l;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00003993 listitem *item;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00003994 listitem *item2;
3995{
3996 listitem *ip;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00003997
Bram Moolenaar8a283e52005-01-06 23:28:25 +00003998 /* notify watchers */
3999 for (ip = item; ip != NULL; ip = ip->li_next)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004000 {
Bram Moolenaar8a283e52005-01-06 23:28:25 +00004001 list_fix_watch(l, ip);
4002 if (ip == item2)
4003 break;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004004 }
Bram Moolenaar8a283e52005-01-06 23:28:25 +00004005
4006 if (item2->li_next == NULL)
4007 l->lv_last = item->li_prev;
4008 else
4009 item2->li_next->li_prev = item->li_prev;
4010 if (item->li_prev == NULL)
4011 l->lv_first = item2->li_next;
4012 else
4013 item->li_prev->li_next = item2->li_next;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004014}
4015
4016/*
4017 * Return an allocated string with the string representation of a list.
4018 * May return NULL.
4019 */
4020 static char_u *
4021list2string(tv)
4022 typeval *tv;
4023{
4024 garray_T ga;
4025 listitem *item;
4026 int first = TRUE;
4027 char_u *tofree;
4028 char_u *s;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00004029 char_u numbuf[NUMBUFLEN];
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004030
4031 if (tv->vval.v_list == NULL)
4032 return NULL;
4033 ga_init2(&ga, (int)sizeof(char), 80);
4034 ga_append(&ga, '[');
4035
4036 for (item = tv->vval.v_list->lv_first; item != NULL; item = item->li_next)
4037 {
4038 if (first)
4039 first = FALSE;
4040 else
4041 ga_concat(&ga, (char_u *)", ");
4042
Bram Moolenaar8a283e52005-01-06 23:28:25 +00004043 s = tv2string(&item->li_tv, &tofree, numbuf);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004044 if (s != NULL)
4045 ga_concat(&ga, s);
4046 vim_free(tofree);
4047 }
4048
4049 ga_append(&ga, ']');
4050 ga_append(&ga, NUL);
4051 return (char_u *)ga.ga_data;
4052}
4053
4054/*
4055 * Return a string with the string representation of a variable.
4056 * If the memory is allocated "tofree" is set to it, otherwise NULL.
Bram Moolenaar8a283e52005-01-06 23:28:25 +00004057 * "numbuf" is used for a number.
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004058 * May return NULL;
4059 */
4060 static char_u *
Bram Moolenaar8a283e52005-01-06 23:28:25 +00004061tv2string(tv, tofree, numbuf)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004062 typeval *tv;
4063 char_u **tofree;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00004064 char_u *numbuf;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004065{
4066 switch (tv->v_type)
4067 {
4068 case VAR_FUNC:
4069 *tofree = NULL;
4070 return tv->vval.v_string;
4071 case VAR_LIST:
4072 *tofree = list2string(tv);
4073 return *tofree;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004074 case VAR_STRING:
4075 case VAR_NUMBER:
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004076 break;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004077 default:
4078 EMSG2(_(e_intern2), "tv2string()");
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004079 }
4080 *tofree = NULL;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00004081 return get_tv_string_buf(tv, numbuf);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004082}
4083
4084/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00004085 * Get the value of an environment variable.
4086 * "arg" is pointing to the '$'. It is advanced to after the name.
4087 * If the environment variable was not set, silently assume it is empty.
4088 * Always return OK.
4089 */
4090 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004091get_env_tv(arg, rettv, evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004092 char_u **arg;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004093 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004094 int evaluate;
4095{
4096 char_u *string = NULL;
4097 int len;
4098 int cc;
4099 char_u *name;
4100
4101 ++*arg;
4102 name = *arg;
4103 len = get_env_len(arg);
4104 if (evaluate)
4105 {
4106 if (len != 0)
4107 {
4108 cc = name[len];
4109 name[len] = NUL;
4110 /* first try mch_getenv(), fast for normal environment vars */
4111 string = mch_getenv(name);
4112 if (string != NULL && *string != NUL)
4113 string = vim_strsave(string);
4114 else
4115 {
4116 /* next try expanding things like $VIM and ${HOME} */
4117 string = expand_env_save(name - 1);
4118 if (string != NULL && *string == '$')
4119 {
4120 vim_free(string);
4121 string = NULL;
4122 }
4123 }
4124 name[len] = cc;
4125 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004126 rettv->v_type = VAR_STRING;
4127 rettv->vval.v_string = string;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004128 }
4129
4130 return OK;
4131}
4132
4133/*
4134 * Array with names and number of arguments of all internal functions
4135 * MUST BE KEPT SORTED IN strcmp() ORDER FOR BINARY SEARCH!
4136 */
4137static struct fst
4138{
4139 char *f_name; /* function name */
4140 char f_min_argc; /* minimal number of arguments */
4141 char f_max_argc; /* maximal number of arguments */
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004142 void (*f_func) __ARGS((typeval *args, typeval *rvar));
4143 /* implemenation of function */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004144} functions[] =
4145{
4146 {"append", 2, 2, f_append},
4147 {"argc", 0, 0, f_argc},
4148 {"argidx", 0, 0, f_argidx},
4149 {"argv", 1, 1, f_argv},
4150 {"browse", 4, 4, f_browse},
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00004151 {"browsedir", 2, 2, f_browsedir},
Bram Moolenaar071d4272004-06-13 20:20:40 +00004152 {"bufexists", 1, 1, f_bufexists},
4153 {"buffer_exists", 1, 1, f_bufexists}, /* obsolete */
4154 {"buffer_name", 1, 1, f_bufname}, /* obsolete */
4155 {"buffer_number", 1, 1, f_bufnr}, /* obsolete */
4156 {"buflisted", 1, 1, f_buflisted},
4157 {"bufloaded", 1, 1, f_bufloaded},
4158 {"bufname", 1, 1, f_bufname},
4159 {"bufnr", 1, 1, f_bufnr},
4160 {"bufwinnr", 1, 1, f_bufwinnr},
4161 {"byte2line", 1, 1, f_byte2line},
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00004162 {"byteidx", 2, 2, f_byteidx},
Bram Moolenaar8a283e52005-01-06 23:28:25 +00004163 {"call", 2, 2, f_call},
Bram Moolenaar071d4272004-06-13 20:20:40 +00004164 {"char2nr", 1, 1, f_char2nr},
4165 {"cindent", 1, 1, f_cindent},
4166 {"col", 1, 1, f_col},
4167 {"confirm", 1, 4, f_confirm},
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004168 {"copy", 1, 1, f_copy},
Bram Moolenaar8a283e52005-01-06 23:28:25 +00004169 {"count", 2, 3, f_count},
Bram Moolenaar071d4272004-06-13 20:20:40 +00004170 {"cscope_connection",0,3, f_cscope_connection},
4171 {"cursor", 2, 2, f_cursor},
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004172 {"deepcopy", 1, 1, f_deepcopy},
Bram Moolenaar071d4272004-06-13 20:20:40 +00004173 {"delete", 1, 1, f_delete},
4174 {"did_filetype", 0, 0, f_did_filetype},
Bram Moolenaar47136d72004-10-12 20:02:24 +00004175 {"diff_filler", 1, 1, f_diff_filler},
4176 {"diff_hlID", 2, 2, f_diff_hlID},
Bram Moolenaar071d4272004-06-13 20:20:40 +00004177 {"escape", 2, 2, f_escape},
4178 {"eventhandler", 0, 0, f_eventhandler},
4179 {"executable", 1, 1, f_executable},
4180 {"exists", 1, 1, f_exists},
4181 {"expand", 1, 2, f_expand},
Bram Moolenaar8a283e52005-01-06 23:28:25 +00004182 {"extend", 2, 3, f_extend},
Bram Moolenaar071d4272004-06-13 20:20:40 +00004183 {"file_readable", 1, 1, f_filereadable}, /* obsolete */
4184 {"filereadable", 1, 1, f_filereadable},
4185 {"filewritable", 1, 1, f_filewritable},
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00004186 {"finddir", 1, 3, f_finddir},
4187 {"findfile", 1, 3, f_findfile},
Bram Moolenaar071d4272004-06-13 20:20:40 +00004188 {"fnamemodify", 2, 2, f_fnamemodify},
4189 {"foldclosed", 1, 1, f_foldclosed},
4190 {"foldclosedend", 1, 1, f_foldclosedend},
4191 {"foldlevel", 1, 1, f_foldlevel},
4192 {"foldtext", 0, 0, f_foldtext},
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00004193 {"foldtextresult", 1, 1, f_foldtextresult},
Bram Moolenaar071d4272004-06-13 20:20:40 +00004194 {"foreground", 0, 0, f_foreground},
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004195 {"function", 1, 1, f_function},
Bram Moolenaar071d4272004-06-13 20:20:40 +00004196 {"getbufvar", 2, 2, f_getbufvar},
4197 {"getchar", 0, 1, f_getchar},
4198 {"getcharmod", 0, 0, f_getcharmod},
4199 {"getcmdline", 0, 0, f_getcmdline},
4200 {"getcmdpos", 0, 0, f_getcmdpos},
4201 {"getcwd", 0, 0, f_getcwd},
Bram Moolenaar46c9c732004-12-12 11:37:09 +00004202 {"getfontname", 0, 1, f_getfontname},
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00004203 {"getfperm", 1, 1, f_getfperm},
Bram Moolenaar071d4272004-06-13 20:20:40 +00004204 {"getfsize", 1, 1, f_getfsize},
4205 {"getftime", 1, 1, f_getftime},
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00004206 {"getftype", 1, 1, f_getftype},
Bram Moolenaar071d4272004-06-13 20:20:40 +00004207 {"getline", 1, 1, f_getline},
4208 {"getreg", 0, 1, f_getreg},
4209 {"getregtype", 0, 1, f_getregtype},
4210 {"getwinposx", 0, 0, f_getwinposx},
4211 {"getwinposy", 0, 0, f_getwinposy},
4212 {"getwinvar", 2, 2, f_getwinvar},
4213 {"glob", 1, 1, f_glob},
4214 {"globpath", 2, 2, f_globpath},
4215 {"has", 1, 1, f_has},
4216 {"hasmapto", 1, 2, f_hasmapto},
4217 {"highlightID", 1, 1, f_hlID}, /* obsolete */
4218 {"highlight_exists",1, 1, f_hlexists}, /* obsolete */
4219 {"histadd", 2, 2, f_histadd},
4220 {"histdel", 1, 2, f_histdel},
4221 {"histget", 1, 2, f_histget},
4222 {"histnr", 1, 1, f_histnr},
4223 {"hlID", 1, 1, f_hlID},
4224 {"hlexists", 1, 1, f_hlexists},
4225 {"hostname", 0, 0, f_hostname},
4226 {"iconv", 3, 3, f_iconv},
4227 {"indent", 1, 1, f_indent},
Bram Moolenaar8a283e52005-01-06 23:28:25 +00004228 {"index", 2, 3, f_index},
Bram Moolenaar071d4272004-06-13 20:20:40 +00004229 {"input", 1, 2, f_input},
4230 {"inputdialog", 1, 3, f_inputdialog},
4231 {"inputrestore", 0, 0, f_inputrestore},
4232 {"inputsave", 0, 0, f_inputsave},
4233 {"inputsecret", 1, 2, f_inputsecret},
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004234 {"insert", 2, 3, f_insert},
Bram Moolenaar071d4272004-06-13 20:20:40 +00004235 {"isdirectory", 1, 1, f_isdirectory},
4236 {"last_buffer_nr", 0, 0, f_last_buffer_nr},/* obsolete */
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004237 {"len", 1, 1, f_len},
Bram Moolenaar071d4272004-06-13 20:20:40 +00004238 {"libcall", 3, 3, f_libcall},
4239 {"libcallnr", 3, 3, f_libcallnr},
4240 {"line", 1, 1, f_line},
4241 {"line2byte", 1, 1, f_line2byte},
4242 {"lispindent", 1, 1, f_lispindent},
4243 {"localtime", 0, 0, f_localtime},
4244 {"maparg", 1, 2, f_maparg},
4245 {"mapcheck", 1, 2, f_mapcheck},
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00004246 {"match", 2, 4, f_match},
4247 {"matchend", 2, 4, f_matchend},
4248 {"matchstr", 2, 4, f_matchstr},
Bram Moolenaar071d4272004-06-13 20:20:40 +00004249 {"mode", 0, 0, f_mode},
4250 {"nextnonblank", 1, 1, f_nextnonblank},
4251 {"nr2char", 1, 1, f_nr2char},
4252 {"prevnonblank", 1, 1, f_prevnonblank},
4253 {"remote_expr", 2, 3, f_remote_expr},
4254 {"remote_foreground", 1, 1, f_remote_foreground},
4255 {"remote_peek", 1, 2, f_remote_peek},
4256 {"remote_read", 1, 1, f_remote_read},
4257 {"remote_send", 2, 3, f_remote_send},
Bram Moolenaar8a283e52005-01-06 23:28:25 +00004258 {"remove", 2, 3, f_remove},
Bram Moolenaar071d4272004-06-13 20:20:40 +00004259 {"rename", 2, 2, f_rename},
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00004260 {"repeat", 2, 2, f_repeat},
Bram Moolenaar071d4272004-06-13 20:20:40 +00004261 {"resolve", 1, 1, f_resolve},
4262 {"search", 1, 2, f_search},
4263 {"searchpair", 3, 5, f_searchpair},
4264 {"server2client", 2, 2, f_server2client},
4265 {"serverlist", 0, 0, f_serverlist},
4266 {"setbufvar", 3, 3, f_setbufvar},
4267 {"setcmdpos", 1, 1, f_setcmdpos},
4268 {"setline", 2, 2, f_setline},
4269 {"setreg", 2, 3, f_setreg},
4270 {"setwinvar", 3, 3, f_setwinvar},
4271 {"simplify", 1, 1, f_simplify},
4272#ifdef HAVE_STRFTIME
4273 {"strftime", 1, 2, f_strftime},
4274#endif
4275 {"stridx", 2, 2, f_stridx},
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004276 {"string", 1, 1, f_string},
Bram Moolenaar071d4272004-06-13 20:20:40 +00004277 {"strlen", 1, 1, f_strlen},
4278 {"strpart", 2, 3, f_strpart},
4279 {"strridx", 2, 2, f_strridx},
4280 {"strtrans", 1, 1, f_strtrans},
4281 {"submatch", 1, 1, f_submatch},
4282 {"substitute", 4, 4, f_substitute},
4283 {"synID", 3, 3, f_synID},
4284 {"synIDattr", 2, 3, f_synIDattr},
4285 {"synIDtrans", 1, 1, f_synIDtrans},
Bram Moolenaarc0197e22004-09-13 20:26:32 +00004286 {"system", 1, 2, f_system},
Bram Moolenaar071d4272004-06-13 20:20:40 +00004287 {"tempname", 0, 0, f_tempname},
4288 {"tolower", 1, 1, f_tolower},
4289 {"toupper", 1, 1, f_toupper},
Bram Moolenaar8299df92004-07-10 09:47:34 +00004290 {"tr", 3, 3, f_tr},
Bram Moolenaar071d4272004-06-13 20:20:40 +00004291 {"type", 1, 1, f_type},
4292 {"virtcol", 1, 1, f_virtcol},
4293 {"visualmode", 0, 1, f_visualmode},
4294 {"winbufnr", 1, 1, f_winbufnr},
4295 {"wincol", 0, 0, f_wincol},
4296 {"winheight", 1, 1, f_winheight},
4297 {"winline", 0, 0, f_winline},
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00004298 {"winnr", 0, 1, f_winnr},
Bram Moolenaar071d4272004-06-13 20:20:40 +00004299 {"winrestcmd", 0, 0, f_winrestcmd},
4300 {"winwidth", 1, 1, f_winwidth},
4301};
4302
4303#if defined(FEAT_CMDL_COMPL) || defined(PROTO)
4304
4305/*
4306 * Function given to ExpandGeneric() to obtain the list of internal
4307 * or user defined function names.
4308 */
4309 char_u *
4310get_function_name(xp, idx)
4311 expand_T *xp;
4312 int idx;
4313{
4314 static int intidx = -1;
4315 char_u *name;
4316
4317 if (idx == 0)
4318 intidx = -1;
4319 if (intidx < 0)
4320 {
4321 name = get_user_func_name(xp, idx);
4322 if (name != NULL)
4323 return name;
4324 }
4325 if (++intidx < (int)(sizeof(functions) / sizeof(struct fst)))
4326 {
4327 STRCPY(IObuff, functions[intidx].f_name);
4328 STRCAT(IObuff, "(");
4329 if (functions[intidx].f_max_argc == 0)
4330 STRCAT(IObuff, ")");
4331 return IObuff;
4332 }
4333
4334 return NULL;
4335}
4336
4337/*
4338 * Function given to ExpandGeneric() to obtain the list of internal or
4339 * user defined variable or function names.
4340 */
4341/*ARGSUSED*/
4342 char_u *
4343get_expr_name(xp, idx)
4344 expand_T *xp;
4345 int idx;
4346{
4347 static int intidx = -1;
4348 char_u *name;
4349
4350 if (idx == 0)
4351 intidx = -1;
4352 if (intidx < 0)
4353 {
4354 name = get_function_name(xp, idx);
4355 if (name != NULL)
4356 return name;
4357 }
4358 return get_user_var_name(xp, ++intidx);
4359}
4360
4361#endif /* FEAT_CMDL_COMPL */
4362
4363/*
4364 * Find internal function in table above.
4365 * Return index, or -1 if not found
4366 */
4367 static int
4368find_internal_func(name)
4369 char_u *name; /* name of the function */
4370{
4371 int first = 0;
4372 int last = (int)(sizeof(functions) / sizeof(struct fst)) - 1;
4373 int cmp;
4374 int x;
4375
4376 /*
4377 * Find the function name in the table. Binary search.
4378 */
4379 while (first <= last)
4380 {
4381 x = first + ((unsigned)(last - first) >> 1);
4382 cmp = STRCMP(name, functions[x].f_name);
4383 if (cmp < 0)
4384 last = x - 1;
4385 else if (cmp > 0)
4386 first = x + 1;
4387 else
4388 return x;
4389 }
4390 return -1;
4391}
4392
4393/*
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004394 * Check if "name" is a variable of type VAR_FUNC. If so, return the function
4395 * name it contains, otherwise return "name".
4396 */
4397 static char_u *
4398deref_func_name(name, lenp)
4399 char_u *name;
4400 int *lenp;
4401{
4402 VAR v;
4403 int cc;
4404
4405 cc = name[*lenp];
4406 name[*lenp] = NUL;
4407 v = find_var(name, FALSE);
4408 name[*lenp] = cc;
4409 if (v != NULL && v->tv.v_type == VAR_FUNC)
4410 {
4411 if (v->tv.vval.v_string == NULL)
4412 {
4413 *lenp = 0;
4414 return (char_u *)""; /* just in case */
4415 }
4416 *lenp = STRLEN(v->tv.vval.v_string);
4417 return v->tv.vval.v_string;
4418 }
4419
4420 return name;
4421}
4422
4423/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00004424 * Allocate a variable for the result of a function.
4425 * Return OK or FAIL.
4426 */
4427 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004428get_func_tv(name, len, rettv, arg, firstline, lastline, doesrange, evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004429 char_u *name; /* name of the function */
4430 int len; /* length of "name" */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004431 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004432 char_u **arg; /* argument, pointing to the '(' */
4433 linenr_T firstline; /* first line of range */
4434 linenr_T lastline; /* last line of range */
4435 int *doesrange; /* return: function handled range */
4436 int evaluate;
4437{
4438 char_u *argp;
4439 int ret = OK;
4440#define MAX_FUNC_ARGS 20
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004441 typeval argvars[MAX_FUNC_ARGS]; /* vars for arguments */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004442 int argcount = 0; /* number of arguments found */
4443
4444 /*
4445 * Get the arguments.
4446 */
4447 argp = *arg;
4448 while (argcount < MAX_FUNC_ARGS)
4449 {
4450 argp = skipwhite(argp + 1); /* skip the '(' or ',' */
4451 if (*argp == ')' || *argp == ',' || *argp == NUL)
4452 break;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004453 if (eval1(&argp, &argvars[argcount], evaluate) == FAIL)
4454 {
4455 ret = FAIL;
4456 break;
4457 }
4458 ++argcount;
4459 if (*argp != ',')
4460 break;
4461 }
4462 if (*argp == ')')
4463 ++argp;
4464 else
4465 ret = FAIL;
4466
4467 if (ret == OK)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004468 ret = call_func(name, len, rettv, argcount, argvars,
Bram Moolenaar071d4272004-06-13 20:20:40 +00004469 firstline, lastline, doesrange, evaluate);
4470 else if (!aborting())
4471 EMSG2(_("E116: Invalid arguments for function %s"), name);
4472
4473 while (--argcount >= 0)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004474 clear_tv(&argvars[argcount]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004475
4476 *arg = skipwhite(argp);
4477 return ret;
4478}
4479
4480
4481/*
4482 * Call a function with its resolved parameters
4483 * Return OK or FAIL.
4484 */
4485 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004486call_func(name, len, rettv, argcount, argvars, firstline, lastline,
Bram Moolenaar071d4272004-06-13 20:20:40 +00004487 doesrange, evaluate)
4488 char_u *name; /* name of the function */
4489 int len; /* length of "name" */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004490 typeval *rettv; /* return value goes here */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004491 int argcount; /* number of "argvars" */
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004492 typeval *argvars; /* vars for arguments */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004493 linenr_T firstline; /* first line of range */
4494 linenr_T lastline; /* last line of range */
4495 int *doesrange; /* return: function handled range */
4496 int evaluate;
4497{
4498 int ret = FAIL;
4499 static char *errors[] =
4500 {N_("E117: Unknown function: %s"),
4501 N_("E118: Too many arguments for function: %s"),
4502 N_("E119: Not enough arguments for function: %s"),
4503 N_("E120: Using <SID> not in a script context: %s"),
4504 };
4505#define ERROR_UNKNOWN 0
4506#define ERROR_TOOMANY 1
4507#define ERROR_TOOFEW 2
4508#define ERROR_SCRIPT 3
4509#define ERROR_NONE 4
4510#define ERROR_OTHER 5
4511 int error = ERROR_NONE;
4512 int i;
4513 int llen;
4514 ufunc_T *fp;
4515 int cc;
4516#define FLEN_FIXED 40
4517 char_u fname_buf[FLEN_FIXED + 1];
4518 char_u *fname;
4519
4520 /*
4521 * In a script change <SID>name() and s:name() to K_SNR 123_name().
4522 * Change <SNR>123_name() to K_SNR 123_name().
4523 * Use fname_buf[] when it fits, otherwise allocate memory (slow).
4524 */
4525 cc = name[len];
4526 name[len] = NUL;
4527 llen = eval_fname_script(name);
4528 if (llen > 0)
4529 {
4530 fname_buf[0] = K_SPECIAL;
4531 fname_buf[1] = KS_EXTRA;
4532 fname_buf[2] = (int)KE_SNR;
4533 i = 3;
4534 if (eval_fname_sid(name)) /* "<SID>" or "s:" */
4535 {
4536 if (current_SID <= 0)
4537 error = ERROR_SCRIPT;
4538 else
4539 {
4540 sprintf((char *)fname_buf + 3, "%ld_", (long)current_SID);
4541 i = (int)STRLEN(fname_buf);
4542 }
4543 }
4544 if (i + STRLEN(name + llen) < FLEN_FIXED)
4545 {
4546 STRCPY(fname_buf + i, name + llen);
4547 fname = fname_buf;
4548 }
4549 else
4550 {
4551 fname = alloc((unsigned)(i + STRLEN(name + llen) + 1));
4552 if (fname == NULL)
4553 error = ERROR_OTHER;
4554 else
4555 {
4556 mch_memmove(fname, fname_buf, (size_t)i);
4557 STRCPY(fname + i, name + llen);
4558 }
4559 }
4560 }
4561 else
4562 fname = name;
4563
4564 *doesrange = FALSE;
4565
4566
4567 /* execute the function if no errors detected and executing */
4568 if (evaluate && error == ERROR_NONE)
4569 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004570 rettv->v_type = VAR_NUMBER; /* default is number rettv */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004571 error = ERROR_UNKNOWN;
4572
4573 if (!ASCII_ISLOWER(fname[0]))
4574 {
4575 /*
4576 * User defined function.
4577 */
4578 fp = find_func(fname);
4579#ifdef FEAT_AUTOCMD
4580 if (fp == NULL && apply_autocmds(EVENT_FUNCUNDEFINED,
4581 fname, fname, TRUE, NULL)
4582#ifdef FEAT_EVAL
4583 && !aborting()
4584#endif
4585 )
4586 {
4587 /* executed an autocommand, search for function again */
4588 fp = find_func(fname);
4589 }
4590#endif
4591 if (fp != NULL)
4592 {
4593 if (fp->flags & FC_RANGE)
4594 *doesrange = TRUE;
4595 if (argcount < fp->args.ga_len)
4596 error = ERROR_TOOFEW;
4597 else if (!fp->varargs && argcount > fp->args.ga_len)
4598 error = ERROR_TOOMANY;
4599 else
4600 {
4601 /*
4602 * Call the user function.
4603 * Save and restore search patterns, script variables and
4604 * redo buffer.
4605 */
4606 save_search_patterns();
4607 saveRedobuff();
4608 ++fp->calls;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004609 call_user_func(fp, argcount, argvars, rettv,
Bram Moolenaar071d4272004-06-13 20:20:40 +00004610 firstline, lastline);
4611 --fp->calls;
4612 restoreRedobuff();
4613 restore_search_patterns();
4614 error = ERROR_NONE;
4615 }
4616 }
4617 }
4618 else
4619 {
4620 /*
4621 * Find the function name in the table, call its implementation.
4622 */
4623 i = find_internal_func(fname);
4624 if (i >= 0)
4625 {
4626 if (argcount < functions[i].f_min_argc)
4627 error = ERROR_TOOFEW;
4628 else if (argcount > functions[i].f_max_argc)
4629 error = ERROR_TOOMANY;
4630 else
4631 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004632 argvars[argcount].v_type = VAR_UNKNOWN;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004633 functions[i].f_func(argvars, rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004634 error = ERROR_NONE;
4635 }
4636 }
4637 }
4638 /*
4639 * The function call (or "FuncUndefined" autocommand sequence) might
4640 * have been aborted by an error, an interrupt, or an explicitly thrown
4641 * exception that has not been caught so far. This situation can be
4642 * tested for by calling aborting(). For an error in an internal
4643 * function or for the "E132" error in call_user_func(), however, the
4644 * throw point at which the "force_abort" flag (temporarily reset by
4645 * emsg()) is normally updated has not been reached yet. We need to
4646 * update that flag first to make aborting() reliable.
4647 */
4648 update_force_abort();
4649 }
4650 if (error == ERROR_NONE)
4651 ret = OK;
4652
4653 /*
4654 * Report an error unless the argument evaluation or function call has been
4655 * cancelled due to an aborting error, an interrupt, or an exception.
4656 */
4657 if (error < ERROR_NONE && !aborting())
4658 EMSG2((char_u *)_(errors[error]), name);
4659
4660 name[len] = cc;
4661 if (fname != name && fname != fname_buf)
4662 vim_free(fname);
4663
4664 return ret;
4665}
4666
4667/*********************************************
4668 * Implementation of the built-in functions
4669 */
4670
4671/*
4672 * "append(lnum, string)" function
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004673 * or "append(list, item)" function
Bram Moolenaar071d4272004-06-13 20:20:40 +00004674 */
4675 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004676f_append(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004677 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004678 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004679{
4680 long lnum;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00004681 listvar *l;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004682
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004683 rettv->vval.v_number = 1; /* Default: Failed */
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004684 if (argvars[0].v_type == VAR_LIST)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004685 {
Bram Moolenaar8a283e52005-01-06 23:28:25 +00004686 l = argvars[0].vval.v_list;
4687 if (l != NULL && list_append_tv(l, &argvars[1]) == OK)
4688 {
4689 ++l->lv_refcount;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004690 copy_tv(&argvars[0], rettv);
Bram Moolenaar8a283e52005-01-06 23:28:25 +00004691 }
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004692 }
4693 else
4694 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004695 lnum = get_tv_lnum(argvars);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004696 if (lnum >= 0
4697 && lnum <= curbuf->b_ml.ml_line_count
4698 && u_save(lnum, lnum + 1) == OK)
4699 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004700 ml_append(lnum, get_tv_string(&argvars[1]), (colnr_T)0, FALSE);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004701 if (curwin->w_cursor.lnum > lnum)
4702 ++curwin->w_cursor.lnum;
4703 appended_lines_mark(lnum, 1L);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004704 rettv->vval.v_number = 0;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004705 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004706 }
4707}
4708
4709/*
4710 * "argc()" function
4711 */
4712/* ARGSUSED */
4713 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004714f_argc(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004715 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004716 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004717{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004718 rettv->vval.v_number = ARGCOUNT;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004719}
4720
4721/*
4722 * "argidx()" function
4723 */
4724/* ARGSUSED */
4725 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004726f_argidx(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004727 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004728 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004729{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004730 rettv->vval.v_number = curwin->w_arg_idx;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004731}
4732
4733/*
4734 * "argv(nr)" function
4735 */
4736 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004737f_argv(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004738 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004739 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004740{
4741 int idx;
4742
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004743 idx = get_tv_number(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004744 if (idx >= 0 && idx < ARGCOUNT)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004745 rettv->vval.v_string = vim_strsave(alist_name(&ARGLIST[idx]));
Bram Moolenaar071d4272004-06-13 20:20:40 +00004746 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004747 rettv->vval.v_string = NULL;
4748 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004749}
4750
4751/*
4752 * "browse(save, title, initdir, default)" function
4753 */
4754/* ARGSUSED */
4755 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004756f_browse(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004757 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004758 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004759{
4760#ifdef FEAT_BROWSE
4761 int save;
4762 char_u *title;
4763 char_u *initdir;
4764 char_u *defname;
4765 char_u buf[NUMBUFLEN];
4766 char_u buf2[NUMBUFLEN];
4767
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004768 save = get_tv_number(&argvars[0]);
4769 title = get_tv_string(&argvars[1]);
4770 initdir = get_tv_string_buf(&argvars[2], buf);
4771 defname = get_tv_string_buf(&argvars[3], buf2);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004772
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004773 rettv->vval.v_string =
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00004774 do_browse(save ? BROWSE_SAVE : 0,
4775 title, defname, NULL, initdir, NULL, curbuf);
4776#else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004777 rettv->vval.v_string = NULL;
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00004778#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004779 rettv->v_type = VAR_STRING;
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00004780}
4781
4782/*
4783 * "browsedir(title, initdir)" function
4784 */
4785/* ARGSUSED */
4786 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004787f_browsedir(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004788 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004789 typeval *rettv;
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00004790{
4791#ifdef FEAT_BROWSE
4792 char_u *title;
4793 char_u *initdir;
4794 char_u buf[NUMBUFLEN];
4795
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004796 title = get_tv_string(&argvars[0]);
4797 initdir = get_tv_string_buf(&argvars[1], buf);
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00004798
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004799 rettv->vval.v_string = do_browse(BROWSE_DIR,
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00004800 title, NULL, NULL, initdir, NULL, curbuf);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004801#else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004802 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004803#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004804 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004805}
4806
4807/*
4808 * Find a buffer by number or exact name.
4809 */
4810 static buf_T *
4811find_buffer(avar)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004812 typeval *avar;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004813{
4814 buf_T *buf = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004815
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004816 if (avar->v_type == VAR_NUMBER)
4817 buf = buflist_findnr((int)avar->vval.v_number);
4818 else if (avar->vval.v_string != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004819 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004820 buf = buflist_findname_exp(avar->vval.v_string);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004821 if (buf == NULL)
4822 {
4823 /* No full path name match, try a match with a URL or a "nofile"
4824 * buffer, these don't use the full path. */
4825 for (buf = firstbuf; buf != NULL; buf = buf->b_next)
4826 if (buf->b_fname != NULL
4827 && (path_with_url(buf->b_fname)
4828#ifdef FEAT_QUICKFIX
4829 || bt_nofile(buf)
4830#endif
4831 )
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004832 && STRCMP(buf->b_fname, avar->vval.v_string) == 0)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004833 break;
4834 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004835 }
4836 return buf;
4837}
4838
4839/*
4840 * "bufexists(expr)" function
4841 */
4842 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004843f_bufexists(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004844 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004845 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004846{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004847 rettv->vval.v_number = (find_buffer(&argvars[0]) != NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004848}
4849
4850/*
4851 * "buflisted(expr)" function
4852 */
4853 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004854f_buflisted(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004855 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004856 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004857{
4858 buf_T *buf;
4859
4860 buf = find_buffer(&argvars[0]);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004861 rettv->vval.v_number = (buf != NULL && buf->b_p_bl);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004862}
4863
4864/*
4865 * "bufloaded(expr)" function
4866 */
4867 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004868f_bufloaded(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004869 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004870 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004871{
4872 buf_T *buf;
4873
4874 buf = find_buffer(&argvars[0]);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004875 rettv->vval.v_number = (buf != NULL && buf->b_ml.ml_mfp != NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004876}
4877
4878/*
4879 * Get buffer by number or pattern.
4880 */
4881 static buf_T *
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004882get_buf_tv(tv)
4883 typeval *tv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004884{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004885 char_u *name = tv->vval.v_string;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004886 int save_magic;
4887 char_u *save_cpo;
4888 buf_T *buf;
4889
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004890 if (tv->v_type == VAR_NUMBER)
4891 return buflist_findnr((int)tv->vval.v_number);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004892 if (name == NULL || *name == NUL)
4893 return curbuf;
4894 if (name[0] == '$' && name[1] == NUL)
4895 return lastbuf;
4896
4897 /* Ignore 'magic' and 'cpoptions' here to make scripts portable */
4898 save_magic = p_magic;
4899 p_magic = TRUE;
4900 save_cpo = p_cpo;
4901 p_cpo = (char_u *)"";
4902
4903 buf = buflist_findnr(buflist_findpat(name, name + STRLEN(name),
4904 TRUE, FALSE));
4905
4906 p_magic = save_magic;
4907 p_cpo = save_cpo;
4908
4909 /* If not found, try expanding the name, like done for bufexists(). */
4910 if (buf == NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004911 buf = find_buffer(tv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004912
4913 return buf;
4914}
4915
4916/*
4917 * "bufname(expr)" function
4918 */
4919 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004920f_bufname(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004921 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004922 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004923{
4924 buf_T *buf;
4925
4926 ++emsg_off;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004927 buf = get_buf_tv(&argvars[0]);
4928 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004929 if (buf != NULL && buf->b_fname != NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004930 rettv->vval.v_string = vim_strsave(buf->b_fname);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004931 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004932 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004933 --emsg_off;
4934}
4935
4936/*
4937 * "bufnr(expr)" function
4938 */
4939 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004940f_bufnr(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004941 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004942 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004943{
4944 buf_T *buf;
4945
4946 ++emsg_off;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004947 buf = get_buf_tv(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004948 if (buf != NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004949 rettv->vval.v_number = buf->b_fnum;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004950 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004951 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004952 --emsg_off;
4953}
4954
4955/*
4956 * "bufwinnr(nr)" function
4957 */
4958 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004959f_bufwinnr(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004960 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004961 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004962{
4963#ifdef FEAT_WINDOWS
4964 win_T *wp;
4965 int winnr = 0;
4966#endif
4967 buf_T *buf;
4968
4969 ++emsg_off;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004970 buf = get_buf_tv(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004971#ifdef FEAT_WINDOWS
4972 for (wp = firstwin; wp; wp = wp->w_next)
4973 {
4974 ++winnr;
4975 if (wp->w_buffer == buf)
4976 break;
4977 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004978 rettv->vval.v_number = (wp != NULL ? winnr : -1);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004979#else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004980 rettv->vval.v_number = (curwin->w_buffer == buf ? 1 : -1);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004981#endif
4982 --emsg_off;
4983}
4984
4985/*
4986 * "byte2line(byte)" function
4987 */
4988/*ARGSUSED*/
4989 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004990f_byte2line(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004991 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004992 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004993{
4994#ifndef FEAT_BYTEOFF
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004995 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004996#else
4997 long boff = 0;
4998
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004999 boff = get_tv_number(&argvars[0]) - 1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005000 if (boff < 0)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005001 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005002 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005003 rettv->vval.v_number = ml_find_line_or_offset(curbuf,
Bram Moolenaar071d4272004-06-13 20:20:40 +00005004 (linenr_T)0, &boff);
5005#endif
5006}
5007
5008/*
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00005009 * "byteidx()" function
5010 */
5011/*ARGSUSED*/
5012 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005013f_byteidx(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005014 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005015 typeval *rettv;
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00005016{
5017#ifdef FEAT_MBYTE
5018 char_u *t;
5019#endif
5020 char_u *str;
5021 long idx;
5022
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005023 str = get_tv_string(&argvars[0]);
5024 idx = get_tv_number(&argvars[1]);
5025 rettv->vval.v_number = -1;
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00005026 if (idx < 0)
5027 return;
5028
5029#ifdef FEAT_MBYTE
5030 t = str;
5031 for ( ; idx > 0; idx--)
5032 {
5033 if (*t == NUL) /* EOL reached */
5034 return;
5035 t += mb_ptr2len_check(t);
5036 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005037 rettv->vval.v_number = t - str;
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00005038#else
5039 if (idx <= STRLEN(str))
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005040 rettv->vval.v_number = idx;
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00005041#endif
5042}
5043
5044/*
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005045 * "call(func, arglist)" function
5046 */
5047 static void
5048f_call(argvars, rettv)
5049 typeval *argvars;
5050 typeval *rettv;
5051{
5052 char_u *func;
5053 typeval argv[MAX_FUNC_ARGS];
5054 int argc = 0;
5055 listitem *item;
5056 int dummy;
5057
5058 rettv->vval.v_number = 0;
5059 if (argvars[1].v_type != VAR_LIST)
5060 {
5061 EMSG(_(e_listreq));
5062 return;
5063 }
5064 if (argvars[1].vval.v_list == NULL)
5065 return;
5066
5067 if (argvars[0].v_type == VAR_FUNC)
5068 func = argvars[0].vval.v_string;
5069 else
5070 func = get_tv_string(&argvars[0]);
5071
5072 for (item = argvars[1].vval.v_list->lv_first; item != NULL;
5073 item = item->li_next)
5074 {
5075 if (argc == MAX_FUNC_ARGS)
5076 {
5077 EMSG(_("E999: Too many arguments"));
5078 break;
5079 }
5080 /* Make a copy of each argument (is this really needed?) */
5081 copy_tv(&item->li_tv, &argv[argc++]);
5082 }
5083
5084 if (item == NULL)
5085 (void)call_func(func, STRLEN(func), rettv, argc, argv,
5086 curwin->w_cursor.lnum, curwin->w_cursor.lnum, &dummy, TRUE);
5087
5088 /* Free the arguments. */
5089 while (argc > 0)
5090 clear_tv(&argv[--argc]);
5091}
5092
5093/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00005094 * "char2nr(string)" function
5095 */
5096 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005097f_char2nr(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005098 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005099 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005100{
5101#ifdef FEAT_MBYTE
5102 if (has_mbyte)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005103 rettv->vval.v_number =
5104 (*mb_ptr2char)(get_tv_string(&argvars[0]));
Bram Moolenaar071d4272004-06-13 20:20:40 +00005105 else
5106#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005107 rettv->vval.v_number = get_tv_string(&argvars[0])[0];
Bram Moolenaar071d4272004-06-13 20:20:40 +00005108}
5109
5110/*
5111 * "cindent(lnum)" function
5112 */
5113 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005114f_cindent(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005115 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005116 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005117{
5118#ifdef FEAT_CINDENT
5119 pos_T pos;
5120 linenr_T lnum;
5121
5122 pos = curwin->w_cursor;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005123 lnum = get_tv_lnum(argvars);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005124 if (lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count)
5125 {
5126 curwin->w_cursor.lnum = lnum;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005127 rettv->vval.v_number = get_c_indent();
Bram Moolenaar071d4272004-06-13 20:20:40 +00005128 curwin->w_cursor = pos;
5129 }
5130 else
5131#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005132 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005133}
5134
5135/*
5136 * "col(string)" function
5137 */
5138 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005139f_col(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005140 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005141 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005142{
5143 colnr_T col = 0;
5144 pos_T *fp;
5145
5146 fp = var2fpos(&argvars[0], FALSE);
5147 if (fp != NULL)
5148 {
5149 if (fp->col == MAXCOL)
5150 {
5151 /* '> can be MAXCOL, get the length of the line then */
5152 if (fp->lnum <= curbuf->b_ml.ml_line_count)
5153 col = STRLEN(ml_get(fp->lnum)) + 1;
5154 else
5155 col = MAXCOL;
5156 }
5157 else
5158 {
5159 col = fp->col + 1;
5160#ifdef FEAT_VIRTUALEDIT
5161 /* col(".") when the cursor is on the NUL at the end of the line
5162 * because of "coladd" can be seen as an extra column. */
5163 if (virtual_active() && fp == &curwin->w_cursor)
5164 {
5165 char_u *p = ml_get_cursor();
5166
5167 if (curwin->w_cursor.coladd >= (colnr_T)chartabsize(p,
5168 curwin->w_virtcol - curwin->w_cursor.coladd))
5169 {
5170# ifdef FEAT_MBYTE
5171 int l;
5172
5173 if (*p != NUL && p[(l = (*mb_ptr2len_check)(p))] == NUL)
5174 col += l;
5175# else
5176 if (*p != NUL && p[1] == NUL)
5177 ++col;
5178# endif
5179 }
5180 }
5181#endif
5182 }
5183 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005184 rettv->vval.v_number = col;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005185}
5186
5187/*
5188 * "confirm(message, buttons[, default [, type]])" function
5189 */
5190/*ARGSUSED*/
5191 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005192f_confirm(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005193 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005194 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005195{
5196#if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
5197 char_u *message;
5198 char_u *buttons = NULL;
5199 char_u buf[NUMBUFLEN];
5200 char_u buf2[NUMBUFLEN];
5201 int def = 1;
5202 int type = VIM_GENERIC;
5203 int c;
5204
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005205 message = get_tv_string(&argvars[0]);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005206 if (argvars[1].v_type != VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005207 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005208 buttons = get_tv_string_buf(&argvars[1], buf);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005209 if (argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005210 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005211 def = get_tv_number(&argvars[2]);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005212 if (argvars[3].v_type != VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005213 {
5214 /* avoid that TOUPPER_ASC calls get_var_string_buf() twice */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005215 c = *get_tv_string_buf(&argvars[3], buf2);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005216 switch (TOUPPER_ASC(c))
5217 {
5218 case 'E': type = VIM_ERROR; break;
5219 case 'Q': type = VIM_QUESTION; break;
5220 case 'I': type = VIM_INFO; break;
5221 case 'W': type = VIM_WARNING; break;
5222 case 'G': type = VIM_GENERIC; break;
5223 }
5224 }
5225 }
5226 }
5227
5228 if (buttons == NULL || *buttons == NUL)
5229 buttons = (char_u *)_("&Ok");
5230
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005231 rettv->vval.v_number = do_dialog(type, NULL, message, buttons,
Bram Moolenaar071d4272004-06-13 20:20:40 +00005232 def, NULL);
5233#else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005234 rettv->vval.v_number = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005235#endif
5236}
5237
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005238/*
5239 * "copy()" function
5240 */
5241 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005242f_copy(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005243 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005244 typeval *rettv;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005245{
5246 if (argvars[0].v_type == VAR_LIST)
5247 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005248 rettv->v_type = VAR_LIST;
5249 rettv->vval.v_list = list_copy(argvars[0].vval.v_list, FALSE);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005250 }
5251 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005252 copy_tv(&argvars[0], rettv);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005253}
Bram Moolenaar071d4272004-06-13 20:20:40 +00005254
5255/*
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005256 * "count()" function
5257 */
5258 static void
5259f_count(argvars, rettv)
5260 typeval *argvars;
5261 typeval *rettv;
5262{
5263 listitem *li;
5264 long n = 0;
5265 int ic = FALSE;
5266
5267 if (argvars[0].v_type != VAR_LIST)
5268 EMSG(_(e_listreq));
5269 else if (argvars[0].vval.v_list != NULL)
5270 {
5271 if (argvars[2].v_type != VAR_UNKNOWN)
5272 ic = get_tv_number(&argvars[2]);
5273
5274 for (li = argvars[0].vval.v_list->lv_first; li != NULL;
5275 li = li->li_next)
5276 if (tv_equal(&li->li_tv, &argvars[1], ic))
5277 ++n;
5278 }
5279 rettv->vval.v_number = n;
5280}
5281
5282/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00005283 * "cscope_connection([{num} , {dbpath} [, {prepend}]])" function
5284 *
5285 * Checks the existence of a cscope connection.
5286 */
5287/*ARGSUSED*/
5288 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005289f_cscope_connection(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005290 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005291 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005292{
5293#ifdef FEAT_CSCOPE
5294 int num = 0;
5295 char_u *dbpath = NULL;
5296 char_u *prepend = NULL;
5297 char_u buf[NUMBUFLEN];
5298
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005299 if (argvars[0].v_type != VAR_UNKNOWN
5300 && argvars[1].v_type != VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005301 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005302 num = (int)get_tv_number(&argvars[0]);
5303 dbpath = get_tv_string(&argvars[1]);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005304 if (argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005305 prepend = get_tv_string_buf(&argvars[2], buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005306 }
5307
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005308 rettv->vval.v_number = cs_connection(num, dbpath, prepend);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005309#else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005310 rettv->vval.v_number = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005311#endif
5312}
5313
5314/*
5315 * "cursor(lnum, col)" function
5316 *
5317 * Moves the cursor to the specified line and column
5318 */
5319/*ARGSUSED*/
5320 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005321f_cursor(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005322 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005323 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005324{
5325 long line, col;
5326
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005327 line = get_tv_lnum(argvars);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005328 if (line > 0)
5329 curwin->w_cursor.lnum = line;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005330 col = get_tv_number(&argvars[1]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005331 if (col > 0)
5332 curwin->w_cursor.col = col - 1;
5333#ifdef FEAT_VIRTUALEDIT
5334 curwin->w_cursor.coladd = 0;
5335#endif
5336
5337 /* Make sure the cursor is in a valid position. */
5338 check_cursor();
5339#ifdef FEAT_MBYTE
5340 /* Correct cursor for multi-byte character. */
5341 if (has_mbyte)
5342 mb_adjust_cursor();
5343#endif
Bram Moolenaarf4b8e572004-06-24 15:53:16 +00005344
5345 curwin->w_set_curswant = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005346}
5347
5348/*
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005349 * "deepcopy()" function
Bram Moolenaar071d4272004-06-13 20:20:40 +00005350 */
5351 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005352f_deepcopy(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005353 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005354 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005355{
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005356 if (argvars[0].v_type == VAR_LIST)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005357 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005358 rettv->v_type = VAR_LIST;
5359 rettv->vval.v_list = list_copy(argvars[0].vval.v_list, TRUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005360 }
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005361 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005362 copy_tv(&argvars[0], rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005363}
5364
5365/*
5366 * "delete()" function
5367 */
5368 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005369f_delete(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005370 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005371 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005372{
5373 if (check_restricted() || check_secure())
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005374 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005375 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005376 rettv->vval.v_number = mch_remove(get_tv_string(&argvars[0]));
Bram Moolenaar071d4272004-06-13 20:20:40 +00005377}
5378
5379/*
5380 * "did_filetype()" function
5381 */
5382/*ARGSUSED*/
5383 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005384f_did_filetype(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005385 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005386 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005387{
5388#ifdef FEAT_AUTOCMD
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005389 rettv->vval.v_number = did_filetype;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005390#else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005391 rettv->vval.v_number = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005392#endif
5393}
5394
5395/*
Bram Moolenaar47136d72004-10-12 20:02:24 +00005396 * "diff_filler()" function
5397 */
5398/*ARGSUSED*/
5399 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005400f_diff_filler(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005401 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005402 typeval *rettv;
Bram Moolenaar47136d72004-10-12 20:02:24 +00005403{
5404#ifdef FEAT_DIFF
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005405 rettv->vval.v_number = diff_check_fill(curwin, get_tv_lnum(argvars));
Bram Moolenaar47136d72004-10-12 20:02:24 +00005406#endif
5407}
5408
5409/*
5410 * "diff_hlID()" function
5411 */
5412/*ARGSUSED*/
5413 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005414f_diff_hlID(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005415 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005416 typeval *rettv;
Bram Moolenaar47136d72004-10-12 20:02:24 +00005417{
5418#ifdef FEAT_DIFF
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005419 linenr_T lnum = get_tv_lnum(argvars);
Bram Moolenaar47136d72004-10-12 20:02:24 +00005420 static linenr_T prev_lnum = 0;
5421 static int changedtick = 0;
5422 static int fnum = 0;
5423 static int change_start = 0;
5424 static int change_end = 0;
5425 static enum hlf_value hlID = 0;
5426 int filler_lines;
5427 int col;
5428
5429 if (lnum != prev_lnum
5430 || changedtick != curbuf->b_changedtick
5431 || fnum != curbuf->b_fnum)
5432 {
5433 /* New line, buffer, change: need to get the values. */
5434 filler_lines = diff_check(curwin, lnum);
5435 if (filler_lines < 0)
5436 {
5437 if (filler_lines == -1)
5438 {
5439 change_start = MAXCOL;
5440 change_end = -1;
5441 if (diff_find_change(curwin, lnum, &change_start, &change_end))
5442 hlID = HLF_ADD; /* added line */
5443 else
5444 hlID = HLF_CHD; /* changed line */
5445 }
5446 else
5447 hlID = HLF_ADD; /* added line */
5448 }
5449 else
5450 hlID = (enum hlf_value)0;
5451 prev_lnum = lnum;
5452 changedtick = curbuf->b_changedtick;
5453 fnum = curbuf->b_fnum;
5454 }
5455
5456 if (hlID == HLF_CHD || hlID == HLF_TXD)
5457 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005458 col = get_tv_number(&argvars[1]) - 1;
Bram Moolenaar47136d72004-10-12 20:02:24 +00005459 if (col >= change_start && col <= change_end)
5460 hlID = HLF_TXD; /* changed text */
5461 else
5462 hlID = HLF_CHD; /* changed line */
5463 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005464 rettv->vval.v_number = hlID == (enum hlf_value)0 ? 0 : (int)hlID;
Bram Moolenaar47136d72004-10-12 20:02:24 +00005465#endif
5466}
5467
5468/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00005469 * "escape({string}, {chars})" function
5470 */
5471 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005472f_escape(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005473 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005474 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005475{
5476 char_u buf[NUMBUFLEN];
5477
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005478 rettv->vval.v_string =
5479 vim_strsave_escaped(get_tv_string(&argvars[0]),
5480 get_tv_string_buf(&argvars[1], buf));
5481 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005482}
5483
5484/*
5485 * "eventhandler()" function
5486 */
5487/*ARGSUSED*/
5488 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005489f_eventhandler(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005490 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005491 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005492{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005493 rettv->vval.v_number = vgetc_busy;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005494}
5495
5496/*
5497 * "executable()" function
5498 */
5499 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005500f_executable(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005501 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005502 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005503{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005504 rettv->vval.v_number = mch_can_exe(get_tv_string(&argvars[0]));
Bram Moolenaar071d4272004-06-13 20:20:40 +00005505}
5506
5507/*
5508 * "exists()" function
5509 */
5510 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005511f_exists(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005512 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005513 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005514{
5515 char_u *p;
5516 char_u *name;
5517 int n = FALSE;
5518 int len = 0;
5519
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005520 p = get_tv_string(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005521 if (*p == '$') /* environment variable */
5522 {
5523 /* first try "normal" environment variables (fast) */
5524 if (mch_getenv(p + 1) != NULL)
5525 n = TRUE;
5526 else
5527 {
5528 /* try expanding things like $VIM and ${HOME} */
5529 p = expand_env_save(p);
5530 if (p != NULL && *p != '$')
5531 n = TRUE;
5532 vim_free(p);
5533 }
5534 }
5535 else if (*p == '&' || *p == '+') /* option */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005536 n = (get_option_tv(&p, NULL, TRUE) == OK);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005537 else if (*p == '*') /* internal or user defined function */
5538 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005539 n = function_exists(p + 1);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005540 }
5541 else if (*p == ':')
5542 {
5543 n = cmd_exists(p + 1);
5544 }
5545 else if (*p == '#')
5546 {
5547#ifdef FEAT_AUTOCMD
5548 name = p + 1;
5549 p = vim_strchr(name, '#');
5550 if (p != NULL)
5551 n = au_exists(name, p, p + 1);
5552 else
5553 n = au_exists(name, name + STRLEN(name), NULL);
5554#endif
5555 }
5556 else /* internal variable */
5557 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00005558 char_u *expr_start;
5559 char_u *expr_end;
5560 char_u *temp_string = NULL;
5561 char_u *s;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005562 name = p;
5563
Bram Moolenaar071d4272004-06-13 20:20:40 +00005564 /* Find the end of the name. */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005565 s = find_name_end(name, &expr_start, &expr_end, FALSE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005566 if (expr_start != NULL)
5567 {
5568 temp_string = make_expanded_name(name, expr_start, expr_end, s);
5569 if (temp_string != NULL)
5570 {
5571 len = STRLEN(temp_string);
5572 name = temp_string;
5573 }
5574 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00005575 if (len == 0)
5576 len = get_id_len(&p);
5577 if (len != 0)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005578 n = (get_var_tv(name, len, NULL) == OK);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005579
Bram Moolenaar071d4272004-06-13 20:20:40 +00005580 vim_free(temp_string);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005581 }
5582
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005583 rettv->vval.v_number = n;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005584}
5585
5586/*
5587 * "expand()" function
5588 */
5589 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005590f_expand(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005591 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005592 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005593{
5594 char_u *s;
5595 int len;
5596 char_u *errormsg;
5597 int flags = WILD_SILENT|WILD_USE_NL|WILD_LIST_NOTFOUND;
5598 expand_T xpc;
5599
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005600 rettv->v_type = VAR_STRING;
5601 s = get_tv_string(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005602 if (*s == '%' || *s == '#' || *s == '<')
5603 {
5604 ++emsg_off;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005605 rettv->vval.v_string = eval_vars(s, &len, NULL, &errormsg, s);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005606 --emsg_off;
5607 }
5608 else
5609 {
5610 /* When the optional second argument is non-zero, don't remove matches
5611 * for 'suffixes' and 'wildignore' */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005612 if (argvars[1].v_type != VAR_UNKNOWN && get_tv_number(&argvars[1]))
Bram Moolenaar071d4272004-06-13 20:20:40 +00005613 flags |= WILD_KEEP_ALL;
5614 ExpandInit(&xpc);
5615 xpc.xp_context = EXPAND_FILES;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005616 rettv->vval.v_string = ExpandOne(&xpc, s, NULL, flags, WILD_ALL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005617 ExpandCleanup(&xpc);
5618 }
5619}
5620
5621/*
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005622 * "extend(list, list [, idx])" function
5623 */
5624 static void
5625f_extend(argvars, rettv)
5626 typeval *argvars;
5627 typeval *rettv;
5628{
5629 long before;
5630 long n;
5631 listitem *item;
5632 listvar *l1, *l2;
5633
5634 rettv->vval.v_number = 0;
5635 if (argvars[0].v_type != VAR_LIST || argvars[1].v_type != VAR_LIST)
5636 {
5637 EMSG(_(e_listreq));
5638 return;
5639 }
5640 l1 = argvars[0].vval.v_list;
5641 l2 = argvars[1].vval.v_list;
5642 if (l1 != NULL && l2 != NULL)
5643 {
5644 if (argvars[2].v_type != VAR_UNKNOWN)
5645 {
5646 n = before = get_tv_number(&argvars[2]);
5647 item = list_find_ext(l1, &n);
5648 if (n != 0)
5649 {
5650 EMSGN(_(e_listidx), before);
5651 return;
5652 }
5653 }
5654 else
5655 item = NULL;
5656 list_extend(l1, l2, item);
5657
5658 ++l1->lv_refcount;
5659 copy_tv(&argvars[0], rettv);
5660 }
5661}
5662
5663/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00005664 * "filereadable()" function
5665 */
5666 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005667f_filereadable(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005668 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005669 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005670{
5671 FILE *fd;
5672 char_u *p;
5673 int n;
5674
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005675 p = get_tv_string(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005676 if (*p && !mch_isdir(p) && (fd = mch_fopen((char *)p, "r")) != NULL)
5677 {
5678 n = TRUE;
5679 fclose(fd);
5680 }
5681 else
5682 n = FALSE;
5683
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005684 rettv->vval.v_number = n;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005685}
5686
5687/*
5688 * return 0 for not writable, 1 for writable file, 2 for a dir which we have
5689 * rights to write into.
5690 */
5691 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005692f_filewritable(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005693 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005694 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005695{
5696 char_u *p;
5697 int retval = 0;
5698#if defined(UNIX) || defined(VMS)
5699 int perm = 0;
5700#endif
5701
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005702 p = get_tv_string(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005703#if defined(UNIX) || defined(VMS)
5704 perm = mch_getperm(p);
5705#endif
5706#ifndef MACOS_CLASSIC /* TODO: get either mch_writable or mch_access */
5707 if (
5708# ifdef WIN3264
5709 mch_writable(p) &&
5710# else
5711# if defined(UNIX) || defined(VMS)
5712 (perm & 0222) &&
5713# endif
5714# endif
5715 mch_access((char *)p, W_OK) == 0
5716 )
5717#endif
5718 {
5719 ++retval;
5720 if (mch_isdir(p))
5721 ++retval;
5722 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005723 rettv->vval.v_number = retval;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005724}
5725
5726/*
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00005727 * "finddir({fname}[, {path}[, {count}]])" function
5728 */
5729 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005730f_finddir(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005731 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005732 typeval *rettv;
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00005733{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005734 f_findfilendir(argvars, rettv, TRUE);
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00005735}
5736
5737/*
5738 * "findfile({fname}[, {path}[, {count}]])" function
5739 */
5740 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005741f_findfile(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005742 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005743 typeval *rettv;
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00005744{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005745 f_findfilendir(argvars, rettv, FALSE);
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00005746}
5747
5748 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005749f_findfilendir(argvars, rettv, dir)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005750 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005751 typeval *rettv;
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00005752 int dir;
5753{
5754#ifdef FEAT_SEARCHPATH
5755 char_u *fname;
5756 char_u *fresult = NULL;
5757 char_u *path = *curbuf->b_p_path == NUL ? p_path : curbuf->b_p_path;
5758 char_u *p;
5759 char_u pathbuf[NUMBUFLEN];
5760 int count = 1;
5761 int first = TRUE;
5762
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005763 fname = get_tv_string(&argvars[0]);
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00005764
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005765 if (argvars[1].v_type != VAR_UNKNOWN)
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00005766 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005767 p = get_tv_string_buf(&argvars[1], pathbuf);
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00005768 if (*p != NUL)
5769 path = p;
5770
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005771 if (argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005772 count = get_tv_number(&argvars[2]);
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00005773 }
5774
5775 do
5776 {
5777 vim_free(fresult);
5778 fresult = find_file_in_path_option(first ? fname : NULL,
5779 first ? (int)STRLEN(fname) : 0,
5780 0, first, path, dir, NULL);
5781 first = FALSE;
5782 } while (--count > 0 && fresult != NULL);
5783
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005784 rettv->vval.v_string = fresult;
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00005785#else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005786 rettv->vval.v_string = NULL;
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00005787#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005788 rettv->v_type = VAR_STRING;
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00005789}
5790
5791/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00005792 * "fnamemodify({fname}, {mods})" function
5793 */
5794 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005795f_fnamemodify(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005796 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005797 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005798{
5799 char_u *fname;
5800 char_u *mods;
5801 int usedlen = 0;
5802 int len;
5803 char_u *fbuf = NULL;
5804 char_u buf[NUMBUFLEN];
5805
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005806 fname = get_tv_string(&argvars[0]);
5807 mods = get_tv_string_buf(&argvars[1], buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005808 len = (int)STRLEN(fname);
5809
5810 (void)modify_fname(mods, &usedlen, &fname, &fbuf, &len);
5811
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005812 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005813 if (fname == NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005814 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005815 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005816 rettv->vval.v_string = vim_strnsave(fname, len);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005817 vim_free(fbuf);
5818}
5819
5820/*
5821 * "foldclosed()" function
5822 */
5823 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005824f_foldclosed(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005825 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005826 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005827{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005828 foldclosed_both(argvars, rettv, FALSE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005829}
5830
5831/*
5832 * "foldclosedend()" function
5833 */
5834 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005835f_foldclosedend(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005836 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005837 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005838{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005839 foldclosed_both(argvars, rettv, TRUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005840}
5841
5842/*
5843 * "foldclosed()" function
5844 */
5845 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005846foldclosed_both(argvars, rettv, end)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005847 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005848 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005849 int end;
5850{
5851#ifdef FEAT_FOLDING
5852 linenr_T lnum;
5853 linenr_T first, last;
5854
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005855 lnum = get_tv_lnum(argvars);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005856 if (lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count)
5857 {
5858 if (hasFoldingWin(curwin, lnum, &first, &last, FALSE, NULL))
5859 {
5860 if (end)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005861 rettv->vval.v_number = (varnumber_T)last;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005862 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005863 rettv->vval.v_number = (varnumber_T)first;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005864 return;
5865 }
5866 }
5867#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005868 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005869}
5870
5871/*
5872 * "foldlevel()" function
5873 */
5874 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005875f_foldlevel(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005876 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005877 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005878{
5879#ifdef FEAT_FOLDING
5880 linenr_T lnum;
5881
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005882 lnum = get_tv_lnum(argvars);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005883 if (lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005884 rettv->vval.v_number = foldLevel(lnum);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005885 else
5886#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005887 rettv->vval.v_number = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005888}
5889
5890/*
5891 * "foldtext()" function
5892 */
5893/*ARGSUSED*/
5894 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005895f_foldtext(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005896 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005897 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005898{
5899#ifdef FEAT_FOLDING
5900 linenr_T lnum;
5901 char_u *s;
5902 char_u *r;
5903 int len;
5904 char *txt;
5905#endif
5906
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005907 rettv->v_type = VAR_STRING;
5908 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005909#ifdef FEAT_FOLDING
5910 if ((linenr_T)vimvars[VV_FOLDSTART].val > 0
5911 && (linenr_T)vimvars[VV_FOLDEND].val <= curbuf->b_ml.ml_line_count
5912 && vimvars[VV_FOLDDASHES].val != NULL)
5913 {
5914 /* Find first non-empty line in the fold. */
5915 lnum = (linenr_T)vimvars[VV_FOLDSTART].val;
5916 while (lnum < (linenr_T)vimvars[VV_FOLDEND].val)
5917 {
5918 if (!linewhite(lnum))
5919 break;
5920 ++lnum;
5921 }
5922
5923 /* Find interesting text in this line. */
5924 s = skipwhite(ml_get(lnum));
5925 /* skip C comment-start */
5926 if (s[0] == '/' && (s[1] == '*' || s[1] == '/'))
Bram Moolenaar293ee4d2004-12-09 21:34:53 +00005927 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00005928 s = skipwhite(s + 2);
Bram Moolenaar293ee4d2004-12-09 21:34:53 +00005929 if (*skipwhite(s) == NUL
5930 && lnum + 1 < (linenr_T)vimvars[VV_FOLDEND].val)
5931 {
5932 s = skipwhite(ml_get(lnum + 1));
5933 if (*s == '*')
5934 s = skipwhite(s + 1);
5935 }
5936 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00005937 txt = _("+-%s%3ld lines: ");
5938 r = alloc((unsigned)(STRLEN(txt)
5939 + STRLEN(vimvars[VV_FOLDDASHES].val) /* for %s */
5940 + 20 /* for %3ld */
5941 + STRLEN(s))); /* concatenated */
5942 if (r != NULL)
5943 {
5944 sprintf((char *)r, txt, vimvars[VV_FOLDDASHES].val,
5945 (long)((linenr_T)vimvars[VV_FOLDEND].val
5946 - (linenr_T)vimvars[VV_FOLDSTART].val + 1));
5947 len = (int)STRLEN(r);
5948 STRCAT(r, s);
5949 /* remove 'foldmarker' and 'commentstring' */
5950 foldtext_cleanup(r + len);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005951 rettv->vval.v_string = r;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005952 }
5953 }
5954#endif
5955}
5956
5957/*
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00005958 * "foldtextresult(lnum)" function
5959 */
5960/*ARGSUSED*/
5961 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005962f_foldtextresult(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005963 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005964 typeval *rettv;
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00005965{
5966#ifdef FEAT_FOLDING
5967 linenr_T lnum;
5968 char_u *text;
5969 char_u buf[51];
5970 foldinfo_T foldinfo;
5971 int fold_count;
5972#endif
5973
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005974 rettv->v_type = VAR_STRING;
5975 rettv->vval.v_string = NULL;
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00005976#ifdef FEAT_FOLDING
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005977 lnum = get_tv_lnum(argvars);
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00005978 fold_count = foldedCount(curwin, lnum, &foldinfo);
5979 if (fold_count > 0)
5980 {
5981 text = get_foldtext(curwin, lnum, lnum + fold_count - 1,
5982 &foldinfo, buf);
5983 if (text == buf)
5984 text = vim_strsave(text);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005985 rettv->vval.v_string = text;
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00005986 }
5987#endif
5988}
5989
5990/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00005991 * "foreground()" function
5992 */
5993/*ARGSUSED*/
5994 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005995f_foreground(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005996 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005997 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005998{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005999 rettv->vval.v_number = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006000#ifdef FEAT_GUI
6001 if (gui.in_use)
6002 gui_mch_set_foreground();
6003#else
6004# ifdef WIN32
6005 win32_set_foreground();
6006# endif
6007#endif
6008}
6009
6010/*
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006011 * "function()" function
6012 */
6013/*ARGSUSED*/
6014 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006015f_function(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006016 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006017 typeval *rettv;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006018{
6019 char_u *s;
6020
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006021 s = get_tv_string(&argvars[0]);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006022 if (s == NULL || *s == NUL || isdigit(*s))
6023 EMSG2(_(e_invarg2), s);
6024 else if (!function_exists(s))
6025 EMSG2(_("E999: Unknown function: %s"), s);
6026 else
6027 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006028 rettv->vval.v_string = vim_strsave(s);
6029 rettv->v_type = VAR_FUNC;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006030 }
6031}
6032
6033/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00006034 * "getchar()" function
6035 */
6036 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006037f_getchar(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006038 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006039 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006040{
6041 varnumber_T n;
6042
6043 ++no_mapping;
6044 ++allow_keys;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006045 if (argvars[0].v_type == VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006046 /* getchar(): blocking wait. */
6047 n = safe_vgetc();
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006048 else if (get_tv_number(&argvars[0]) == 1)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006049 /* getchar(1): only check if char avail */
6050 n = vpeekc();
6051 else if (vpeekc() == NUL)
6052 /* getchar(0) and no char avail: return zero */
6053 n = 0;
6054 else
6055 /* getchar(0) and char avail: return char */
6056 n = safe_vgetc();
6057 --no_mapping;
6058 --allow_keys;
6059
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006060 rettv->vval.v_number = n;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006061 if (IS_SPECIAL(n) || mod_mask != 0)
6062 {
6063 char_u temp[10]; /* modifier: 3, mbyte-char: 6, NUL: 1 */
6064 int i = 0;
6065
6066 /* Turn a special key into three bytes, plus modifier. */
6067 if (mod_mask != 0)
6068 {
6069 temp[i++] = K_SPECIAL;
6070 temp[i++] = KS_MODIFIER;
6071 temp[i++] = mod_mask;
6072 }
6073 if (IS_SPECIAL(n))
6074 {
6075 temp[i++] = K_SPECIAL;
6076 temp[i++] = K_SECOND(n);
6077 temp[i++] = K_THIRD(n);
6078 }
6079#ifdef FEAT_MBYTE
6080 else if (has_mbyte)
6081 i += (*mb_char2bytes)(n, temp + i);
6082#endif
6083 else
6084 temp[i++] = n;
6085 temp[i++] = NUL;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006086 rettv->v_type = VAR_STRING;
6087 rettv->vval.v_string = vim_strsave(temp);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006088 }
6089}
6090
6091/*
6092 * "getcharmod()" function
6093 */
6094/*ARGSUSED*/
6095 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006096f_getcharmod(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006097 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006098 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006099{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006100 rettv->vval.v_number = mod_mask;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006101}
6102
6103/*
6104 * "getcmdline()" function
6105 */
6106/*ARGSUSED*/
6107 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006108f_getcmdline(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006109 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006110 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006111{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006112 rettv->v_type = VAR_STRING;
6113 rettv->vval.v_string = get_cmdline_str();
Bram Moolenaar071d4272004-06-13 20:20:40 +00006114}
6115
6116/*
6117 * "getcmdpos()" function
6118 */
6119/*ARGSUSED*/
6120 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006121f_getcmdpos(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006122 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006123 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006124{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006125 rettv->vval.v_number = get_cmdline_pos() + 1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006126}
6127
6128/*
6129 * "getbufvar()" function
6130 */
6131 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006132f_getbufvar(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006133 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006134 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006135{
6136 buf_T *buf;
6137 buf_T *save_curbuf;
6138 char_u *varname;
6139 VAR v;
6140
6141 ++emsg_off;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006142 buf = get_buf_tv(&argvars[0]);
6143 varname = get_tv_string(&argvars[1]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006144
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006145 rettv->v_type = VAR_STRING;
6146 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006147
6148 if (buf != NULL && varname != NULL)
6149 {
6150 if (*varname == '&') /* buffer-local-option */
6151 {
6152 /* set curbuf to be our buf, temporarily */
6153 save_curbuf = curbuf;
6154 curbuf = buf;
6155
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006156 get_option_tv(&varname, rettv, TRUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006157
6158 /* restore previous notion of curbuf */
6159 curbuf = save_curbuf;
6160 }
6161 else
6162 {
6163 /* look up the variable */
6164 v = find_var_in_ga(&buf->b_vars, varname);
6165 if (v != NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006166 copy_tv(&v->tv, rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006167 }
6168 }
6169
6170 --emsg_off;
6171}
6172
6173/*
6174 * "getcwd()" function
6175 */
6176/*ARGSUSED*/
6177 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006178f_getcwd(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006179 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006180 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006181{
6182 char_u cwd[MAXPATHL];
6183
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006184 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006185 if (mch_dirname(cwd, MAXPATHL) == FAIL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006186 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006187 else
6188 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006189 rettv->vval.v_string = vim_strsave(cwd);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006190#ifdef BACKSLASH_IN_FILENAME
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006191 slash_adjust(rettv->vval.v_string);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006192#endif
6193 }
6194}
6195
6196/*
Bram Moolenaar46c9c732004-12-12 11:37:09 +00006197 * "getfontname()" function
6198 */
Bram Moolenaar1cd871b2004-12-19 22:46:22 +00006199/*ARGSUSED*/
Bram Moolenaar46c9c732004-12-12 11:37:09 +00006200 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006201f_getfontname(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006202 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006203 typeval *rettv;
Bram Moolenaar46c9c732004-12-12 11:37:09 +00006204{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006205 rettv->v_type = VAR_STRING;
6206 rettv->vval.v_string = NULL;
Bram Moolenaar46c9c732004-12-12 11:37:09 +00006207#ifdef FEAT_GUI
6208 if (gui.in_use)
6209 {
6210 GuiFont font;
6211 char_u *name = NULL;
6212
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006213 if (argvars[0].v_type == VAR_UNKNOWN)
Bram Moolenaar46c9c732004-12-12 11:37:09 +00006214 {
6215 /* Get the "Normal" font. Either the name saved by
6216 * hl_set_font_name() or from the font ID. */
6217 font = gui.norm_font;
6218 name = hl_get_font_name();
6219 }
6220 else
6221 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006222 name = get_tv_string(&argvars[0]);
Bram Moolenaar46c9c732004-12-12 11:37:09 +00006223 if (STRCMP(name, "*") == 0) /* don't use font dialog */
6224 return;
6225 font = gui_mch_get_font(name, FALSE);
6226 if (font == NOFONT)
6227 return; /* Invalid font name, return empty string. */
6228 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006229 rettv->vval.v_string = gui_mch_get_fontname(font, name);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006230 if (argvars[0].v_type != VAR_UNKNOWN)
Bram Moolenaar46c9c732004-12-12 11:37:09 +00006231 gui_mch_free_font(font);
6232 }
6233#endif
6234}
6235
6236/*
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00006237 * "getfperm({fname})" function
6238 */
6239 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006240f_getfperm(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006241 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006242 typeval *rettv;
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00006243{
6244 char_u *fname;
6245 struct stat st;
6246 char_u *perm = NULL;
6247 char_u flags[] = "rwx";
6248 int i;
6249
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006250 fname = get_tv_string(&argvars[0]);
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00006251
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006252 rettv->v_type = VAR_STRING;
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00006253 if (mch_stat((char *)fname, &st) >= 0)
6254 {
6255 perm = vim_strsave((char_u *)"---------");
6256 if (perm != NULL)
6257 {
6258 for (i = 0; i < 9; i++)
6259 {
6260 if (st.st_mode & (1 << (8 - i)))
6261 perm[i] = flags[i % 3];
6262 }
6263 }
6264 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006265 rettv->vval.v_string = perm;
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00006266}
6267
6268/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00006269 * "getfsize({fname})" function
6270 */
6271 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006272f_getfsize(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006273 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006274 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006275{
6276 char_u *fname;
6277 struct stat st;
6278
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006279 fname = get_tv_string(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006280
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006281 rettv->v_type = VAR_NUMBER;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006282
6283 if (mch_stat((char *)fname, &st) >= 0)
6284 {
6285 if (mch_isdir(fname))
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006286 rettv->vval.v_number = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006287 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006288 rettv->vval.v_number = (varnumber_T)st.st_size;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006289 }
6290 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006291 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006292}
6293
6294/*
6295 * "getftime({fname})" function
6296 */
6297 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006298f_getftime(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006299 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006300 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006301{
6302 char_u *fname;
6303 struct stat st;
6304
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006305 fname = get_tv_string(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006306
6307 if (mch_stat((char *)fname, &st) >= 0)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006308 rettv->vval.v_number = (varnumber_T)st.st_mtime;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006309 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006310 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006311}
6312
6313/*
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00006314 * "getftype({fname})" function
6315 */
6316 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006317f_getftype(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006318 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006319 typeval *rettv;
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00006320{
6321 char_u *fname;
6322 struct stat st;
6323 char_u *type = NULL;
6324 char *t;
6325
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006326 fname = get_tv_string(&argvars[0]);
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00006327
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006328 rettv->v_type = VAR_STRING;
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00006329 if (mch_lstat((char *)fname, &st) >= 0)
6330 {
6331#ifdef S_ISREG
6332 if (S_ISREG(st.st_mode))
6333 t = "file";
6334 else if (S_ISDIR(st.st_mode))
6335 t = "dir";
6336# ifdef S_ISLNK
6337 else if (S_ISLNK(st.st_mode))
6338 t = "link";
6339# endif
6340# ifdef S_ISBLK
6341 else if (S_ISBLK(st.st_mode))
6342 t = "bdev";
6343# endif
6344# ifdef S_ISCHR
6345 else if (S_ISCHR(st.st_mode))
6346 t = "cdev";
6347# endif
6348# ifdef S_ISFIFO
6349 else if (S_ISFIFO(st.st_mode))
6350 t = "fifo";
6351# endif
6352# ifdef S_ISSOCK
6353 else if (S_ISSOCK(st.st_mode))
6354 t = "fifo";
6355# endif
6356 else
6357 t = "other";
6358#else
6359# ifdef S_IFMT
6360 switch (st.st_mode & S_IFMT)
6361 {
6362 case S_IFREG: t = "file"; break;
6363 case S_IFDIR: t = "dir"; break;
6364# ifdef S_IFLNK
6365 case S_IFLNK: t = "link"; break;
6366# endif
6367# ifdef S_IFBLK
6368 case S_IFBLK: t = "bdev"; break;
6369# endif
6370# ifdef S_IFCHR
6371 case S_IFCHR: t = "cdev"; break;
6372# endif
6373# ifdef S_IFIFO
6374 case S_IFIFO: t = "fifo"; break;
6375# endif
6376# ifdef S_IFSOCK
6377 case S_IFSOCK: t = "socket"; break;
6378# endif
6379 default: t = "other";
6380 }
6381# else
6382 if (mch_isdir(fname))
6383 t = "dir";
6384 else
6385 t = "file";
6386# endif
6387#endif
6388 type = vim_strsave((char_u *)t);
6389 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006390 rettv->vval.v_string = type;
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00006391}
6392
6393/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00006394 * "getreg()" function
6395 */
6396 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006397f_getreg(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006398 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006399 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006400{
6401 char_u *strregname;
6402 int regname;
6403
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006404 if (argvars[0].v_type != VAR_UNKNOWN)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006405 strregname = get_tv_string(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006406 else
6407 strregname = vimvars[VV_REG].val;
6408 regname = (strregname == NULL ? '"' : *strregname);
6409 if (regname == 0)
6410 regname = '"';
6411
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006412 rettv->v_type = VAR_STRING;
6413 rettv->vval.v_string = get_reg_contents(regname, TRUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006414}
6415
6416/*
6417 * "getregtype()" function
6418 */
6419 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006420f_getregtype(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006421 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006422 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006423{
6424 char_u *strregname;
6425 int regname;
6426 char_u buf[NUMBUFLEN + 2];
6427 long reglen = 0;
6428
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006429 if (argvars[0].v_type != VAR_UNKNOWN)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006430 strregname = get_tv_string(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006431 else
6432 /* Default to v:register */
6433 strregname = vimvars[VV_REG].val;
6434
6435 regname = (strregname == NULL ? '"' : *strregname);
6436 if (regname == 0)
6437 regname = '"';
6438
6439 buf[0] = NUL;
6440 buf[1] = NUL;
6441 switch (get_reg_type(regname, &reglen))
6442 {
6443 case MLINE: buf[0] = 'V'; break;
6444 case MCHAR: buf[0] = 'v'; break;
6445#ifdef FEAT_VISUAL
6446 case MBLOCK:
6447 buf[0] = Ctrl_V;
6448 sprintf((char *)buf + 1, "%ld", reglen + 1);
6449 break;
6450#endif
6451 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006452 rettv->v_type = VAR_STRING;
6453 rettv->vval.v_string = vim_strsave(buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006454}
6455
6456/*
6457 * "getline(lnum)" function
6458 */
6459 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006460f_getline(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006461 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006462 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006463{
6464 linenr_T lnum;
6465 char_u *p;
6466
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006467 lnum = get_tv_lnum(argvars);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006468
6469 if (lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count)
6470 p = ml_get(lnum);
6471 else
6472 p = (char_u *)"";
6473
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006474 rettv->v_type = VAR_STRING;
6475 rettv->vval.v_string = vim_strsave(p);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006476}
6477
6478/*
6479 * "getwinposx()" function
6480 */
6481/*ARGSUSED*/
6482 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006483f_getwinposx(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006484 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006485 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006486{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006487 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006488#ifdef FEAT_GUI
6489 if (gui.in_use)
6490 {
6491 int x, y;
6492
6493 if (gui_mch_get_winpos(&x, &y) == OK)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006494 rettv->vval.v_number = x;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006495 }
6496#endif
6497}
6498
6499/*
6500 * "getwinposy()" function
6501 */
6502/*ARGSUSED*/
6503 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006504f_getwinposy(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006505 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006506 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006507{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006508 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006509#ifdef FEAT_GUI
6510 if (gui.in_use)
6511 {
6512 int x, y;
6513
6514 if (gui_mch_get_winpos(&x, &y) == OK)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006515 rettv->vval.v_number = y;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006516 }
6517#endif
6518}
6519
6520/*
6521 * "getwinvar()" function
6522 */
6523 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006524f_getwinvar(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006525 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006526 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006527{
6528 win_T *win, *oldcurwin;
6529 char_u *varname;
6530 VAR v;
6531
6532 ++emsg_off;
6533 win = find_win_by_nr(&argvars[0]);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006534 varname = get_tv_string(&argvars[1]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006535
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006536 rettv->v_type = VAR_STRING;
6537 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006538
6539 if (win != NULL && varname != NULL)
6540 {
6541 if (*varname == '&') /* window-local-option */
6542 {
6543 /* set curwin to be our win, temporarily */
6544 oldcurwin = curwin;
6545 curwin = win;
6546
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006547 get_option_tv(&varname, rettv, 1);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006548
6549 /* restore previous notion of curwin */
6550 curwin = oldcurwin;
6551 }
6552 else
6553 {
6554 /* look up the variable */
6555 v = find_var_in_ga(&win->w_vars, varname);
6556 if (v != NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006557 copy_tv(&v->tv, rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006558 }
6559 }
6560
6561 --emsg_off;
6562}
6563
6564/*
6565 * "glob()" function
6566 */
6567 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006568f_glob(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006569 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006570 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006571{
6572 expand_T xpc;
6573
6574 ExpandInit(&xpc);
6575 xpc.xp_context = EXPAND_FILES;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006576 rettv->v_type = VAR_STRING;
6577 rettv->vval.v_string = ExpandOne(&xpc, get_tv_string(&argvars[0]),
Bram Moolenaar071d4272004-06-13 20:20:40 +00006578 NULL, WILD_USE_NL|WILD_SILENT, WILD_ALL);
6579 ExpandCleanup(&xpc);
6580}
6581
6582/*
6583 * "globpath()" function
6584 */
6585 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006586f_globpath(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006587 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006588 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006589{
6590 char_u buf1[NUMBUFLEN];
6591
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006592 rettv->v_type = VAR_STRING;
6593 rettv->vval.v_string = globpath(get_tv_string(&argvars[0]),
6594 get_tv_string_buf(&argvars[1], buf1));
Bram Moolenaar071d4272004-06-13 20:20:40 +00006595}
6596
6597/*
6598 * "has()" function
6599 */
6600 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006601f_has(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006602 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006603 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006604{
6605 int i;
6606 char_u *name;
6607 int n = FALSE;
6608 static char *(has_list[]) =
6609 {
6610#ifdef AMIGA
6611 "amiga",
6612# ifdef FEAT_ARP
6613 "arp",
6614# endif
6615#endif
6616#ifdef __BEOS__
6617 "beos",
6618#endif
6619#ifdef MSDOS
6620# ifdef DJGPP
6621 "dos32",
6622# else
6623 "dos16",
6624# endif
6625#endif
6626#ifdef MACOS /* TODO: Should we add MACOS_CLASSIC, MACOS_X? (Dany) */
6627 "mac",
6628#endif
6629#if defined(MACOS_X_UNIX)
6630 "macunix",
6631#endif
6632#ifdef OS2
6633 "os2",
6634#endif
6635#ifdef __QNX__
6636 "qnx",
6637#endif
6638#ifdef RISCOS
6639 "riscos",
6640#endif
6641#ifdef UNIX
6642 "unix",
6643#endif
6644#ifdef VMS
6645 "vms",
6646#endif
6647#ifdef WIN16
6648 "win16",
6649#endif
6650#ifdef WIN32
6651 "win32",
6652#endif
6653#if defined(UNIX) && (defined(__CYGWIN32__) || defined(__CYGWIN__))
6654 "win32unix",
6655#endif
6656#ifdef WIN64
6657 "win64",
6658#endif
6659#ifdef EBCDIC
6660 "ebcdic",
6661#endif
6662#ifndef CASE_INSENSITIVE_FILENAME
6663 "fname_case",
6664#endif
6665#ifdef FEAT_ARABIC
6666 "arabic",
6667#endif
6668#ifdef FEAT_AUTOCMD
6669 "autocmd",
6670#endif
6671#ifdef FEAT_BEVAL
6672 "balloon_eval",
6673#endif
6674#if defined(SOME_BUILTIN_TCAPS) || defined(ALL_BUILTIN_TCAPS)
6675 "builtin_terms",
6676# ifdef ALL_BUILTIN_TCAPS
6677 "all_builtin_terms",
6678# endif
6679#endif
6680#ifdef FEAT_BYTEOFF
6681 "byte_offset",
6682#endif
6683#ifdef FEAT_CINDENT
6684 "cindent",
6685#endif
6686#ifdef FEAT_CLIENTSERVER
6687 "clientserver",
6688#endif
6689#ifdef FEAT_CLIPBOARD
6690 "clipboard",
6691#endif
6692#ifdef FEAT_CMDL_COMPL
6693 "cmdline_compl",
6694#endif
6695#ifdef FEAT_CMDHIST
6696 "cmdline_hist",
6697#endif
6698#ifdef FEAT_COMMENTS
6699 "comments",
6700#endif
6701#ifdef FEAT_CRYPT
6702 "cryptv",
6703#endif
6704#ifdef FEAT_CSCOPE
6705 "cscope",
6706#endif
6707#ifdef DEBUG
6708 "debug",
6709#endif
6710#ifdef FEAT_CON_DIALOG
6711 "dialog_con",
6712#endif
6713#ifdef FEAT_GUI_DIALOG
6714 "dialog_gui",
6715#endif
6716#ifdef FEAT_DIFF
6717 "diff",
6718#endif
6719#ifdef FEAT_DIGRAPHS
6720 "digraphs",
6721#endif
6722#ifdef FEAT_DND
6723 "dnd",
6724#endif
6725#ifdef FEAT_EMACS_TAGS
6726 "emacs_tags",
6727#endif
6728 "eval", /* always present, of course! */
6729#ifdef FEAT_EX_EXTRA
6730 "ex_extra",
6731#endif
6732#ifdef FEAT_SEARCH_EXTRA
6733 "extra_search",
6734#endif
6735#ifdef FEAT_FKMAP
6736 "farsi",
6737#endif
6738#ifdef FEAT_SEARCHPATH
6739 "file_in_path",
6740#endif
6741#ifdef FEAT_FIND_ID
6742 "find_in_path",
6743#endif
6744#ifdef FEAT_FOLDING
6745 "folding",
6746#endif
6747#ifdef FEAT_FOOTER
6748 "footer",
6749#endif
6750#if !defined(USE_SYSTEM) && defined(UNIX)
6751 "fork",
6752#endif
6753#ifdef FEAT_GETTEXT
6754 "gettext",
6755#endif
6756#ifdef FEAT_GUI
6757 "gui",
6758#endif
6759#ifdef FEAT_GUI_ATHENA
6760# ifdef FEAT_GUI_NEXTAW
6761 "gui_neXtaw",
6762# else
6763 "gui_athena",
6764# endif
6765#endif
Bram Moolenaar843ee412004-06-30 16:16:41 +00006766#ifdef FEAT_GUI_KDE
6767 "gui_kde",
6768#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00006769#ifdef FEAT_GUI_GTK
6770 "gui_gtk",
6771# ifdef HAVE_GTK2
6772 "gui_gtk2",
6773# endif
6774#endif
6775#ifdef FEAT_GUI_MAC
6776 "gui_mac",
6777#endif
6778#ifdef FEAT_GUI_MOTIF
6779 "gui_motif",
6780#endif
6781#ifdef FEAT_GUI_PHOTON
6782 "gui_photon",
6783#endif
6784#ifdef FEAT_GUI_W16
6785 "gui_win16",
6786#endif
6787#ifdef FEAT_GUI_W32
6788 "gui_win32",
6789#endif
6790#ifdef FEAT_HANGULIN
6791 "hangul_input",
6792#endif
6793#if defined(HAVE_ICONV_H) && defined(USE_ICONV)
6794 "iconv",
6795#endif
6796#ifdef FEAT_INS_EXPAND
6797 "insert_expand",
6798#endif
6799#ifdef FEAT_JUMPLIST
6800 "jumplist",
6801#endif
6802#ifdef FEAT_KEYMAP
6803 "keymap",
6804#endif
6805#ifdef FEAT_LANGMAP
6806 "langmap",
6807#endif
6808#ifdef FEAT_LIBCALL
6809 "libcall",
6810#endif
6811#ifdef FEAT_LINEBREAK
6812 "linebreak",
6813#endif
6814#ifdef FEAT_LISP
6815 "lispindent",
6816#endif
6817#ifdef FEAT_LISTCMDS
6818 "listcmds",
6819#endif
6820#ifdef FEAT_LOCALMAP
6821 "localmap",
6822#endif
6823#ifdef FEAT_MENU
6824 "menu",
6825#endif
6826#ifdef FEAT_SESSION
6827 "mksession",
6828#endif
6829#ifdef FEAT_MODIFY_FNAME
6830 "modify_fname",
6831#endif
6832#ifdef FEAT_MOUSE
6833 "mouse",
6834#endif
6835#ifdef FEAT_MOUSESHAPE
6836 "mouseshape",
6837#endif
6838#if defined(UNIX) || defined(VMS)
6839# ifdef FEAT_MOUSE_DEC
6840 "mouse_dec",
6841# endif
6842# ifdef FEAT_MOUSE_GPM
6843 "mouse_gpm",
6844# endif
6845# ifdef FEAT_MOUSE_JSB
6846 "mouse_jsbterm",
6847# endif
6848# ifdef FEAT_MOUSE_NET
6849 "mouse_netterm",
6850# endif
6851# ifdef FEAT_MOUSE_PTERM
6852 "mouse_pterm",
6853# endif
6854# ifdef FEAT_MOUSE_XTERM
6855 "mouse_xterm",
6856# endif
6857#endif
6858#ifdef FEAT_MBYTE
6859 "multi_byte",
6860#endif
6861#ifdef FEAT_MBYTE_IME
6862 "multi_byte_ime",
6863#endif
6864#ifdef FEAT_MULTI_LANG
6865 "multi_lang",
6866#endif
Bram Moolenaar325b7a22004-07-05 15:58:32 +00006867#ifdef FEAT_MZSCHEME
6868 "mzscheme",
6869#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00006870#ifdef FEAT_OLE
6871 "ole",
6872#endif
6873#ifdef FEAT_OSFILETYPE
6874 "osfiletype",
6875#endif
6876#ifdef FEAT_PATH_EXTRA
6877 "path_extra",
6878#endif
6879#ifdef FEAT_PERL
6880#ifndef DYNAMIC_PERL
6881 "perl",
6882#endif
6883#endif
6884#ifdef FEAT_PYTHON
6885#ifndef DYNAMIC_PYTHON
6886 "python",
6887#endif
6888#endif
6889#ifdef FEAT_POSTSCRIPT
6890 "postscript",
6891#endif
6892#ifdef FEAT_PRINTER
6893 "printer",
6894#endif
6895#ifdef FEAT_QUICKFIX
6896 "quickfix",
6897#endif
6898#ifdef FEAT_RIGHTLEFT
6899 "rightleft",
6900#endif
6901#if defined(FEAT_RUBY) && !defined(DYNAMIC_RUBY)
6902 "ruby",
6903#endif
6904#ifdef FEAT_SCROLLBIND
6905 "scrollbind",
6906#endif
6907#ifdef FEAT_CMDL_INFO
6908 "showcmd",
6909 "cmdline_info",
6910#endif
6911#ifdef FEAT_SIGNS
6912 "signs",
6913#endif
6914#ifdef FEAT_SMARTINDENT
6915 "smartindent",
6916#endif
6917#ifdef FEAT_SNIFF
6918 "sniff",
6919#endif
6920#ifdef FEAT_STL_OPT
6921 "statusline",
6922#endif
6923#ifdef FEAT_SUN_WORKSHOP
6924 "sun_workshop",
6925#endif
6926#ifdef FEAT_NETBEANS_INTG
6927 "netbeans_intg",
6928#endif
6929#ifdef FEAT_SYN_HL
6930 "syntax",
6931#endif
6932#if defined(USE_SYSTEM) || !defined(UNIX)
6933 "system",
6934#endif
6935#ifdef FEAT_TAG_BINS
6936 "tag_binary",
6937#endif
6938#ifdef FEAT_TAG_OLDSTATIC
6939 "tag_old_static",
6940#endif
6941#ifdef FEAT_TAG_ANYWHITE
6942 "tag_any_white",
6943#endif
6944#ifdef FEAT_TCL
6945# ifndef DYNAMIC_TCL
6946 "tcl",
6947# endif
6948#endif
6949#ifdef TERMINFO
6950 "terminfo",
6951#endif
6952#ifdef FEAT_TERMRESPONSE
6953 "termresponse",
6954#endif
6955#ifdef FEAT_TEXTOBJ
6956 "textobjects",
6957#endif
6958#ifdef HAVE_TGETENT
6959 "tgetent",
6960#endif
6961#ifdef FEAT_TITLE
6962 "title",
6963#endif
6964#ifdef FEAT_TOOLBAR
6965 "toolbar",
6966#endif
6967#ifdef FEAT_USR_CMDS
6968 "user-commands", /* was accidentally included in 5.4 */
6969 "user_commands",
6970#endif
6971#ifdef FEAT_VIMINFO
6972 "viminfo",
6973#endif
6974#ifdef FEAT_VERTSPLIT
6975 "vertsplit",
6976#endif
6977#ifdef FEAT_VIRTUALEDIT
6978 "virtualedit",
6979#endif
6980#ifdef FEAT_VISUAL
6981 "visual",
6982#endif
6983#ifdef FEAT_VISUALEXTRA
6984 "visualextra",
6985#endif
6986#ifdef FEAT_VREPLACE
6987 "vreplace",
6988#endif
6989#ifdef FEAT_WILDIGN
6990 "wildignore",
6991#endif
6992#ifdef FEAT_WILDMENU
6993 "wildmenu",
6994#endif
6995#ifdef FEAT_WINDOWS
6996 "windows",
6997#endif
6998#ifdef FEAT_WAK
6999 "winaltkeys",
7000#endif
7001#ifdef FEAT_WRITEBACKUP
7002 "writebackup",
7003#endif
7004#ifdef FEAT_XIM
7005 "xim",
7006#endif
7007#ifdef FEAT_XFONTSET
7008 "xfontset",
7009#endif
7010#ifdef USE_XSMP
7011 "xsmp",
7012#endif
7013#ifdef USE_XSMP_INTERACT
7014 "xsmp_interact",
7015#endif
7016#ifdef FEAT_XCLIPBOARD
7017 "xterm_clipboard",
7018#endif
7019#ifdef FEAT_XTERM_SAVE
7020 "xterm_save",
7021#endif
7022#if defined(UNIX) && defined(FEAT_X11)
7023 "X11",
7024#endif
7025 NULL
7026 };
7027
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007028 name = get_tv_string(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007029 for (i = 0; has_list[i] != NULL; ++i)
7030 if (STRICMP(name, has_list[i]) == 0)
7031 {
7032 n = TRUE;
7033 break;
7034 }
7035
7036 if (n == FALSE)
7037 {
7038 if (STRNICMP(name, "patch", 5) == 0)
7039 n = has_patch(atoi((char *)name + 5));
7040 else if (STRICMP(name, "vim_starting") == 0)
7041 n = (starting != 0);
7042#ifdef DYNAMIC_TCL
7043 else if (STRICMP(name, "tcl") == 0)
7044 n = tcl_enabled(FALSE);
7045#endif
7046#if defined(USE_ICONV) && defined(DYNAMIC_ICONV)
7047 else if (STRICMP(name, "iconv") == 0)
7048 n = iconv_enabled(FALSE);
7049#endif
7050#ifdef DYNAMIC_RUBY
7051 else if (STRICMP(name, "ruby") == 0)
7052 n = ruby_enabled(FALSE);
7053#endif
7054#ifdef DYNAMIC_PYTHON
7055 else if (STRICMP(name, "python") == 0)
7056 n = python_enabled(FALSE);
7057#endif
7058#ifdef DYNAMIC_PERL
7059 else if (STRICMP(name, "perl") == 0)
7060 n = perl_enabled(FALSE);
7061#endif
7062#ifdef FEAT_GUI
7063 else if (STRICMP(name, "gui_running") == 0)
7064 n = (gui.in_use || gui.starting);
7065# ifdef FEAT_GUI_W32
7066 else if (STRICMP(name, "gui_win32s") == 0)
7067 n = gui_is_win32s();
7068# endif
7069# ifdef FEAT_BROWSE
7070 else if (STRICMP(name, "browse") == 0)
7071 n = gui.in_use; /* gui_mch_browse() works when GUI is running */
7072# endif
7073#endif
7074#ifdef FEAT_SYN_HL
7075 else if (STRICMP(name, "syntax_items") == 0)
7076 n = syntax_present(curbuf);
7077#endif
7078#if defined(WIN3264)
7079 else if (STRICMP(name, "win95") == 0)
7080 n = mch_windows95();
7081#endif
Bram Moolenaar35a9aaa2004-10-24 19:23:07 +00007082#ifdef FEAT_NETBEANS_INTG
7083 else if (STRICMP(name, "netbeans_enabled") == 0)
7084 n = usingNetbeans;
7085#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00007086 }
7087
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007088 rettv->vval.v_number = n;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007089}
7090
7091/*
7092 * "hasmapto()" function
7093 */
7094 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007095f_hasmapto(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007096 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007097 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007098{
7099 char_u *name;
7100 char_u *mode;
7101 char_u buf[NUMBUFLEN];
7102
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007103 name = get_tv_string(&argvars[0]);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007104 if (argvars[1].v_type == VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007105 mode = (char_u *)"nvo";
7106 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007107 mode = get_tv_string_buf(&argvars[1], buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007108
7109 if (map_to_exists(name, mode))
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007110 rettv->vval.v_number = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007111 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007112 rettv->vval.v_number = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007113}
7114
7115/*
7116 * "histadd()" function
7117 */
7118/*ARGSUSED*/
7119 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007120f_histadd(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007121 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007122 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007123{
7124#ifdef FEAT_CMDHIST
7125 int histype;
7126 char_u *str;
7127 char_u buf[NUMBUFLEN];
7128#endif
7129
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007130 rettv->vval.v_number = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007131 if (check_restricted() || check_secure())
7132 return;
7133#ifdef FEAT_CMDHIST
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007134 histype = get_histtype(get_tv_string(&argvars[0]));
Bram Moolenaar071d4272004-06-13 20:20:40 +00007135 if (histype >= 0)
7136 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007137 str = get_tv_string_buf(&argvars[1], buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007138 if (*str != NUL)
7139 {
7140 add_to_history(histype, str, FALSE, NUL);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007141 rettv->vval.v_number = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007142 return;
7143 }
7144 }
7145#endif
7146}
7147
7148/*
7149 * "histdel()" function
7150 */
7151/*ARGSUSED*/
7152 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007153f_histdel(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007154 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007155 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007156{
7157#ifdef FEAT_CMDHIST
7158 int n;
7159 char_u buf[NUMBUFLEN];
7160
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007161 if (argvars[1].v_type == VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007162 /* only one argument: clear entire history */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007163 n = clr_history(get_histtype(get_tv_string(&argvars[0])));
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007164 else if (argvars[1].v_type == VAR_NUMBER)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007165 /* index given: remove that entry */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007166 n = del_history_idx(get_histtype(get_tv_string(&argvars[0])),
7167 (int)get_tv_number(&argvars[1]));
Bram Moolenaar071d4272004-06-13 20:20:40 +00007168 else
7169 /* string given: remove all matching entries */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007170 n = del_history_entry(get_histtype(get_tv_string(&argvars[0])),
7171 get_tv_string_buf(&argvars[1], buf));
7172 rettv->vval.v_number = n;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007173#else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007174 rettv->vval.v_number = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007175#endif
7176}
7177
7178/*
7179 * "histget()" function
7180 */
7181/*ARGSUSED*/
7182 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007183f_histget(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007184 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007185 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007186{
7187#ifdef FEAT_CMDHIST
7188 int type;
7189 int idx;
7190
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007191 type = get_histtype(get_tv_string(&argvars[0]));
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007192 if (argvars[1].v_type == VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007193 idx = get_history_idx(type);
7194 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007195 idx = (int)get_tv_number(&argvars[1]);
7196 rettv->vval.v_string = vim_strsave(get_history_entry(type, idx));
Bram Moolenaar071d4272004-06-13 20:20:40 +00007197#else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007198 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007199#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007200 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007201}
7202
7203/*
7204 * "histnr()" function
7205 */
7206/*ARGSUSED*/
7207 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007208f_histnr(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007209 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007210 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007211{
7212 int i;
7213
7214#ifdef FEAT_CMDHIST
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007215 i = get_histtype(get_tv_string(&argvars[0]));
Bram Moolenaar071d4272004-06-13 20:20:40 +00007216 if (i >= HIST_CMD && i < HIST_COUNT)
7217 i = get_history_idx(i);
7218 else
7219#endif
7220 i = -1;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007221 rettv->vval.v_number = i;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007222}
7223
7224/*
7225 * "highlight_exists()" function
7226 */
7227 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007228f_hlexists(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007229 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007230 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007231{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007232 rettv->vval.v_number = highlight_exists(get_tv_string(&argvars[0]));
Bram Moolenaar071d4272004-06-13 20:20:40 +00007233}
7234
7235/*
7236 * "highlightID(name)" function
7237 */
7238 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007239f_hlID(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007240 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007241 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007242{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007243 rettv->vval.v_number = syn_name2id(get_tv_string(&argvars[0]));
Bram Moolenaar071d4272004-06-13 20:20:40 +00007244}
7245
7246/*
7247 * "hostname()" function
7248 */
7249/*ARGSUSED*/
7250 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007251f_hostname(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007252 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007253 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007254{
7255 char_u hostname[256];
7256
7257 mch_get_host_name(hostname, 256);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007258 rettv->v_type = VAR_STRING;
7259 rettv->vval.v_string = vim_strsave(hostname);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007260}
7261
7262/*
7263 * iconv() function
7264 */
7265/*ARGSUSED*/
7266 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007267f_iconv(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007268 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007269 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007270{
7271#ifdef FEAT_MBYTE
7272 char_u buf1[NUMBUFLEN];
7273 char_u buf2[NUMBUFLEN];
7274 char_u *from, *to, *str;
7275 vimconv_T vimconv;
7276#endif
7277
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007278 rettv->v_type = VAR_STRING;
7279 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007280
7281#ifdef FEAT_MBYTE
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007282 str = get_tv_string(&argvars[0]);
7283 from = enc_canonize(enc_skip(get_tv_string_buf(&argvars[1], buf1)));
7284 to = enc_canonize(enc_skip(get_tv_string_buf(&argvars[2], buf2)));
Bram Moolenaar071d4272004-06-13 20:20:40 +00007285 vimconv.vc_type = CONV_NONE;
7286 convert_setup(&vimconv, from, to);
7287
7288 /* If the encodings are equal, no conversion needed. */
7289 if (vimconv.vc_type == CONV_NONE)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007290 rettv->vval.v_string = vim_strsave(str);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007291 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007292 rettv->vval.v_string = string_convert(&vimconv, str, NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007293
7294 convert_setup(&vimconv, NULL, NULL);
7295 vim_free(from);
7296 vim_free(to);
7297#endif
7298}
7299
7300/*
7301 * "indent()" function
7302 */
7303 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007304f_indent(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007305 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007306 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007307{
7308 linenr_T lnum;
7309
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007310 lnum = get_tv_lnum(argvars);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007311 if (lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007312 rettv->vval.v_number = get_indent_lnum(lnum);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007313 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007314 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007315}
7316
Bram Moolenaar8a283e52005-01-06 23:28:25 +00007317/*
7318 * "index()" function
7319 */
7320 static void
7321f_index(argvars, rettv)
7322 typeval *argvars;
7323 typeval *rettv;
7324{
7325 listvar *l;
7326 listitem *item;
7327 long idx = 0;
7328 int ic = FALSE;
7329
7330 rettv->vval.v_number = -1;
7331 if (argvars[0].v_type != VAR_LIST)
7332 {
7333 EMSG(_(e_listreq));
7334 return;
7335 }
7336 l = argvars[0].vval.v_list;
7337 if (l != NULL)
7338 {
7339 if (argvars[2].v_type != VAR_UNKNOWN)
7340 ic = get_tv_number(&argvars[2]);
7341
7342 for (item = l->lv_first; item != NULL; item = item->li_next, ++idx)
7343 if (tv_equal(&item->li_tv, &argvars[1], ic))
7344 {
7345 rettv->vval.v_number = idx;
7346 break;
7347 }
7348 }
7349}
7350
Bram Moolenaar071d4272004-06-13 20:20:40 +00007351static int inputsecret_flag = 0;
7352
7353/*
7354 * "input()" function
7355 * Also handles inputsecret() when inputsecret is set.
7356 */
7357 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007358f_input(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007359 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007360 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007361{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007362 char_u *prompt = get_tv_string(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007363 char_u *p = NULL;
7364 int c;
7365 char_u buf[NUMBUFLEN];
7366 int cmd_silent_save = cmd_silent;
7367
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007368 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007369
7370#ifdef NO_CONSOLE_INPUT
7371 /* While starting up, there is no place to enter text. */
7372 if (no_console_input())
7373 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007374 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007375 return;
7376 }
7377#endif
7378
7379 cmd_silent = FALSE; /* Want to see the prompt. */
7380 if (prompt != NULL)
7381 {
7382 /* Only the part of the message after the last NL is considered as
7383 * prompt for the command line */
7384 p = vim_strrchr(prompt, '\n');
7385 if (p == NULL)
7386 p = prompt;
7387 else
7388 {
7389 ++p;
7390 c = *p;
7391 *p = NUL;
7392 msg_start();
7393 msg_clr_eos();
7394 msg_puts_attr(prompt, echo_attr);
7395 msg_didout = FALSE;
7396 msg_starthere();
7397 *p = c;
7398 }
7399 cmdline_row = msg_row;
7400 }
7401
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007402 if (argvars[1].v_type != VAR_UNKNOWN)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007403 stuffReadbuffSpec(get_tv_string_buf(&argvars[1], buf));
Bram Moolenaar071d4272004-06-13 20:20:40 +00007404
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007405 rettv->vval.v_string =
Bram Moolenaar071d4272004-06-13 20:20:40 +00007406 getcmdline_prompt(inputsecret_flag ? NUL : '@', p, echo_attr);
7407
7408 /* since the user typed this, no need to wait for return */
7409 need_wait_return = FALSE;
7410 msg_didout = FALSE;
7411 cmd_silent = cmd_silent_save;
7412}
7413
7414/*
7415 * "inputdialog()" function
7416 */
7417 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007418f_inputdialog(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007419 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007420 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007421{
7422#if defined(FEAT_GUI_TEXTDIALOG)
7423 /* Use a GUI dialog if the GUI is running and 'c' is not in 'guioptions' */
7424 if (gui.in_use && vim_strchr(p_go, GO_CONDIALOG) == NULL)
7425 {
7426 char_u *message;
7427 char_u buf[NUMBUFLEN];
7428
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007429 message = get_tv_string(&argvars[0]);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007430 if (argvars[1].v_type != VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007431 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007432 STRNCPY(IObuff, get_tv_string_buf(&argvars[1], buf), IOSIZE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007433 IObuff[IOSIZE - 1] = NUL;
7434 }
7435 else
7436 IObuff[0] = NUL;
7437 if (do_dialog(VIM_QUESTION, NULL, message, (char_u *)_("&OK\n&Cancel"),
7438 1, IObuff) == 1)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007439 rettv->vval.v_string = vim_strsave(IObuff);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007440 else
7441 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007442 if (argvars[1].v_type != VAR_UNKNOWN
7443 && argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007444 rettv->vval.v_string = vim_strsave(
7445 get_tv_string_buf(&argvars[2], buf));
Bram Moolenaar071d4272004-06-13 20:20:40 +00007446 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007447 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007448 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007449 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007450 }
7451 else
7452#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007453 f_input(argvars, rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007454}
7455
7456static garray_T ga_userinput = {0, 0, sizeof(tasave_T), 4, NULL};
7457
7458/*
7459 * "inputrestore()" function
7460 */
7461/*ARGSUSED*/
7462 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007463f_inputrestore(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007464 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007465 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007466{
7467 if (ga_userinput.ga_len > 0)
7468 {
7469 --ga_userinput.ga_len;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007470 restore_typeahead((tasave_T *)(ga_userinput.ga_data)
7471 + ga_userinput.ga_len);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007472 rettv->vval.v_number = 0; /* OK */
Bram Moolenaar071d4272004-06-13 20:20:40 +00007473 }
7474 else if (p_verbose > 1)
7475 {
7476 msg((char_u *)_("called inputrestore() more often than inputsave()"));
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007477 rettv->vval.v_number = 1; /* Failed */
Bram Moolenaar071d4272004-06-13 20:20:40 +00007478 }
7479}
7480
7481/*
7482 * "inputsave()" function
7483 */
7484/*ARGSUSED*/
7485 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007486f_inputsave(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007487 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007488 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007489{
7490 /* Add an entry to the stack of typehead storage. */
7491 if (ga_grow(&ga_userinput, 1) == OK)
7492 {
7493 save_typeahead((tasave_T *)(ga_userinput.ga_data)
7494 + ga_userinput.ga_len);
7495 ++ga_userinput.ga_len;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007496 rettv->vval.v_number = 0; /* OK */
Bram Moolenaar071d4272004-06-13 20:20:40 +00007497 }
7498 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007499 rettv->vval.v_number = 1; /* Failed */
Bram Moolenaar071d4272004-06-13 20:20:40 +00007500}
7501
7502/*
7503 * "inputsecret()" function
7504 */
7505 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007506f_inputsecret(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007507 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007508 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007509{
7510 ++cmdline_star;
7511 ++inputsecret_flag;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007512 f_input(argvars, rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007513 --cmdline_star;
7514 --inputsecret_flag;
7515}
7516
7517/*
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007518 * "insert()" function
7519 */
7520 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007521f_insert(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007522 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007523 typeval *rettv;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007524{
7525 long before = 0;
7526 long n;
7527 listitem *item;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007528 listvar *l;
7529
7530 if (argvars[0].v_type != VAR_LIST)
7531 EMSG(_("E999: First argument of insert() must be a list"));
7532 else if ((l = argvars[0].vval.v_list) != NULL)
7533 {
7534 if (argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007535 before = get_tv_number(&argvars[2]);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007536
Bram Moolenaar8a283e52005-01-06 23:28:25 +00007537 n = before;
7538 item = list_find_ext(l, &n);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007539 if (n > 0)
7540 EMSGN(_(e_listidx), before);
7541 else
7542 {
Bram Moolenaar8a283e52005-01-06 23:28:25 +00007543 list_insert_tv(l, &argvars[1], item);
7544 ++l->lv_refcount;
7545 copy_tv(&argvars[0], rettv);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007546 }
7547 }
7548}
7549
7550/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00007551 * "isdirectory()" function
7552 */
7553 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007554f_isdirectory(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007555 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007556 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007557{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007558 rettv->vval.v_number = mch_isdir(get_tv_string(&argvars[0]));
Bram Moolenaar071d4272004-06-13 20:20:40 +00007559}
7560
7561/*
7562 * "last_buffer_nr()" function.
7563 */
7564/*ARGSUSED*/
7565 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007566f_last_buffer_nr(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007567 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007568 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007569{
7570 int n = 0;
7571 buf_T *buf;
7572
7573 for (buf = firstbuf; buf != NULL; buf = buf->b_next)
7574 if (n < buf->b_fnum)
7575 n = buf->b_fnum;
7576
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007577 rettv->vval.v_number = n;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007578}
7579
7580/*
7581 * "len()" function
7582 */
7583 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007584f_len(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007585 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007586 typeval *rettv;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007587{
7588 switch (argvars[0].v_type)
7589 {
7590 case VAR_STRING:
7591 case VAR_NUMBER:
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007592 rettv->vval.v_number = (varnumber_T)STRLEN(
7593 get_tv_string(&argvars[0]));
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007594 break;
7595 case VAR_LIST:
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007596 rettv->vval.v_number = list_len(argvars[0].vval.v_list);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007597 break;
7598 default:
7599 EMSG(_("E999: Invalid type for len()"));
7600 break;
7601 }
7602}
7603
7604/*
7605 * "libcall()" function
7606 */
7607 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007608f_libcall(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007609 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007610 typeval *rettv;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007611{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007612 libcall_common(argvars, rettv, VAR_STRING);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007613}
7614
7615/*
7616 * "libcallnr()" function
7617 */
7618 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007619f_libcallnr(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007620 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007621 typeval *rettv;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007622{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007623 libcall_common(argvars, rettv, VAR_NUMBER);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007624}
7625
7626 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007627libcall_common(argvars, rettv, type)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007628 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007629 typeval *rettv;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007630 int type;
7631{
7632#ifdef FEAT_LIBCALL
7633 char_u *string_in;
7634 char_u **string_result;
7635 int nr_result;
7636#endif
7637
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007638 rettv->v_type = type;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007639 if (type == VAR_NUMBER)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007640 rettv->vval.v_number = 0;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007641 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007642 rettv->vval.v_string = NULL;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007643
7644 if (check_restricted() || check_secure())
7645 return;
7646
7647#ifdef FEAT_LIBCALL
7648 /* The first two args must be strings, otherwise its meaningless */
7649 if (argvars[0].v_type == VAR_STRING && argvars[1].v_type == VAR_STRING)
7650 {
7651 if (argvars[2].v_type == VAR_NUMBER)
7652 string_in = NULL;
7653 else
7654 string_in = argvars[2].vval.v_string;
7655 if (type == VAR_NUMBER)
7656 string_result = NULL;
7657 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007658 string_result = &rettv->vval.v_string;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007659 if (mch_libcall(argvars[0].vval.v_string,
7660 argvars[1].vval.v_string,
7661 string_in,
7662 argvars[2].vval.v_number,
7663 string_result,
7664 &nr_result) == OK
7665 && type == VAR_NUMBER)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007666 rettv->vval.v_number = nr_result;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007667 }
7668#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00007669}
7670
7671/*
7672 * "line(string)" function
7673 */
7674 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007675f_line(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007676 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007677 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007678{
7679 linenr_T lnum = 0;
7680 pos_T *fp;
7681
7682 fp = var2fpos(&argvars[0], TRUE);
7683 if (fp != NULL)
7684 lnum = fp->lnum;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007685 rettv->vval.v_number = lnum;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007686}
7687
7688/*
7689 * "line2byte(lnum)" function
7690 */
7691/*ARGSUSED*/
7692 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007693f_line2byte(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007694 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007695 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007696{
7697#ifndef FEAT_BYTEOFF
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007698 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007699#else
7700 linenr_T lnum;
7701
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007702 lnum = get_tv_lnum(argvars);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007703 if (lnum < 1 || lnum > curbuf->b_ml.ml_line_count + 1)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007704 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007705 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007706 rettv->vval.v_number = ml_find_line_or_offset(curbuf, lnum, NULL);
7707 if (rettv->vval.v_number >= 0)
7708 ++rettv->vval.v_number;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007709#endif
7710}
7711
7712/*
7713 * "lispindent(lnum)" function
7714 */
7715 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007716f_lispindent(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007717 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007718 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007719{
7720#ifdef FEAT_LISP
7721 pos_T pos;
7722 linenr_T lnum;
7723
7724 pos = curwin->w_cursor;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007725 lnum = get_tv_lnum(argvars);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007726 if (lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count)
7727 {
7728 curwin->w_cursor.lnum = lnum;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007729 rettv->vval.v_number = get_lisp_indent();
Bram Moolenaar071d4272004-06-13 20:20:40 +00007730 curwin->w_cursor = pos;
7731 }
7732 else
7733#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007734 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007735}
7736
7737/*
7738 * "localtime()" function
7739 */
7740/*ARGSUSED*/
7741 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007742f_localtime(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007743 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007744 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007745{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007746 rettv->vval.v_number = (varnumber_T)time(NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007747}
7748
7749/*
7750 * "maparg()" function
7751 */
7752 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007753f_maparg(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007754 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007755 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007756{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007757 get_maparg(argvars, rettv, TRUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007758}
7759
7760/*
7761 * "mapcheck()" function
7762 */
7763 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007764f_mapcheck(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007765 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007766 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007767{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007768 get_maparg(argvars, rettv, FALSE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007769}
7770
7771 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007772get_maparg(argvars, rettv, exact)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007773 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007774 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007775 int exact;
7776{
7777 char_u *keys;
7778 char_u *which;
7779 char_u buf[NUMBUFLEN];
7780 char_u *keys_buf = NULL;
7781 char_u *rhs;
7782 int mode;
7783 garray_T ga;
7784
7785 /* return empty string for failure */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007786 rettv->v_type = VAR_STRING;
7787 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007788
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007789 keys = get_tv_string(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007790 if (*keys == NUL)
7791 return;
7792
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007793 if (argvars[1].v_type != VAR_UNKNOWN)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007794 which = get_tv_string_buf(&argvars[1], buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007795 else
7796 which = (char_u *)"";
7797 mode = get_map_mode(&which, 0);
7798
7799 keys = replace_termcodes(keys, &keys_buf, TRUE, TRUE);
7800 rhs = check_map(keys, mode, exact);
7801 vim_free(keys_buf);
7802 if (rhs != NULL)
7803 {
7804 ga_init(&ga);
7805 ga.ga_itemsize = 1;
7806 ga.ga_growsize = 40;
7807
7808 while (*rhs != NUL)
7809 ga_concat(&ga, str2special(&rhs, FALSE));
7810
7811 ga_append(&ga, NUL);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007812 rettv->vval.v_string = (char_u *)ga.ga_data;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007813 }
7814}
7815
7816/*
7817 * "match()" function
7818 */
7819 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007820f_match(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007821 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007822 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007823{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007824 find_some_match(argvars, rettv, 1);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007825}
7826
7827/*
7828 * "matchend()" function
7829 */
7830 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007831f_matchend(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007832 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007833 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007834{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007835 find_some_match(argvars, rettv, 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007836}
7837
7838/*
7839 * "matchstr()" function
7840 */
7841 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007842f_matchstr(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007843 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007844 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007845{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007846 find_some_match(argvars, rettv, 2);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007847}
7848
7849 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007850find_some_match(argvars, rettv, type)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007851 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007852 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007853 int type;
7854{
7855 char_u *str;
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00007856 char_u *expr;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007857 char_u *pat;
7858 regmatch_T regmatch;
7859 char_u patbuf[NUMBUFLEN];
7860 char_u *save_cpo;
7861 long start = 0;
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00007862 long nth = 1;
7863 int match;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007864
7865 /* Make 'cpoptions' empty, the 'l' flag should not be used here. */
7866 save_cpo = p_cpo;
7867 p_cpo = (char_u *)"";
7868
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007869 expr = str = get_tv_string(&argvars[0]);
7870 pat = get_tv_string_buf(&argvars[1], patbuf);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007871
7872 if (type == 2)
7873 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007874 rettv->v_type = VAR_STRING;
7875 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007876 }
7877 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007878 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007879
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007880 if (argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007881 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007882 start = get_tv_number(&argvars[2]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007883 if (start < 0)
7884 start = 0;
7885 if (start > (long)STRLEN(str))
7886 goto theend;
7887 str += start;
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00007888
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007889 if (argvars[3].v_type != VAR_UNKNOWN)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007890 nth = get_tv_number(&argvars[3]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007891 }
7892
7893 regmatch.regprog = vim_regcomp(pat, RE_MAGIC + RE_STRING);
7894 if (regmatch.regprog != NULL)
7895 {
7896 regmatch.rm_ic = p_ic;
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00007897
7898 while (1)
7899 {
7900 match = vim_regexec_nl(&regmatch, str, (colnr_T)0);
7901 if (!match || --nth <= 0)
7902 break;
7903 /* Advance to just after the match. */
7904#ifdef FEAT_MBYTE
7905 str = regmatch.startp[0] + mb_ptr2len_check(regmatch.startp[0]);
7906#else
7907 str = regmatch.startp[0] + 1;
7908#endif
7909 }
7910
7911 if (match)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007912 {
7913 if (type == 2)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007914 rettv->vval.v_string = vim_strnsave(regmatch.startp[0],
Bram Moolenaar071d4272004-06-13 20:20:40 +00007915 (int)(regmatch.endp[0] - regmatch.startp[0]));
7916 else
7917 {
7918 if (type != 0)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007919 rettv->vval.v_number =
Bram Moolenaar071d4272004-06-13 20:20:40 +00007920 (varnumber_T)(regmatch.startp[0] - str);
7921 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007922 rettv->vval.v_number =
Bram Moolenaar071d4272004-06-13 20:20:40 +00007923 (varnumber_T)(regmatch.endp[0] - str);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007924 rettv->vval.v_number += str - expr;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007925 }
7926 }
7927 vim_free(regmatch.regprog);
7928 }
7929
7930theend:
7931 p_cpo = save_cpo;
7932}
7933
7934/*
7935 * "mode()" function
7936 */
7937/*ARGSUSED*/
7938 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007939f_mode(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007940 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007941 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007942{
7943 char_u buf[2];
7944
7945#ifdef FEAT_VISUAL
7946 if (VIsual_active)
7947 {
7948 if (VIsual_select)
7949 buf[0] = VIsual_mode + 's' - 'v';
7950 else
7951 buf[0] = VIsual_mode;
7952 }
7953 else
7954#endif
7955 if (State == HITRETURN || State == ASKMORE || State == SETWSIZE)
7956 buf[0] = 'r';
7957 else if (State & INSERT)
7958 {
7959 if (State & REPLACE_FLAG)
7960 buf[0] = 'R';
7961 else
7962 buf[0] = 'i';
7963 }
7964 else if (State & CMDLINE)
7965 buf[0] = 'c';
7966 else
7967 buf[0] = 'n';
7968
7969 buf[1] = NUL;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007970 rettv->vval.v_string = vim_strsave(buf);
7971 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007972}
7973
7974/*
7975 * "nr2char()" function
7976 */
7977 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007978f_nr2char(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007979 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007980 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007981{
7982 char_u buf[NUMBUFLEN];
7983
7984#ifdef FEAT_MBYTE
7985 if (has_mbyte)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007986 buf[(*mb_char2bytes)((int)get_tv_number(&argvars[0]), buf)] = NUL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007987 else
7988#endif
7989 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007990 buf[0] = (char_u)get_tv_number(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007991 buf[1] = NUL;
7992 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007993 rettv->v_type = VAR_STRING;
7994 rettv->vval.v_string = vim_strsave(buf);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007995}
7996
7997/*
Bram Moolenaar8a283e52005-01-06 23:28:25 +00007998 * "remove({list}, {idx} [, {end}])" function
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007999 */
8000 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008001f_remove(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008002 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008003 typeval *rettv;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008004{
8005 listvar *l;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00008006 listitem *item, *item2;
8007 listitem *li;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008008 long idx;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00008009 long end;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008010
Bram Moolenaar8a283e52005-01-06 23:28:25 +00008011 rettv->vval.v_number = 0;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008012 if (argvars[0].v_type != VAR_LIST)
8013 EMSG(_("E999: First argument of remove() must be a list"));
8014 else if ((l = argvars[0].vval.v_list) != NULL)
8015 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008016 idx = get_tv_number(&argvars[1]);
Bram Moolenaar8a283e52005-01-06 23:28:25 +00008017 item = list_find(l, idx);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008018 if (item == NULL)
8019 EMSGN(_(e_listidx), idx);
8020 else
8021 {
Bram Moolenaar8a283e52005-01-06 23:28:25 +00008022 if (argvars[2].v_type == VAR_UNKNOWN)
8023 {
8024 /* Remove one item, return its value. */
8025 list_getrem(l, item, item);
8026 *rettv = item->li_tv;
8027 vim_free(item);
8028 }
8029 else
8030 {
8031 /* Remove range of items, return list with values. */
8032 end = get_tv_number(&argvars[2]);
8033 item2 = list_find(l, end);
8034 if (item2 == NULL)
8035 EMSGN(_(e_listidx), end);
8036 else
8037 {
8038 for (li = item; li != item2 && li != NULL; li = li->li_next)
8039 ;
8040 if (li == NULL) /* didn't find "item2" after "item" */
8041 EMSG(_(e_invrange));
8042 else
8043 {
8044 list_getrem(l, item, item2);
8045 l = list_alloc();
8046 if (l != NULL)
8047 {
8048 rettv->v_type = VAR_LIST;
8049 rettv->vval.v_list = l;
8050 l->lv_first = item;
8051 l->lv_last = item2;
8052 l->lv_refcount = 1;
8053 item->li_prev = NULL;
8054 item2->li_next = NULL;
8055 }
8056 }
8057 }
8058 }
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008059 }
8060 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00008061}
8062
8063/*
8064 * "rename({from}, {to})" function
8065 */
8066 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008067f_rename(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008068 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008069 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008070{
8071 char_u buf[NUMBUFLEN];
8072
8073 if (check_restricted() || check_secure())
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008074 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008075 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008076 rettv->vval.v_number = vim_rename(get_tv_string(&argvars[0]),
8077 get_tv_string_buf(&argvars[1], buf));
Bram Moolenaar071d4272004-06-13 20:20:40 +00008078}
8079
8080/*
Bram Moolenaar8a283e52005-01-06 23:28:25 +00008081 * "repeat()" function
8082 */
8083/*ARGSUSED*/
8084 static void
8085f_repeat(argvars, rettv)
8086 typeval *argvars;
8087 typeval *rettv;
8088{
8089 char_u *p;
8090 int n;
8091 int slen;
8092 int len;
8093 char_u *r;
8094 int i;
8095 listvar *l;
8096
8097 n = get_tv_number(&argvars[1]);
8098 if (argvars[0].v_type == VAR_LIST)
8099 {
8100 l = list_alloc();
8101 if (l != NULL && argvars[0].vval.v_list != NULL)
8102 {
8103 l->lv_refcount = 1;
8104 while (n-- > 0)
8105 if (list_extend(l, argvars[0].vval.v_list, NULL) == FAIL)
8106 break;
8107 }
8108 rettv->v_type = VAR_LIST;
8109 rettv->vval.v_list = l;
8110 }
8111 else
8112 {
8113 p = get_tv_string(&argvars[0]);
8114 rettv->v_type = VAR_STRING;
8115 rettv->vval.v_string = NULL;
8116
8117 slen = (int)STRLEN(p);
8118 len = slen * n;
8119 if (len <= 0)
8120 return;
8121
8122 r = alloc(len + 1);
8123 if (r != NULL)
8124 {
8125 for (i = 0; i < n; i++)
8126 mch_memmove(r + i * slen, p, (size_t)slen);
8127 r[len] = NUL;
8128 }
8129
8130 rettv->vval.v_string = r;
8131 }
8132}
8133
8134/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00008135 * "resolve()" function
8136 */
8137 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008138f_resolve(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008139 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008140 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008141{
8142 char_u *p;
8143
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008144 p = get_tv_string(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008145#ifdef FEAT_SHORTCUT
8146 {
8147 char_u *v = NULL;
8148
8149 v = mch_resolve_shortcut(p);
8150 if (v != NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008151 rettv->vval.v_string = v;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008152 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008153 rettv->vval.v_string = vim_strsave(p);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008154 }
8155#else
8156# ifdef HAVE_READLINK
8157 {
8158 char_u buf[MAXPATHL + 1];
8159 char_u *cpy;
8160 int len;
8161 char_u *remain = NULL;
8162 char_u *q;
8163 int is_relative_to_current = FALSE;
8164 int has_trailing_pathsep = FALSE;
8165 int limit = 100;
8166
8167 p = vim_strsave(p);
8168
8169 if (p[0] == '.' && (vim_ispathsep(p[1])
8170 || (p[1] == '.' && (vim_ispathsep(p[2])))))
8171 is_relative_to_current = TRUE;
8172
8173 len = STRLEN(p);
Bram Moolenaar1cd871b2004-12-19 22:46:22 +00008174 if (len > 0 && after_pathsep(p, p + len))
Bram Moolenaar071d4272004-06-13 20:20:40 +00008175 has_trailing_pathsep = TRUE;
8176
8177 q = getnextcomp(p);
8178 if (*q != NUL)
8179 {
8180 /* Separate the first path component in "p", and keep the
8181 * remainder (beginning with the path separator). */
8182 remain = vim_strsave(q - 1);
8183 q[-1] = NUL;
8184 }
8185
8186 for (;;)
8187 {
8188 for (;;)
8189 {
8190 len = readlink((char *)p, (char *)buf, MAXPATHL);
8191 if (len <= 0)
8192 break;
8193 buf[len] = NUL;
8194
8195 if (limit-- == 0)
8196 {
8197 vim_free(p);
8198 vim_free(remain);
8199 EMSG(_("E655: Too many symbolic links (cycle?)"));
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008200 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008201 goto fail;
8202 }
8203
8204 /* Ensure that the result will have a trailing path separator
8205 * if the argument has one. */
8206 if (remain == NULL && has_trailing_pathsep)
8207 add_pathsep(buf);
8208
8209 /* Separate the first path component in the link value and
8210 * concatenate the remainders. */
8211 q = getnextcomp(vim_ispathsep(*buf) ? buf + 1 : buf);
8212 if (*q != NUL)
8213 {
8214 if (remain == NULL)
8215 remain = vim_strsave(q - 1);
8216 else
8217 {
8218 cpy = vim_strnsave(q-1, STRLEN(q-1)+STRLEN(remain));
8219 if (cpy != NULL)
8220 {
8221 STRCAT(cpy, remain);
8222 vim_free(remain);
8223 remain = cpy;
8224 }
8225 }
8226 q[-1] = NUL;
8227 }
8228
8229 q = gettail(p);
8230 if (q > p && *q == NUL)
8231 {
8232 /* Ignore trailing path separator. */
8233 q[-1] = NUL;
8234 q = gettail(p);
8235 }
8236 if (q > p && !mch_isFullName(buf))
8237 {
8238 /* symlink is relative to directory of argument */
8239 cpy = alloc((unsigned)(STRLEN(p) + STRLEN(buf) + 1));
8240 if (cpy != NULL)
8241 {
8242 STRCPY(cpy, p);
8243 STRCPY(gettail(cpy), buf);
8244 vim_free(p);
8245 p = cpy;
8246 }
8247 }
8248 else
8249 {
8250 vim_free(p);
8251 p = vim_strsave(buf);
8252 }
8253 }
8254
8255 if (remain == NULL)
8256 break;
8257
8258 /* Append the first path component of "remain" to "p". */
8259 q = getnextcomp(remain + 1);
8260 len = q - remain - (*q != NUL);
8261 cpy = vim_strnsave(p, STRLEN(p) + len);
8262 if (cpy != NULL)
8263 {
8264 STRNCAT(cpy, remain, len);
8265 vim_free(p);
8266 p = cpy;
8267 }
8268 /* Shorten "remain". */
8269 if (*q != NUL)
8270 STRCPY(remain, q - 1);
8271 else
8272 {
8273 vim_free(remain);
8274 remain = NULL;
8275 }
8276 }
8277
8278 /* If the result is a relative path name, make it explicitly relative to
8279 * the current directory if and only if the argument had this form. */
8280 if (!vim_ispathsep(*p))
8281 {
8282 if (is_relative_to_current
8283 && *p != NUL
8284 && !(p[0] == '.'
8285 && (p[1] == NUL
8286 || vim_ispathsep(p[1])
8287 || (p[1] == '.'
8288 && (p[2] == NUL
8289 || vim_ispathsep(p[2]))))))
8290 {
8291 /* Prepend "./". */
8292 cpy = vim_strnsave((char_u *)"./", 2 + STRLEN(p));
8293 if (cpy != NULL)
8294 {
8295 STRCAT(cpy, p);
8296 vim_free(p);
8297 p = cpy;
8298 }
8299 }
8300 else if (!is_relative_to_current)
8301 {
8302 /* Strip leading "./". */
8303 q = p;
8304 while (q[0] == '.' && vim_ispathsep(q[1]))
8305 q += 2;
8306 if (q > p)
8307 mch_memmove(p, p + 2, STRLEN(p + 2) + (size_t)1);
8308 }
8309 }
8310
8311 /* Ensure that the result will have no trailing path separator
8312 * if the argument had none. But keep "/" or "//". */
8313 if (!has_trailing_pathsep)
8314 {
8315 q = p + STRLEN(p);
Bram Moolenaar1cd871b2004-12-19 22:46:22 +00008316 if (after_pathsep(p, q))
8317 *gettail_sep(p) = NUL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008318 }
8319
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008320 rettv->vval.v_string = p;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008321 }
8322# else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008323 rettv->vval.v_string = vim_strsave(p);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008324# endif
8325#endif
8326
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008327 simplify_filename(rettv->vval.v_string);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008328
8329#ifdef HAVE_READLINK
8330fail:
8331#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008332 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008333}
8334
8335/*
8336 * "simplify()" function
8337 */
8338 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008339f_simplify(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008340 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008341 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008342{
8343 char_u *p;
8344
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008345 p = get_tv_string(&argvars[0]);
8346 rettv->vval.v_string = vim_strsave(p);
8347 simplify_filename(rettv->vval.v_string); /* simplify in place */
8348 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008349}
8350
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00008351#define SP_NOMOVE 1 /* don't move cursor */
8352#define SP_REPEAT 2 /* repeat to find outer pair */
8353#define SP_RETCOUNT 4 /* return matchcount */
8354
Bram Moolenaar071d4272004-06-13 20:20:40 +00008355/*
8356 * "search()" function
8357 */
8358 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008359f_search(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008360 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008361 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008362{
8363 char_u *pat;
8364 pos_T pos;
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00008365 pos_T save_cursor;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008366 int save_p_ws = p_ws;
8367 int dir;
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00008368 int flags = 0;
8369
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008370 rettv->vval.v_number = 0; /* default: FAIL */
Bram Moolenaar071d4272004-06-13 20:20:40 +00008371
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008372 pat = get_tv_string(&argvars[0]);
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00008373 dir = get_search_arg(&argvars[1], &flags); /* may set p_ws */
8374 if (dir == 0)
8375 goto theend;
8376 if ((flags & ~SP_NOMOVE) != 0)
8377 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008378 EMSG2(_(e_invarg2), get_tv_string(&argvars[1]));
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00008379 goto theend;
8380 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00008381
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00008382 pos = save_cursor = curwin->w_cursor;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008383 if (searchit(curwin, curbuf, &pos, dir, pat, 1L,
8384 SEARCH_KEEP, RE_SEARCH) != FAIL)
8385 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008386 rettv->vval.v_number = pos.lnum;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008387 curwin->w_cursor = pos;
8388 /* "/$" will put the cursor after the end of the line, may need to
8389 * correct that here */
8390 check_cursor();
8391 }
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00008392
8393 /* If 'n' flag is used: restore cursor position. */
8394 if (flags & SP_NOMOVE)
8395 curwin->w_cursor = save_cursor;
8396theend:
Bram Moolenaar071d4272004-06-13 20:20:40 +00008397 p_ws = save_p_ws;
8398}
8399
Bram Moolenaar071d4272004-06-13 20:20:40 +00008400/*
8401 * "searchpair()" function
8402 */
8403 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008404f_searchpair(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008405 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008406 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008407{
8408 char_u *spat, *mpat, *epat;
8409 char_u *skip;
8410 char_u *pat, *pat2, *pat3;
8411 pos_T pos;
8412 pos_T firstpos;
8413 pos_T save_cursor;
8414 pos_T save_pos;
8415 int save_p_ws = p_ws;
8416 char_u *save_cpo;
8417 int dir;
8418 int flags = 0;
8419 char_u nbuf1[NUMBUFLEN];
8420 char_u nbuf2[NUMBUFLEN];
8421 char_u nbuf3[NUMBUFLEN];
8422 int n;
8423 int r;
8424 int nest = 1;
8425 int err;
8426
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008427 rettv->vval.v_number = 0; /* default: FAIL */
Bram Moolenaar071d4272004-06-13 20:20:40 +00008428
8429 /* Make 'cpoptions' empty, the 'l' flag should not be used here. */
8430 save_cpo = p_cpo;
8431 p_cpo = (char_u *)"";
8432
8433 /* Get the three pattern arguments: start, middle, end. */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008434 spat = get_tv_string(&argvars[0]);
8435 mpat = get_tv_string_buf(&argvars[1], nbuf1);
8436 epat = get_tv_string_buf(&argvars[2], nbuf2);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008437
8438 /* Make two search patterns: start/end (pat2, for in nested pairs) and
8439 * start/middle/end (pat3, for the top pair). */
8440 pat2 = alloc((unsigned)(STRLEN(spat) + STRLEN(epat) + 15));
8441 pat3 = alloc((unsigned)(STRLEN(spat) + STRLEN(mpat) + STRLEN(epat) + 23));
8442 if (pat2 == NULL || pat3 == NULL)
8443 goto theend;
8444 sprintf((char *)pat2, "\\(%s\\m\\)\\|\\(%s\\m\\)", spat, epat);
8445 if (*mpat == NUL)
8446 STRCPY(pat3, pat2);
8447 else
8448 sprintf((char *)pat3, "\\(%s\\m\\)\\|\\(%s\\m\\)\\|\\(%s\\m\\)",
8449 spat, epat, mpat);
8450
8451 /* Handle the optional fourth argument: flags */
8452 dir = get_search_arg(&argvars[3], &flags); /* may set p_ws */
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00008453 if (dir == 0)
8454 goto theend;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008455
8456 /* Optional fifth argument: skip expresion */
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008457 if (argvars[3].v_type == VAR_UNKNOWN
8458 || argvars[4].v_type == VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008459 skip = (char_u *)"";
8460 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008461 skip = get_tv_string_buf(&argvars[4], nbuf3);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008462
8463 save_cursor = curwin->w_cursor;
8464 pos = curwin->w_cursor;
8465 firstpos.lnum = 0;
8466 pat = pat3;
8467 for (;;)
8468 {
8469 n = searchit(curwin, curbuf, &pos, dir, pat, 1L,
8470 SEARCH_KEEP, RE_SEARCH);
8471 if (n == FAIL || (firstpos.lnum != 0 && equalpos(pos, firstpos)))
8472 /* didn't find it or found the first match again: FAIL */
8473 break;
8474
8475 if (firstpos.lnum == 0)
8476 firstpos = pos;
8477
8478 /* If the skip pattern matches, ignore this match. */
8479 if (*skip != NUL)
8480 {
8481 save_pos = curwin->w_cursor;
8482 curwin->w_cursor = pos;
8483 r = eval_to_bool(skip, &err, NULL, FALSE);
8484 curwin->w_cursor = save_pos;
8485 if (err)
8486 {
8487 /* Evaluating {skip} caused an error, break here. */
8488 curwin->w_cursor = save_cursor;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008489 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008490 break;
8491 }
8492 if (r)
8493 continue;
8494 }
8495
8496 if ((dir == BACKWARD && n == 3) || (dir == FORWARD && n == 2))
8497 {
8498 /* Found end when searching backwards or start when searching
8499 * forward: nested pair. */
8500 ++nest;
8501 pat = pat2; /* nested, don't search for middle */
8502 }
8503 else
8504 {
8505 /* Found end when searching forward or start when searching
8506 * backward: end of (nested) pair; or found middle in outer pair. */
8507 if (--nest == 1)
8508 pat = pat3; /* outer level, search for middle */
8509 }
8510
8511 if (nest == 0)
8512 {
8513 /* Found the match: return matchcount or line number. */
8514 if (flags & SP_RETCOUNT)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008515 ++rettv->vval.v_number;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008516 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008517 rettv->vval.v_number = pos.lnum;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008518 curwin->w_cursor = pos;
8519 if (!(flags & SP_REPEAT))
8520 break;
8521 nest = 1; /* search for next unmatched */
8522 }
8523 }
8524
8525 /* If 'n' flag is used or search failed: restore cursor position. */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008526 if ((flags & SP_NOMOVE) || rettv->vval.v_number == 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008527 curwin->w_cursor = save_cursor;
8528
8529theend:
8530 vim_free(pat2);
8531 vim_free(pat3);
8532 p_ws = save_p_ws;
8533 p_cpo = save_cpo;
8534}
8535
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00008536/*
8537 * Get flags for a search function.
8538 * Possibly sets "p_ws".
8539 * Returns BACKWARD, FORWARD or zero (for an error).
8540 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00008541 static int
8542get_search_arg(varp, flagsp)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008543 typeval *varp;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008544 int *flagsp;
8545{
8546 int dir = FORWARD;
8547 char_u *flags;
8548 char_u nbuf[NUMBUFLEN];
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00008549 int mask;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008550
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008551 if (varp->v_type != VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008552 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008553 flags = get_tv_string_buf(varp, nbuf);
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00008554 while (*flags != NUL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008555 {
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00008556 switch (*flags)
8557 {
8558 case 'b': dir = BACKWARD; break;
8559 case 'w': p_ws = TRUE; break;
8560 case 'W': p_ws = FALSE; break;
8561 default: mask = 0;
8562 if (flagsp != NULL)
8563 switch (*flags)
8564 {
8565 case 'n': mask = SP_NOMOVE; break;
8566 case 'r': mask = SP_REPEAT; break;
8567 case 'm': mask = SP_RETCOUNT; break;
8568 }
8569 if (mask == 0)
8570 {
8571 EMSG2(_(e_invarg2), flags);
8572 dir = 0;
8573 }
8574 else
8575 *flagsp |= mask;
8576 }
8577 if (dir == 0)
8578 break;
8579 ++flags;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008580 }
8581 }
8582 return dir;
8583}
8584
8585/*
8586 * "setbufvar()" function
8587 */
8588/*ARGSUSED*/
8589 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008590f_setbufvar(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008591 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008592 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008593{
8594 buf_T *buf;
8595#ifdef FEAT_AUTOCMD
8596 aco_save_T aco;
8597#else
8598 buf_T *save_curbuf;
8599#endif
8600 char_u *varname, *bufvarname;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008601 typeval *varp;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008602 char_u nbuf[NUMBUFLEN];
8603
8604 if (check_restricted() || check_secure())
8605 return;
8606 ++emsg_off;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008607 buf = get_buf_tv(&argvars[0]);
8608 varname = get_tv_string(&argvars[1]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008609 varp = &argvars[2];
8610
8611 if (buf != NULL && varname != NULL && varp != NULL)
8612 {
8613 /* set curbuf to be our buf, temporarily */
8614#ifdef FEAT_AUTOCMD
8615 aucmd_prepbuf(&aco, buf);
8616#else
8617 save_curbuf = curbuf;
8618 curbuf = buf;
8619#endif
8620
8621 if (*varname == '&')
8622 {
8623 ++varname;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008624 set_option_value(varname, get_tv_number(varp),
8625 get_tv_string_buf(varp, nbuf), OPT_LOCAL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008626 }
8627 else
8628 {
8629 bufvarname = alloc((unsigned)STRLEN(varname) + 3);
8630 if (bufvarname != NULL)
8631 {
8632 STRCPY(bufvarname, "b:");
8633 STRCPY(bufvarname + 2, varname);
Bram Moolenaar1c2fda22005-01-02 11:43:19 +00008634 set_var(bufvarname, varp, TRUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008635 vim_free(bufvarname);
8636 }
8637 }
8638
8639 /* reset notion of buffer */
8640#ifdef FEAT_AUTOCMD
8641 aucmd_restbuf(&aco);
8642#else
8643 curbuf = save_curbuf;
8644#endif
8645 }
8646 --emsg_off;
8647}
8648
8649/*
8650 * "setcmdpos()" function
8651 */
8652 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008653f_setcmdpos(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008654 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008655 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008656{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008657 rettv->vval.v_number = set_cmdline_pos(
8658 (int)get_tv_number(&argvars[0]) - 1);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008659}
8660
8661/*
8662 * "setline()" function
8663 */
8664 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008665f_setline(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008666 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008667 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008668{
8669 linenr_T lnum;
8670 char_u *line;
8671
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008672 lnum = get_tv_lnum(argvars);
8673 line = get_tv_string(&argvars[1]);
8674 rettv->vval.v_number = 1; /* FAIL is default */
Bram Moolenaar071d4272004-06-13 20:20:40 +00008675
8676 if (lnum >= 1
8677 && lnum <= curbuf->b_ml.ml_line_count
8678 && u_savesub(lnum) == OK
8679 && ml_replace(lnum, line, TRUE) == OK)
8680 {
8681 changed_bytes(lnum, 0);
8682 check_cursor_col();
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008683 rettv->vval.v_number = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008684 }
8685}
8686
8687/*
8688 * "setreg()" function
8689 */
8690 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008691f_setreg(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008692 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008693 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008694{
8695 int regname;
8696 char_u *strregname;
8697 char_u *stropt;
8698 int append;
8699 char_u yank_type;
8700 long block_len;
8701
8702 block_len = -1;
8703 yank_type = MAUTO;
8704 append = FALSE;
8705
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008706 strregname = get_tv_string(argvars);
8707 rettv->vval.v_number = 1; /* FAIL is default */
Bram Moolenaar071d4272004-06-13 20:20:40 +00008708
8709 regname = (strregname == NULL ? '"' : *strregname);
8710 if (regname == 0 || regname == '@')
8711 regname = '"';
8712 else if (regname == '=')
8713 return;
8714
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008715 if (argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008716 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008717 for (stropt = get_tv_string(&argvars[2]); *stropt != NUL; ++stropt)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008718 switch (*stropt)
8719 {
8720 case 'a': case 'A': /* append */
8721 append = TRUE;
8722 break;
8723 case 'v': case 'c': /* character-wise selection */
8724 yank_type = MCHAR;
8725 break;
8726 case 'V': case 'l': /* line-wise selection */
8727 yank_type = MLINE;
8728 break;
8729#ifdef FEAT_VISUAL
8730 case 'b': case Ctrl_V: /* block-wise selection */
8731 yank_type = MBLOCK;
8732 if (VIM_ISDIGIT(stropt[1]))
8733 {
8734 ++stropt;
8735 block_len = getdigits(&stropt) - 1;
8736 --stropt;
8737 }
8738 break;
8739#endif
8740 }
8741 }
8742
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008743 write_reg_contents_ex(regname, get_tv_string(&argvars[1]), -1,
Bram Moolenaar071d4272004-06-13 20:20:40 +00008744 append, yank_type, block_len);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008745 rettv->vval.v_number = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008746}
8747
8748
8749/*
8750 * "setwinvar(expr)" function
8751 */
8752/*ARGSUSED*/
8753 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008754f_setwinvar(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008755 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008756 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008757{
8758 win_T *win;
8759#ifdef FEAT_WINDOWS
8760 win_T *save_curwin;
8761#endif
8762 char_u *varname, *winvarname;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008763 typeval *varp;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008764 char_u nbuf[NUMBUFLEN];
8765
8766 if (check_restricted() || check_secure())
8767 return;
8768 ++emsg_off;
8769 win = find_win_by_nr(&argvars[0]);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008770 varname = get_tv_string(&argvars[1]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008771 varp = &argvars[2];
8772
8773 if (win != NULL && varname != NULL && varp != NULL)
8774 {
8775#ifdef FEAT_WINDOWS
8776 /* set curwin to be our win, temporarily */
8777 save_curwin = curwin;
8778 curwin = win;
8779 curbuf = curwin->w_buffer;
8780#endif
8781
8782 if (*varname == '&')
8783 {
8784 ++varname;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008785 set_option_value(varname, get_tv_number(varp),
8786 get_tv_string_buf(varp, nbuf), OPT_LOCAL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008787 }
8788 else
8789 {
8790 winvarname = alloc((unsigned)STRLEN(varname) + 3);
8791 if (winvarname != NULL)
8792 {
8793 STRCPY(winvarname, "w:");
8794 STRCPY(winvarname + 2, varname);
Bram Moolenaar1c2fda22005-01-02 11:43:19 +00008795 set_var(winvarname, varp, TRUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008796 vim_free(winvarname);
8797 }
8798 }
8799
8800#ifdef FEAT_WINDOWS
8801 /* Restore current window, if it's still valid (autocomands can make
8802 * it invalid). */
8803 if (win_valid(save_curwin))
8804 {
8805 curwin = save_curwin;
8806 curbuf = curwin->w_buffer;
8807 }
8808#endif
8809 }
8810 --emsg_off;
8811}
8812
8813/*
8814 * "nextnonblank()" function
8815 */
8816 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008817f_nextnonblank(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008818 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008819 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008820{
8821 linenr_T lnum;
8822
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008823 for (lnum = get_tv_lnum(argvars); ; ++lnum)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008824 {
8825 if (lnum > curbuf->b_ml.ml_line_count)
8826 {
8827 lnum = 0;
8828 break;
8829 }
8830 if (*skipwhite(ml_get(lnum)) != NUL)
8831 break;
8832 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008833 rettv->vval.v_number = lnum;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008834}
8835
8836/*
8837 * "prevnonblank()" function
8838 */
8839 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008840f_prevnonblank(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008841 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008842 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008843{
8844 linenr_T lnum;
8845
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008846 lnum = get_tv_lnum(argvars);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008847 if (lnum < 1 || lnum > curbuf->b_ml.ml_line_count)
8848 lnum = 0;
8849 else
8850 while (lnum >= 1 && *skipwhite(ml_get(lnum)) == NUL)
8851 --lnum;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008852 rettv->vval.v_number = lnum;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008853}
8854
8855#if defined(FEAT_CLIENTSERVER) && defined(FEAT_X11)
8856static void make_connection __ARGS((void));
8857static int check_connection __ARGS((void));
8858
8859 static void
8860make_connection()
8861{
8862 if (X_DISPLAY == NULL
8863# ifdef FEAT_GUI
8864 && !gui.in_use
8865# endif
8866 )
8867 {
8868 x_force_connect = TRUE;
8869 setup_term_clip();
8870 x_force_connect = FALSE;
8871 }
8872}
8873
8874 static int
8875check_connection()
8876{
8877 make_connection();
8878 if (X_DISPLAY == NULL)
8879 {
8880 EMSG(_("E240: No connection to Vim server"));
8881 return FAIL;
8882 }
8883 return OK;
8884}
8885#endif
8886
8887/*ARGSUSED*/
8888 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008889f_serverlist(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008890 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008891 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008892{
8893 char_u *r = NULL;
8894
8895#ifdef FEAT_CLIENTSERVER
8896# ifdef WIN32
8897 r = serverGetVimNames();
8898# else
8899 make_connection();
8900 if (X_DISPLAY != NULL)
8901 r = serverGetVimNames(X_DISPLAY);
8902# endif
8903#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008904 rettv->v_type = VAR_STRING;
8905 rettv->vval.v_string = r;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008906}
8907
8908/*ARGSUSED*/
8909 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008910f_remote_peek(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008911 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008912 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008913{
8914#ifdef FEAT_CLIENTSERVER
8915 var v;
8916 char_u *s = NULL;
8917# ifdef WIN32
8918 int n = 0;
8919# endif
8920
8921 if (check_restricted() || check_secure())
8922 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008923 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008924 return;
8925 }
8926# ifdef WIN32
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008927 sscanf(get_tv_string(&argvars[0]), "%x", &n);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008928 if (n == 0)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008929 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008930 else
8931 {
8932 s = serverGetReply((HWND)n, FALSE, FALSE, FALSE);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008933 rettv->vval.v_number = (s != NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008934 }
8935# else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008936 rettv->vval.v_number = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008937 if (check_connection() == FAIL)
8938 return;
8939
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008940 rettv->vval.v_number = serverPeekReply(X_DISPLAY,
8941 serverStrToWin(get_tv_string(&argvars[0])), &s);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008942# endif
8943
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008944 if (argvars[1].v_type != VAR_UNKNOWN && rettv->vval.v_number > 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008945 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008946 v.tv.v_type = VAR_STRING;
8947 v.tv.vval.v_string = vim_strsave(s);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008948 set_var(get_tv_string(&argvars[1]), &v.tv, FALSE);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008949 vim_free(v.tv.vval.v_string);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008950 }
8951#else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008952 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008953#endif
8954}
8955
8956/*ARGSUSED*/
8957 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008958f_remote_read(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008959 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008960 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008961{
8962 char_u *r = NULL;
8963
8964#ifdef FEAT_CLIENTSERVER
8965 if (!check_restricted() && !check_secure())
8966 {
8967# ifdef WIN32
8968 /* The server's HWND is encoded in the 'id' parameter */
8969 int n = 0;
8970
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008971 sscanf(get_tv_string(&argvars[0]), "%x", &n);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008972 if (n != 0)
8973 r = serverGetReply((HWND)n, FALSE, TRUE, TRUE);
8974 if (r == NULL)
8975# else
8976 if (check_connection() == FAIL || serverReadReply(X_DISPLAY,
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008977 serverStrToWin(get_tv_string(&argvars[0])), &r, FALSE) < 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008978# endif
8979 EMSG(_("E277: Unable to read a server reply"));
8980 }
8981#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008982 rettv->v_type = VAR_STRING;
8983 rettv->vval.v_string = r;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008984}
8985
8986/*ARGSUSED*/
8987 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008988f_server2client(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008989 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008990 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008991{
8992#ifdef FEAT_CLIENTSERVER
8993 char_u buf[NUMBUFLEN];
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008994 char_u *server = get_tv_string(&argvars[0]);
8995 char_u *reply = get_tv_string_buf(&argvars[1], buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008996
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008997 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008998 if (check_restricted() || check_secure())
8999 return;
9000# ifdef FEAT_X11
9001 if (check_connection() == FAIL)
9002 return;
9003# endif
9004
9005 if (serverSendReply(server, reply) < 0)
9006 {
9007 EMSG(_("E258: Unable to send to client"));
9008 return;
9009 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009010 rettv->vval.v_number = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009011#else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009012 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009013#endif
9014}
9015
9016#ifdef FEAT_CLIENTSERVER
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009017static void remote_common __ARGS((typeval *argvars, typeval *rettv, int expr));
Bram Moolenaar071d4272004-06-13 20:20:40 +00009018
9019 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009020remote_common(argvars, rettv, expr)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009021 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009022 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009023 int expr;
9024{
9025 char_u *server_name;
9026 char_u *keys;
9027 char_u *r = NULL;
9028 char_u buf[NUMBUFLEN];
9029# ifdef WIN32
9030 HWND w;
9031# else
9032 Window w;
9033# endif
9034
9035 if (check_restricted() || check_secure())
9036 return;
9037
9038# ifdef FEAT_X11
9039 if (check_connection() == FAIL)
9040 return;
9041# endif
9042
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009043 server_name = get_tv_string(&argvars[0]);
9044 keys = get_tv_string_buf(&argvars[1], buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009045# ifdef WIN32
9046 if (serverSendToVim(server_name, keys, &r, &w, expr, TRUE) < 0)
9047# else
9048 if (serverSendToVim(X_DISPLAY, server_name, keys, &r, &w, expr, 0, TRUE)
9049 < 0)
9050# endif
9051 {
9052 if (r != NULL)
9053 EMSG(r); /* sending worked but evaluation failed */
9054 else
9055 EMSG2(_("E241: Unable to send to %s"), server_name);
9056 return;
9057 }
9058
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009059 rettv->vval.v_string = r;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009060
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009061 if (argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009062 {
9063 var v;
9064 char_u str[30];
9065
9066 sprintf((char *)str, "0x%x", (unsigned int)w);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009067 v.tv.v_type = VAR_STRING;
9068 v.tv.vval.v_string = vim_strsave(str);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009069 set_var(get_tv_string(&argvars[2]), &v.tv, FALSE);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009070 vim_free(v.tv.vval.v_string);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009071 }
9072}
9073#endif
9074
9075/*
9076 * "remote_expr()" function
9077 */
9078/*ARGSUSED*/
9079 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009080f_remote_expr(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009081 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009082 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009083{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009084 rettv->v_type = VAR_STRING;
9085 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009086#ifdef FEAT_CLIENTSERVER
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009087 remote_common(argvars, rettv, TRUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009088#endif
9089}
9090
9091/*
9092 * "remote_send()" function
9093 */
9094/*ARGSUSED*/
9095 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009096f_remote_send(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009097 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009098 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009099{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009100 rettv->v_type = VAR_STRING;
9101 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009102#ifdef FEAT_CLIENTSERVER
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009103 remote_common(argvars, rettv, FALSE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009104#endif
9105}
9106
9107/*
9108 * "remote_foreground()" function
9109 */
9110/*ARGSUSED*/
9111 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009112f_remote_foreground(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009113 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009114 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009115{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009116 rettv->vval.v_number = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009117#ifdef FEAT_CLIENTSERVER
9118# ifdef WIN32
9119 /* On Win32 it's done in this application. */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009120 serverForeground(get_tv_string(&argvars[0]));
Bram Moolenaar071d4272004-06-13 20:20:40 +00009121# else
9122 /* Send a foreground() expression to the server. */
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009123 argvars[1].v_type = VAR_STRING;
9124 argvars[1].vval.v_string = vim_strsave((char_u *)"foreground()");
9125 argvars[2].v_type = VAR_UNKNOWN;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009126 remote_common(argvars, rettv, TRUE);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009127 vim_free(argvars[1].vval.v_string);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009128# endif
9129#endif
9130}
9131
9132#ifdef HAVE_STRFTIME
9133/*
9134 * "strftime({format}[, {time}])" function
9135 */
9136 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009137f_strftime(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009138 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009139 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009140{
9141 char_u result_buf[256];
9142 struct tm *curtime;
9143 time_t seconds;
9144 char_u *p;
9145
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009146 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009147
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009148 p = get_tv_string(&argvars[0]);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009149 if (argvars[1].v_type == VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009150 seconds = time(NULL);
9151 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009152 seconds = (time_t)get_tv_number(&argvars[1]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009153 curtime = localtime(&seconds);
9154 /* MSVC returns NULL for an invalid value of seconds. */
9155 if (curtime == NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009156 rettv->vval.v_string = vim_strsave((char_u *)_("(Invalid)"));
Bram Moolenaar071d4272004-06-13 20:20:40 +00009157 else
9158 {
9159# ifdef FEAT_MBYTE
9160 vimconv_T conv;
9161 char_u *enc;
9162
9163 conv.vc_type = CONV_NONE;
9164 enc = enc_locale();
9165 convert_setup(&conv, p_enc, enc);
9166 if (conv.vc_type != CONV_NONE)
9167 p = string_convert(&conv, p, NULL);
9168# endif
9169 if (p != NULL)
9170 (void)strftime((char *)result_buf, sizeof(result_buf),
9171 (char *)p, curtime);
9172 else
9173 result_buf[0] = NUL;
9174
9175# ifdef FEAT_MBYTE
9176 if (conv.vc_type != CONV_NONE)
9177 vim_free(p);
9178 convert_setup(&conv, enc, p_enc);
9179 if (conv.vc_type != CONV_NONE)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009180 rettv->vval.v_string = string_convert(&conv, result_buf, NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009181 else
9182# endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009183 rettv->vval.v_string = vim_strsave(result_buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009184
9185# ifdef FEAT_MBYTE
9186 /* Release conversion descriptors */
9187 convert_setup(&conv, NULL, NULL);
9188 vim_free(enc);
9189# endif
9190 }
9191}
9192#endif
9193
9194/*
9195 * "stridx()" function
9196 */
9197 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009198f_stridx(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009199 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009200 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009201{
9202 char_u buf[NUMBUFLEN];
9203 char_u *needle;
9204 char_u *haystack;
9205 char_u *pos;
9206
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009207 needle = get_tv_string(&argvars[1]);
9208 haystack = get_tv_string_buf(&argvars[0], buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009209 pos = (char_u *)strstr((char *)haystack, (char *)needle);
9210
9211 if (pos == NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009212 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009213 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009214 rettv->vval.v_number = (varnumber_T) (pos - haystack);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009215}
9216
9217/*
9218 * "strridx()" function
9219 */
9220 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009221f_strridx(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 buf[NUMBUFLEN];
9226 char_u *needle;
9227 char_u *haystack;
9228 char_u *rest;
9229 char_u *lastmatch = NULL;
9230
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009231 needle = get_tv_string(&argvars[1]);
9232 haystack = get_tv_string_buf(&argvars[0], buf);
Bram Moolenaard4755bb2004-09-02 19:12:26 +00009233 if (*needle == NUL)
9234 /* Empty string matches past the end. */
9235 lastmatch = haystack + STRLEN(haystack);
9236 else
9237 for (rest = haystack; *rest != '\0'; ++rest)
9238 {
9239 rest = (char_u *)strstr((char *)rest, (char *)needle);
9240 if (rest == NULL)
9241 break;
9242 lastmatch = rest;
9243 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00009244
9245 if (lastmatch == NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009246 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009247 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009248 rettv->vval.v_number = (varnumber_T)(lastmatch - haystack);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009249}
9250
9251/*
9252 * "string()" function
9253 */
9254 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009255f_string(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009256 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009257 typeval *rettv;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009258{
9259 char_u *tofree;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00009260 char_u numbuf[NUMBUFLEN];
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009261
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009262 rettv->v_type = VAR_STRING;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00009263 rettv->vval.v_string = tv2string(&argvars[0], &tofree, numbuf);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009264 if (tofree == NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009265 rettv->vval.v_string = vim_strsave(rettv->vval.v_string);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009266}
9267
9268/*
9269 * "strlen()" function
9270 */
9271 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009272f_strlen(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009273 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009274 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009275{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009276 rettv->vval.v_number = (varnumber_T)(STRLEN(
9277 get_tv_string(&argvars[0])));
Bram Moolenaar071d4272004-06-13 20:20:40 +00009278}
9279
9280/*
9281 * "strpart()" function
9282 */
9283 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009284f_strpart(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009285 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009286 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009287{
9288 char_u *p;
9289 int n;
9290 int len;
9291 int slen;
9292
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009293 p = get_tv_string(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009294 slen = (int)STRLEN(p);
9295
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009296 n = get_tv_number(&argvars[1]);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009297 if (argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009298 len = get_tv_number(&argvars[2]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009299 else
9300 len = slen - n; /* default len: all bytes that are available. */
9301
9302 /*
9303 * Only return the overlap between the specified part and the actual
9304 * string.
9305 */
9306 if (n < 0)
9307 {
9308 len += n;
9309 n = 0;
9310 }
9311 else if (n > slen)
9312 n = slen;
9313 if (len < 0)
9314 len = 0;
9315 else if (n + len > slen)
9316 len = slen - n;
9317
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009318 rettv->v_type = VAR_STRING;
9319 rettv->vval.v_string = vim_strnsave(p + n, len);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009320}
9321
9322/*
9323 * "strtrans()" function
9324 */
9325 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009326f_strtrans(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009327 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009328 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009329{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009330 rettv->v_type = VAR_STRING;
9331 rettv->vval.v_string = transstr(get_tv_string(&argvars[0]));
Bram Moolenaar071d4272004-06-13 20:20:40 +00009332}
9333
9334/*
9335 * "synID(line, col, trans)" function
9336 */
9337/*ARGSUSED*/
9338 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009339f_synID(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009340 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009341 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009342{
9343 int id = 0;
9344#ifdef FEAT_SYN_HL
9345 long line;
9346 long col;
9347 int trans;
9348
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009349 line = get_tv_lnum(argvars);
9350 col = get_tv_number(&argvars[1]) - 1;
9351 trans = get_tv_number(&argvars[2]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009352
9353 if (line >= 1 && line <= curbuf->b_ml.ml_line_count
9354 && col >= 0 && col < (long)STRLEN(ml_get(line)))
9355 id = syn_get_id(line, col, trans);
9356#endif
9357
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009358 rettv->vval.v_number = id;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009359}
9360
9361/*
9362 * "synIDattr(id, what [, mode])" function
9363 */
9364/*ARGSUSED*/
9365 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009366f_synIDattr(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009367 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009368 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009369{
9370 char_u *p = NULL;
9371#ifdef FEAT_SYN_HL
9372 int id;
9373 char_u *what;
9374 char_u *mode;
9375 char_u modebuf[NUMBUFLEN];
9376 int modec;
9377
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009378 id = get_tv_number(&argvars[0]);
9379 what = get_tv_string(&argvars[1]);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009380 if (argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009381 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009382 mode = get_tv_string_buf(&argvars[2], modebuf);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009383 modec = TOLOWER_ASC(mode[0]);
9384 if (modec != 't' && modec != 'c'
9385#ifdef FEAT_GUI
9386 && modec != 'g'
9387#endif
9388 )
9389 modec = 0; /* replace invalid with current */
9390 }
9391 else
9392 {
9393#ifdef FEAT_GUI
9394 if (gui.in_use)
9395 modec = 'g';
9396 else
9397#endif
9398 if (t_colors > 1)
9399 modec = 'c';
9400 else
9401 modec = 't';
9402 }
9403
9404
9405 switch (TOLOWER_ASC(what[0]))
9406 {
9407 case 'b':
9408 if (TOLOWER_ASC(what[1]) == 'g') /* bg[#] */
9409 p = highlight_color(id, what, modec);
9410 else /* bold */
9411 p = highlight_has_attr(id, HL_BOLD, modec);
9412 break;
9413
9414 case 'f': /* fg[#] */
9415 p = highlight_color(id, what, modec);
9416 break;
9417
9418 case 'i':
9419 if (TOLOWER_ASC(what[1]) == 'n') /* inverse */
9420 p = highlight_has_attr(id, HL_INVERSE, modec);
9421 else /* italic */
9422 p = highlight_has_attr(id, HL_ITALIC, modec);
9423 break;
9424
9425 case 'n': /* name */
9426 p = get_highlight_name(NULL, id - 1);
9427 break;
9428
9429 case 'r': /* reverse */
9430 p = highlight_has_attr(id, HL_INVERSE, modec);
9431 break;
9432
9433 case 's': /* standout */
9434 p = highlight_has_attr(id, HL_STANDOUT, modec);
9435 break;
9436
9437 case 'u': /* underline */
9438 p = highlight_has_attr(id, HL_UNDERLINE, modec);
9439 break;
9440 }
9441
9442 if (p != NULL)
9443 p = vim_strsave(p);
9444#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009445 rettv->v_type = VAR_STRING;
9446 rettv->vval.v_string = p;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009447}
9448
9449/*
9450 * "synIDtrans(id)" function
9451 */
9452/*ARGSUSED*/
9453 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009454f_synIDtrans(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009455 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009456 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009457{
9458 int id;
9459
9460#ifdef FEAT_SYN_HL
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009461 id = get_tv_number(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009462
9463 if (id > 0)
9464 id = syn_get_final_id(id);
9465 else
9466#endif
9467 id = 0;
9468
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009469 rettv->vval.v_number = id;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009470}
9471
9472/*
9473 * "system()" function
9474 */
9475 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009476f_system(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009477 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009478 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009479{
Bram Moolenaarc0197e22004-09-13 20:26:32 +00009480 char_u *res = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009481 char_u *p;
Bram Moolenaarc0197e22004-09-13 20:26:32 +00009482 char_u *infile = NULL;
9483 char_u buf[NUMBUFLEN];
9484 int err = FALSE;
9485 FILE *fd;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009486
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009487 if (argvars[1].v_type != VAR_UNKNOWN)
Bram Moolenaarc0197e22004-09-13 20:26:32 +00009488 {
9489 /*
9490 * Write the string to a temp file, to be used for input of the shell
9491 * command.
9492 */
9493 if ((infile = vim_tempname('i')) == NULL)
9494 {
9495 EMSG(_(e_notmp));
9496 return;
9497 }
9498
9499 fd = mch_fopen((char *)infile, WRITEBIN);
9500 if (fd == NULL)
9501 {
9502 EMSG2(_(e_notopen), infile);
9503 goto done;
9504 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009505 p = get_tv_string_buf(&argvars[1], buf);
Bram Moolenaarc0197e22004-09-13 20:26:32 +00009506 if (fwrite(p, STRLEN(p), 1, fd) != 1)
9507 err = TRUE;
9508 if (fclose(fd) != 0)
9509 err = TRUE;
9510 if (err)
9511 {
9512 EMSG(_("E677: Error writing temp file"));
9513 goto done;
9514 }
9515 }
9516
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009517 res = get_cmd_output(get_tv_string(&argvars[0]), infile, SHELL_SILENT);
Bram Moolenaarc0197e22004-09-13 20:26:32 +00009518
Bram Moolenaar071d4272004-06-13 20:20:40 +00009519#ifdef USE_CR
9520 /* translate <CR> into <NL> */
Bram Moolenaarc0197e22004-09-13 20:26:32 +00009521 if (res != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009522 {
9523 char_u *s;
9524
Bram Moolenaarc0197e22004-09-13 20:26:32 +00009525 for (s = res; *s; ++s)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009526 {
9527 if (*s == CAR)
9528 *s = NL;
9529 }
9530 }
9531#else
9532# ifdef USE_CRNL
9533 /* translate <CR><NL> into <NL> */
Bram Moolenaarc0197e22004-09-13 20:26:32 +00009534 if (res != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009535 {
9536 char_u *s, *d;
9537
Bram Moolenaarc0197e22004-09-13 20:26:32 +00009538 d = res;
9539 for (s = res; *s; ++s)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009540 {
9541 if (s[0] == CAR && s[1] == NL)
9542 ++s;
9543 *d++ = *s;
9544 }
9545 *d = NUL;
9546 }
9547# endif
9548#endif
Bram Moolenaarc0197e22004-09-13 20:26:32 +00009549
9550done:
9551 if (infile != NULL)
9552 {
9553 mch_remove(infile);
9554 vim_free(infile);
9555 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009556 rettv->v_type = VAR_STRING;
9557 rettv->vval.v_string = res;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009558}
9559
9560/*
9561 * "submatch()" function
9562 */
9563 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009564f_submatch(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009565 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009566 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009567{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009568 rettv->v_type = VAR_STRING;
9569 rettv->vval.v_string = reg_submatch((int)get_tv_number(&argvars[0]));
Bram Moolenaar071d4272004-06-13 20:20:40 +00009570}
9571
9572/*
9573 * "substitute()" function
9574 */
9575 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009576f_substitute(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009577 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009578 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009579{
9580 char_u patbuf[NUMBUFLEN];
9581 char_u subbuf[NUMBUFLEN];
9582 char_u flagsbuf[NUMBUFLEN];
9583
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009584 rettv->v_type = VAR_STRING;
9585 rettv->vval.v_string = do_string_sub(
9586 get_tv_string(&argvars[0]),
9587 get_tv_string_buf(&argvars[1], patbuf),
9588 get_tv_string_buf(&argvars[2], subbuf),
9589 get_tv_string_buf(&argvars[3], flagsbuf));
Bram Moolenaar071d4272004-06-13 20:20:40 +00009590}
9591
9592/*
9593 * "tempname()" function
9594 */
9595/*ARGSUSED*/
9596 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009597f_tempname(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009598 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009599 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009600{
9601 static int x = 'A';
9602
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009603 rettv->v_type = VAR_STRING;
9604 rettv->vval.v_string = vim_tempname(x);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009605
9606 /* Advance 'x' to use A-Z and 0-9, so that there are at least 34 different
9607 * names. Skip 'I' and 'O', they are used for shell redirection. */
9608 do
9609 {
9610 if (x == 'Z')
9611 x = '0';
9612 else if (x == '9')
9613 x = 'A';
9614 else
9615 {
9616#ifdef EBCDIC
9617 if (x == 'I')
9618 x = 'J';
9619 else if (x == 'R')
9620 x = 'S';
9621 else
9622#endif
9623 ++x;
9624 }
9625 } while (x == 'I' || x == 'O');
9626}
9627
9628/*
9629 * "tolower(string)" function
9630 */
9631 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009632f_tolower(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009633 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009634 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009635{
9636 char_u *p;
9637
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009638 p = vim_strsave(get_tv_string(&argvars[0]));
9639 rettv->v_type = VAR_STRING;
9640 rettv->vval.v_string = p;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009641
9642 if (p != NULL)
9643 while (*p != NUL)
9644 {
9645#ifdef FEAT_MBYTE
9646 int l;
9647
9648 if (enc_utf8)
9649 {
9650 int c, lc;
9651
9652 c = utf_ptr2char(p);
9653 lc = utf_tolower(c);
9654 l = utf_ptr2len_check(p);
9655 /* TODO: reallocate string when byte count changes. */
9656 if (utf_char2len(lc) == l)
9657 utf_char2bytes(lc, p);
9658 p += l;
9659 }
9660 else if (has_mbyte && (l = (*mb_ptr2len_check)(p)) > 1)
9661 p += l; /* skip multi-byte character */
9662 else
9663#endif
9664 {
9665 *p = TOLOWER_LOC(*p); /* note that tolower() can be a macro */
9666 ++p;
9667 }
9668 }
9669}
9670
9671/*
9672 * "toupper(string)" function
9673 */
9674 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009675f_toupper(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009676 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009677 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009678{
9679 char_u *p;
9680
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009681 p = vim_strsave(get_tv_string(&argvars[0]));
9682 rettv->v_type = VAR_STRING;
9683 rettv->vval.v_string = p;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009684
9685 if (p != NULL)
9686 while (*p != NUL)
9687 {
9688#ifdef FEAT_MBYTE
9689 int l;
9690
9691 if (enc_utf8)
9692 {
9693 int c, uc;
9694
9695 c = utf_ptr2char(p);
9696 uc = utf_toupper(c);
9697 l = utf_ptr2len_check(p);
9698 /* TODO: reallocate string when byte count changes. */
9699 if (utf_char2len(uc) == l)
9700 utf_char2bytes(uc, p);
9701 p += l;
9702 }
9703 else if (has_mbyte && (l = (*mb_ptr2len_check)(p)) > 1)
9704 p += l; /* skip multi-byte character */
9705 else
9706#endif
9707 {
9708 *p = TOUPPER_LOC(*p); /* note that toupper() can be a macro */
9709 p++;
9710 }
9711 }
9712}
9713
9714/*
Bram Moolenaar8299df92004-07-10 09:47:34 +00009715 * "tr(string, fromstr, tostr)" function
9716 */
9717 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009718f_tr(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009719 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009720 typeval *rettv;
Bram Moolenaar8299df92004-07-10 09:47:34 +00009721{
9722 char_u *instr;
9723 char_u *fromstr;
9724 char_u *tostr;
9725 char_u *p;
9726#ifdef FEAT_MBYTE
9727 int inlen;
9728 int fromlen;
9729 int tolen;
9730 int idx;
9731 char_u *cpstr;
9732 int cplen;
9733 int first = TRUE;
9734#endif
9735 char_u buf[NUMBUFLEN];
9736 char_u buf2[NUMBUFLEN];
9737 garray_T ga;
9738
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009739 instr = get_tv_string(&argvars[0]);
9740 fromstr = get_tv_string_buf(&argvars[1], buf);
9741 tostr = get_tv_string_buf(&argvars[2], buf2);
Bram Moolenaar8299df92004-07-10 09:47:34 +00009742
9743 /* Default return value: empty string. */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009744 rettv->v_type = VAR_STRING;
9745 rettv->vval.v_string = NULL;
Bram Moolenaar8299df92004-07-10 09:47:34 +00009746 ga_init2(&ga, (int)sizeof(char), 80);
9747
9748#ifdef FEAT_MBYTE
9749 if (!has_mbyte)
9750#endif
9751 /* not multi-byte: fromstr and tostr must be the same length */
9752 if (STRLEN(fromstr) != STRLEN(tostr))
9753 {
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00009754#ifdef FEAT_MBYTE
Bram Moolenaar8299df92004-07-10 09:47:34 +00009755error:
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00009756#endif
Bram Moolenaar8299df92004-07-10 09:47:34 +00009757 EMSG2(_(e_invarg2), fromstr);
9758 ga_clear(&ga);
9759 return;
9760 }
9761
9762 /* fromstr and tostr have to contain the same number of chars */
9763 while (*instr != NUL)
9764 {
9765#ifdef FEAT_MBYTE
9766 if (has_mbyte)
9767 {
9768 inlen = mb_ptr2len_check(instr);
9769 cpstr = instr;
9770 cplen = inlen;
9771 idx = 0;
9772 for (p = fromstr; *p != NUL; p += fromlen)
9773 {
9774 fromlen = mb_ptr2len_check(p);
9775 if (fromlen == inlen && STRNCMP(instr, p, inlen) == 0)
9776 {
9777 for (p = tostr; *p != NUL; p += tolen)
9778 {
9779 tolen = mb_ptr2len_check(p);
9780 if (idx-- == 0)
9781 {
9782 cplen = tolen;
9783 cpstr = p;
9784 break;
9785 }
9786 }
9787 if (*p == NUL) /* tostr is shorter than fromstr */
9788 goto error;
9789 break;
9790 }
9791 ++idx;
9792 }
9793
9794 if (first && cpstr == instr)
9795 {
9796 /* Check that fromstr and tostr have the same number of
9797 * (multi-byte) characters. Done only once when a character
9798 * of instr doesn't appear in fromstr. */
9799 first = FALSE;
9800 for (p = tostr; *p != NUL; p += tolen)
9801 {
9802 tolen = mb_ptr2len_check(p);
9803 --idx;
9804 }
9805 if (idx != 0)
9806 goto error;
9807 }
9808
9809 ga_grow(&ga, cplen);
Bram Moolenaar2df6dcc2004-07-12 15:53:54 +00009810 mch_memmove((char *)ga.ga_data + ga.ga_len, cpstr, (size_t)cplen);
Bram Moolenaar8299df92004-07-10 09:47:34 +00009811 ga.ga_len += cplen;
Bram Moolenaar8299df92004-07-10 09:47:34 +00009812
9813 instr += inlen;
9814 }
9815 else
9816#endif
9817 {
9818 /* When not using multi-byte chars we can do it faster. */
9819 p = vim_strchr(fromstr, *instr);
9820 if (p != NULL)
9821 ga_append(&ga, tostr[p - fromstr]);
9822 else
9823 ga_append(&ga, *instr);
9824 ++instr;
9825 }
9826 }
9827
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009828 rettv->vval.v_string = ga.ga_data;
Bram Moolenaar8299df92004-07-10 09:47:34 +00009829}
9830
9831/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00009832 * "type(expr)" function
9833 */
9834 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009835f_type(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009836 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009837 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009838{
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009839 if (argvars[0].v_type == VAR_NUMBER)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009840 rettv->vval.v_number = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009841 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009842 rettv->vval.v_number = 1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009843}
9844
9845/*
9846 * "virtcol(string)" function
9847 */
9848 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009849f_virtcol(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009850 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009851 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009852{
9853 colnr_T vcol = 0;
9854 pos_T *fp;
9855
9856 fp = var2fpos(&argvars[0], FALSE);
9857 if (fp != NULL && fp->lnum <= curbuf->b_ml.ml_line_count)
9858 {
9859 getvvcol(curwin, fp, NULL, NULL, &vcol);
9860 ++vcol;
9861 }
9862
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009863 rettv->vval.v_number = vcol;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009864}
9865
9866/*
9867 * "visualmode()" function
9868 */
9869/*ARGSUSED*/
9870 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009871f_visualmode(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009872 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009873 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009874{
9875#ifdef FEAT_VISUAL
9876 char_u str[2];
9877
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009878 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009879 str[0] = curbuf->b_visual_mode_eval;
9880 str[1] = NUL;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009881 rettv->vval.v_string = vim_strsave(str);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009882
9883 /* A non-zero number or non-empty string argument: reset mode. */
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009884 if ((argvars[0].v_type == VAR_NUMBER
9885 && argvars[0].vval.v_number != 0)
9886 || (argvars[0].v_type == VAR_STRING
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009887 && *get_tv_string(&argvars[0]) != NUL))
Bram Moolenaar071d4272004-06-13 20:20:40 +00009888 curbuf->b_visual_mode_eval = NUL;
9889#else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009890 rettv->vval.v_number = 0; /* return anything, it won't work anyway */
Bram Moolenaar071d4272004-06-13 20:20:40 +00009891#endif
9892}
9893
9894/*
9895 * "winbufnr(nr)" function
9896 */
9897 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009898f_winbufnr(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009899 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009900 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009901{
9902 win_T *wp;
9903
9904 wp = find_win_by_nr(&argvars[0]);
9905 if (wp == NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009906 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009907 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009908 rettv->vval.v_number = wp->w_buffer->b_fnum;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009909}
9910
9911/*
9912 * "wincol()" function
9913 */
9914/*ARGSUSED*/
9915 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009916f_wincol(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009917 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009918 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009919{
9920 validate_cursor();
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009921 rettv->vval.v_number = curwin->w_wcol + 1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009922}
9923
9924/*
9925 * "winheight(nr)" function
9926 */
9927 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009928f_winheight(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009929 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009930 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009931{
9932 win_T *wp;
9933
9934 wp = find_win_by_nr(&argvars[0]);
9935 if (wp == NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009936 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009937 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009938 rettv->vval.v_number = wp->w_height;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009939}
9940
9941/*
9942 * "winline()" function
9943 */
9944/*ARGSUSED*/
9945 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009946f_winline(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009947 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009948 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009949{
9950 validate_cursor();
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009951 rettv->vval.v_number = curwin->w_wrow + 1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009952}
9953
9954/*
9955 * "winnr()" function
9956 */
9957/* ARGSUSED */
9958 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009959f_winnr(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009960 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009961 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009962{
9963 int nr = 1;
9964#ifdef FEAT_WINDOWS
9965 win_T *wp;
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00009966 win_T *twin = curwin;
9967 char_u *arg;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009968
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009969 if (argvars[0].v_type != VAR_UNKNOWN)
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00009970 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009971 arg = get_tv_string(&argvars[0]);
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00009972 if (STRCMP(arg, "$") == 0)
9973 twin = lastwin;
9974 else if (STRCMP(arg, "#") == 0)
9975 {
9976 twin = prevwin;
9977 if (prevwin == NULL)
9978 nr = 0;
9979 }
9980 else
9981 {
9982 EMSG2(_(e_invexpr2), arg);
9983 nr = 0;
9984 }
9985 }
9986
9987 if (nr > 0)
9988 for (wp = firstwin; wp != twin; wp = wp->w_next)
9989 ++nr;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009990#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009991 rettv->vval.v_number = nr;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009992}
9993
9994/*
9995 * "winrestcmd()" function
9996 */
9997/* ARGSUSED */
9998 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009999f_winrestcmd(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010000 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010001 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010002{
10003#ifdef FEAT_WINDOWS
10004 win_T *wp;
10005 int winnr = 1;
10006 garray_T ga;
10007 char_u buf[50];
10008
10009 ga_init2(&ga, (int)sizeof(char), 70);
10010 for (wp = firstwin; wp != NULL; wp = wp->w_next)
10011 {
10012 sprintf((char *)buf, "%dresize %d|", winnr, wp->w_height);
10013 ga_concat(&ga, buf);
10014# ifdef FEAT_VERTSPLIT
10015 sprintf((char *)buf, "vert %dresize %d|", winnr, wp->w_width);
10016 ga_concat(&ga, buf);
10017# endif
10018 ++winnr;
10019 }
Bram Moolenaar269ec652004-07-29 08:43:53 +000010020 ga_append(&ga, NUL);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010021
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010022 rettv->vval.v_string = ga.ga_data;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010023#else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010024 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010025#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010026 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010027}
10028
10029/*
10030 * "winwidth(nr)" function
10031 */
10032 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010033f_winwidth(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010034 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010035 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010036{
10037 win_T *wp;
10038
10039 wp = find_win_by_nr(&argvars[0]);
10040 if (wp == NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010041 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010042 else
10043#ifdef FEAT_VERTSPLIT
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010044 rettv->vval.v_number = wp->w_width;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010045#else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010046 rettv->vval.v_number = Columns;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010047#endif
10048}
10049
10050 static win_T *
10051find_win_by_nr(vp)
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010052 typeval *vp;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010053{
10054#ifdef FEAT_WINDOWS
10055 win_T *wp;
10056#endif
10057 int nr;
10058
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010059 nr = get_tv_number(vp);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010060
10061#ifdef FEAT_WINDOWS
10062 if (nr == 0)
10063 return curwin;
10064
10065 for (wp = firstwin; wp != NULL; wp = wp->w_next)
10066 if (--nr <= 0)
10067 break;
10068 return wp;
10069#else
10070 if (nr == 0 || nr == 1)
10071 return curwin;
10072 return NULL;
10073#endif
10074}
10075
10076/*
10077 * Translate a String variable into a position.
10078 */
10079 static pos_T *
10080var2fpos(varp, lnum)
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010081 typeval *varp;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010082 int lnum; /* TRUE when $ is last line */
10083{
10084 char_u *name;
10085 static pos_T pos;
10086 pos_T *pp;
10087
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010088 name = get_tv_string(varp);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010089 if (name[0] == '.') /* cursor */
10090 return &curwin->w_cursor;
10091 if (name[0] == '\'') /* mark */
10092 {
10093 pp = getmark(name[1], FALSE);
10094 if (pp == NULL || pp == (pos_T *)-1 || pp->lnum <= 0)
10095 return NULL;
10096 return pp;
10097 }
10098 if (name[0] == '$') /* last column or line */
10099 {
10100 if (lnum)
10101 {
10102 pos.lnum = curbuf->b_ml.ml_line_count;
10103 pos.col = 0;
10104 }
10105 else
10106 {
10107 pos.lnum = curwin->w_cursor.lnum;
10108 pos.col = (colnr_T)STRLEN(ml_get_curline());
10109 }
10110 return &pos;
10111 }
10112 return NULL;
10113}
10114
10115/*
10116 * Get the length of an environment variable name.
10117 * Advance "arg" to the first character after the name.
10118 * Return 0 for error.
10119 */
10120 static int
10121get_env_len(arg)
10122 char_u **arg;
10123{
10124 char_u *p;
10125 int len;
10126
10127 for (p = *arg; vim_isIDc(*p); ++p)
10128 ;
10129 if (p == *arg) /* no name found */
10130 return 0;
10131
10132 len = (int)(p - *arg);
10133 *arg = p;
10134 return len;
10135}
10136
10137/*
10138 * Get the length of the name of a function or internal variable.
10139 * "arg" is advanced to the first non-white character after the name.
10140 * Return 0 if something is wrong.
10141 */
10142 static int
10143get_id_len(arg)
10144 char_u **arg;
10145{
10146 char_u *p;
10147 int len;
10148
10149 /* Find the end of the name. */
10150 for (p = *arg; eval_isnamec(*p); ++p)
10151 ;
10152 if (p == *arg) /* no name found */
10153 return 0;
10154
10155 len = (int)(p - *arg);
10156 *arg = skipwhite(p);
10157
10158 return len;
10159}
10160
10161/*
10162 * Get the length of the name of a function.
10163 * "arg" is advanced to the first non-white character after the name.
10164 * Return 0 if something is wrong.
10165 * If the name contains 'magic' {}'s, expand them and return the
10166 * expanded name in an allocated string via 'alias' - caller must free.
10167 */
10168 static int
10169get_func_len(arg, alias, evaluate)
10170 char_u **arg;
10171 char_u **alias;
10172 int evaluate;
10173{
10174 int len;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010175 char_u *p;
10176 char_u *expr_start;
10177 char_u *expr_end;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010178
10179 *alias = NULL; /* default to no alias */
10180
10181 if ((*arg)[0] == K_SPECIAL && (*arg)[1] == KS_EXTRA
10182 && (*arg)[2] == (int)KE_SNR)
10183 {
10184 /* hard coded <SNR>, already translated */
10185 *arg += 3;
10186 return get_id_len(arg) + 3;
10187 }
10188 len = eval_fname_script(*arg);
10189 if (len > 0)
10190 {
10191 /* literal "<SID>", "s:" or "<SNR>" */
10192 *arg += len;
10193 }
10194
Bram Moolenaar071d4272004-06-13 20:20:40 +000010195 /*
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010196 * Find the end of the name; check for {} construction.
Bram Moolenaar071d4272004-06-13 20:20:40 +000010197 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010198 p = find_name_end(*arg, &expr_start, &expr_end, FALSE);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010199 if (expr_start != NULL)
10200 {
10201 char_u *temp_string;
10202
10203 if (!evaluate)
10204 {
10205 len += (int)(p - *arg);
10206 *arg = skipwhite(p);
10207 return len;
10208 }
10209
10210 /*
10211 * Include any <SID> etc in the expanded string:
10212 * Thus the -len here.
10213 */
10214 temp_string = make_expanded_name(*arg - len, expr_start, expr_end, p);
10215 if (temp_string == NULL)
10216 return 0;
10217 *alias = temp_string;
10218 *arg = skipwhite(p);
10219 return (int)STRLEN(temp_string);
10220 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000010221
10222 len += get_id_len(arg);
10223 if (len == 0)
10224 EMSG2(_(e_invexpr2), *arg);
10225
10226 return len;
10227}
10228
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010229/*
10230 * Find the end of a variable or function name, taking care of magic braces.
10231 * If "expr_start" is not NULL then "expr_start" and "expr_end" are set to the
10232 * start and end of the first magic braces item.
10233 * Return a pointer to just after the name. Equal to "arg" if there is no
10234 * valid name.
10235 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000010236 static char_u *
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010237find_name_end(arg, expr_start, expr_end, incl_br)
Bram Moolenaar071d4272004-06-13 20:20:40 +000010238 char_u *arg;
10239 char_u **expr_start;
10240 char_u **expr_end;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010241 int incl_br; /* Include [] indexes */
Bram Moolenaar071d4272004-06-13 20:20:40 +000010242{
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010243 int mb_nest = 0;
10244 int br_nest = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010245 char_u *p;
10246
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010247 if (expr_start != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000010248 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010249 *expr_start = NULL;
10250 *expr_end = NULL;
10251 }
10252
10253 for (p = arg; *p != NUL
10254 && (eval_isnamec(*p)
10255 || (*p == '[' && incl_br)
10256 || mb_nest != 0
10257 || br_nest != 0); ++p)
10258 {
10259 if (mb_nest == 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +000010260 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010261 if (*p == '[')
10262 ++br_nest;
10263 else if (*p == ']')
10264 --br_nest;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010265 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010266 if (br_nest == 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +000010267 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010268 if (*p == '{')
10269 {
10270 mb_nest++;
10271 if (expr_start != NULL && *expr_start == NULL)
10272 *expr_start = p;
10273 }
10274 else if (*p == '}')
10275 {
10276 mb_nest--;
10277 if (expr_start != NULL && mb_nest == 0 && *expr_end == NULL)
10278 *expr_end = p;
10279 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000010280 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000010281 }
10282
10283 return p;
10284}
10285
10286/*
10287 * Return TRUE if character "c" can be used in a variable or function name.
10288 */
10289 static int
10290eval_isnamec(c)
10291 int c;
10292{
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010293 return (ASCII_ISALNUM(c) || c == '_' || c == ':' || c == '{' || c == '}');
Bram Moolenaar071d4272004-06-13 20:20:40 +000010294}
10295
10296/*
10297 * Find a v: variable.
10298 * Return it's index, or -1 if not found.
10299 */
10300 static int
10301find_vim_var(name, len)
10302 char_u *name;
10303 int len; /* length of "name" */
10304{
10305 char_u *vname;
10306 int vlen;
10307 int i;
10308
10309 /*
10310 * Ignore "v:" for old built-in variables, require it for new ones.
10311 */
10312 if (name[0] == 'v' && name[1] == ':')
10313 {
10314 vname = name + 2;
10315 vlen = len - 2;
10316 }
10317 else
10318 {
10319 vname = name;
10320 vlen = len;
10321 }
10322 for (i = 0; i < VV_LEN; ++i)
10323 if (vlen == vimvars[i].len && STRCMP(vname, vimvars[i].name) == 0
10324 && ((vimvars[i].flags & VV_COMPAT) || vname != name))
10325 return i;
10326 return -1;
10327}
10328
10329/*
10330 * Set number v: variable to "val".
10331 */
10332 void
10333set_vim_var_nr(idx, val)
10334 int idx;
10335 long val;
10336{
10337 vimvars[idx].val = (char_u *)val;
10338}
10339
10340/*
10341 * Get number v: variable value;
10342 */
10343 long
10344get_vim_var_nr(idx)
10345 int idx;
10346{
10347 return (long)vimvars[idx].val;
10348}
10349
10350/*
10351 * Set v:count, v:count1 and v:prevcount.
10352 */
10353 void
10354set_vcount(count, count1)
10355 long count;
10356 long count1;
10357{
10358 vimvars[VV_PREVCOUNT].val = vimvars[VV_COUNT].val;
10359 vimvars[VV_COUNT].val = (char_u *)count;
10360 vimvars[VV_COUNT1].val = (char_u *)count1;
10361}
10362
10363/*
10364 * Set string v: variable to a copy of "val".
10365 */
10366 void
10367set_vim_var_string(idx, val, len)
10368 int idx;
10369 char_u *val;
10370 int len; /* length of "val" to use or -1 (whole string) */
10371{
10372 vim_free(vimvars[idx].val);
10373 if (val == NULL)
10374 vimvars[idx].val = NULL;
10375 else if (len == -1)
10376 vimvars[idx].val = vim_strsave(val);
10377 else
10378 vimvars[idx].val = vim_strnsave(val, len);
10379}
10380
10381/*
10382 * Set v:register if needed.
10383 */
10384 void
10385set_reg_var(c)
10386 int c;
10387{
10388 char_u regname;
10389
10390 if (c == 0 || c == ' ')
10391 regname = '"';
10392 else
10393 regname = c;
10394 /* Avoid free/alloc when the value is already right. */
10395 if (vimvars[VV_REG].val == NULL || vimvars[VV_REG].val[0] != c)
10396 set_vim_var_string(VV_REG, &regname, 1);
10397}
10398
10399/*
10400 * Get or set v:exception. If "oldval" == NULL, return the current value.
10401 * Otherwise, restore the value to "oldval" and return NULL.
10402 * Must always be called in pairs to save and restore v:exception! Does not
10403 * take care of memory allocations.
10404 */
10405 char_u *
10406v_exception(oldval)
10407 char_u *oldval;
10408{
10409 if (oldval == NULL)
10410 return vimvars[VV_EXCEPTION].val;
10411
10412 vimvars[VV_EXCEPTION].val = oldval;
10413 return NULL;
10414}
10415
10416/*
10417 * Get or set v:throwpoint. If "oldval" == NULL, return the current value.
10418 * Otherwise, restore the value to "oldval" and return NULL.
10419 * Must always be called in pairs to save and restore v:throwpoint! Does not
10420 * take care of memory allocations.
10421 */
10422 char_u *
10423v_throwpoint(oldval)
10424 char_u *oldval;
10425{
10426 if (oldval == NULL)
10427 return vimvars[VV_THROWPOINT].val;
10428
10429 vimvars[VV_THROWPOINT].val = oldval;
10430 return NULL;
10431}
10432
10433#if defined(FEAT_AUTOCMD) || defined(PROTO)
10434/*
10435 * Set v:cmdarg.
10436 * If "eap" != NULL, use "eap" to generate the value and return the old value.
10437 * If "oldarg" != NULL, restore the value to "oldarg" and return NULL.
10438 * Must always be called in pairs!
10439 */
10440 char_u *
10441set_cmdarg(eap, oldarg)
10442 exarg_T *eap;
10443 char_u *oldarg;
10444{
10445 char_u *oldval;
10446 char_u *newval;
10447 unsigned len;
10448
10449 oldval = vimvars[VV_CMDARG].val;
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +000010450 if (eap == NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000010451 {
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +000010452 vim_free(oldval);
10453 vimvars[VV_CMDARG].val = oldarg;
10454 return NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010455 }
10456
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +000010457 if (eap->force_bin == FORCE_BIN)
10458 len = 6;
10459 else if (eap->force_bin == FORCE_NOBIN)
10460 len = 8;
10461 else
10462 len = 0;
10463 if (eap->force_ff != 0)
10464 len += (unsigned)STRLEN(eap->cmd + eap->force_ff) + 6;
10465# ifdef FEAT_MBYTE
10466 if (eap->force_enc != 0)
10467 len += (unsigned)STRLEN(eap->cmd + eap->force_enc) + 7;
10468# endif
10469
10470 newval = alloc(len + 1);
10471 if (newval == NULL)
10472 return NULL;
10473
10474 if (eap->force_bin == FORCE_BIN)
10475 sprintf((char *)newval, " ++bin");
10476 else if (eap->force_bin == FORCE_NOBIN)
10477 sprintf((char *)newval, " ++nobin");
10478 else
10479 *newval = NUL;
10480 if (eap->force_ff != 0)
10481 sprintf((char *)newval + STRLEN(newval), " ++ff=%s",
10482 eap->cmd + eap->force_ff);
10483# ifdef FEAT_MBYTE
10484 if (eap->force_enc != 0)
10485 sprintf((char *)newval + STRLEN(newval), " ++enc=%s",
10486 eap->cmd + eap->force_enc);
10487# endif
10488 vimvars[VV_CMDARG].val = newval;
10489 return oldval;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010490}
10491#endif
10492
10493/*
10494 * Get the value of internal variable "name".
10495 * Return OK or FAIL.
10496 */
10497 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010498get_var_tv(name, len, rettv)
Bram Moolenaar071d4272004-06-13 20:20:40 +000010499 char_u *name;
10500 int len; /* length of "name" */
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010501 typeval *rettv; /* NULL when only checking existence */
Bram Moolenaar071d4272004-06-13 20:20:40 +000010502{
10503 int ret = OK;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010504 typeval tv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010505 VAR v;
10506 int cc;
10507 int i;
10508
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010509 tv.v_type = VAR_UNKNOWN;
10510
Bram Moolenaar071d4272004-06-13 20:20:40 +000010511 /* truncate the name, so that we can use strcmp() */
10512 cc = name[len];
10513 name[len] = NUL;
10514
10515 /*
10516 * Check for "b:changedtick".
10517 */
10518 if (STRCMP(name, "b:changedtick") == 0)
10519 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010520 tv.v_type = VAR_NUMBER;
10521 tv.vval.v_number = curbuf->b_changedtick;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010522 }
10523
10524 /*
10525 * Check for built-in v: variables.
10526 */
10527 else if ((i = find_vim_var(name, len)) >= 0)
10528 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010529 tv.v_type = vimvars[i].type;
10530 if (tv.v_type == VAR_NUMBER)
10531 tv.vval.v_number = (long)vimvars[i].val;
10532 else
10533 tv.vval.v_string = vimvars[i].val;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010534 }
10535
10536 /*
10537 * Check for user-defined variables.
10538 */
10539 else
10540 {
10541 v = find_var(name, FALSE);
10542 if (v != NULL)
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010543 tv = v->tv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010544 }
10545
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010546 if (tv.v_type == VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +000010547 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010548 if (rettv != NULL)
10549 EMSG2(_(e_undefvar), name);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010550 ret = FAIL;
10551 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010552 else if (rettv != NULL)
10553 copy_tv(&tv, rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010554
10555 name[len] = cc;
10556
10557 return ret;
10558}
10559
10560/*
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010561 * Allocate memory for a variable type-value, and make it emtpy (0 or NULL
10562 * value).
10563 */
10564 static typeval *
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010565alloc_tv()
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010566{
10567 return (typeval *)alloc_clear((unsigned)sizeof(typeval));
10568}
10569
10570/*
10571 * Allocate memory for a variable type-value, and assign a string to it.
Bram Moolenaar071d4272004-06-13 20:20:40 +000010572 * The string "s" must have been allocated, it is consumed.
10573 * Return NULL for out of memory, the variable otherwise.
10574 */
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010575 static typeval *
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010576alloc_string_tv(s)
Bram Moolenaar071d4272004-06-13 20:20:40 +000010577 char_u *s;
10578{
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010579 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010580
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010581 rettv = alloc_tv();
10582 if (rettv != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000010583 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010584 rettv->v_type = VAR_STRING;
10585 rettv->vval.v_string = s;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010586 }
10587 else
10588 vim_free(s);
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010589 return rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010590}
10591
10592/*
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010593 * Free the memory for a variable type-value.
Bram Moolenaar071d4272004-06-13 20:20:40 +000010594 */
10595 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010596free_tv(varp)
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010597 typeval *varp;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010598{
10599 if (varp != NULL)
10600 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010601 switch (varp->v_type)
10602 {
10603 case VAR_STRING:
10604 case VAR_FUNC:
10605 vim_free(varp->vval.v_string);
10606 break;
10607 case VAR_LIST:
10608 list_unref(varp->vval.v_list);
10609 break;
10610 default:
10611 break;
10612 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000010613 vim_free(varp);
10614 }
10615}
10616
10617/*
10618 * Free the memory for a variable value and set the value to NULL or 0.
10619 */
10620 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010621clear_tv(varp)
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010622 typeval *varp;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010623{
10624 if (varp != NULL)
10625 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010626 switch (varp->v_type)
Bram Moolenaar071d4272004-06-13 20:20:40 +000010627 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010628 case VAR_STRING:
10629 case VAR_FUNC:
10630 vim_free(varp->vval.v_string);
10631 varp->vval.v_string = NULL;
10632 break;
10633 case VAR_LIST:
10634 list_unref(varp->vval.v_list);
10635 break;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010636 case VAR_NUMBER:
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010637 varp->vval.v_number = 0;
10638 break;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010639 case VAR_UNKNOWN:
10640 break;
10641 default:
10642 EMSG2(_(e_intern2), "clear_tv()");
Bram Moolenaar071d4272004-06-13 20:20:40 +000010643 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000010644 }
10645}
10646
10647/*
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010648 * Set the value of a variable to NULL without freeing items.
10649 */
10650 static void
10651init_tv(varp)
10652 typeval *varp;
10653{
10654 if (varp != NULL)
10655 vim_memset(varp, 0, sizeof(typeval));
10656}
10657
10658/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000010659 * Get the number value of a variable.
10660 * If it is a String variable, uses vim_str2nr().
10661 */
10662 static long
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010663get_tv_number(varp)
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010664 typeval *varp;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010665{
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010666 long n = 0L;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010667
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010668 switch (varp->v_type)
Bram Moolenaar071d4272004-06-13 20:20:40 +000010669 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010670 case VAR_NUMBER:
10671 n = (long)(varp->vval.v_number);
10672 break;
10673 case VAR_FUNC:
10674 EMSG(_("E999: Using function reference as a number"));
10675 break;
10676 case VAR_STRING:
10677 if (varp->vval.v_string != NULL)
10678 vim_str2nr(varp->vval.v_string, NULL, NULL,
10679 TRUE, TRUE, &n, NULL);
10680 break;
10681 default:
10682 break;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010683 }
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010684 return n;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010685}
10686
10687/*
10688 * Get the lnum from the first argument. Also accepts ".", "$", etc.
10689 */
10690 static linenr_T
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010691get_tv_lnum(argvars)
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010692 typeval *argvars;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010693{
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010694 typeval rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010695 linenr_T lnum;
10696
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010697 lnum = get_tv_number(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010698 if (lnum == 0) /* no valid number, try using line() */
10699 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010700 rettv.v_type = VAR_NUMBER;
10701 f_line(argvars, &rettv);
10702 lnum = rettv.vval.v_number;
10703 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010704 }
10705 return lnum;
10706}
10707
10708/*
10709 * Get the string value of a variable.
10710 * If it is a Number variable, the number is converted into a string.
10711 * get_var_string() uses a single, static buffer. YOU CAN ONLY USE IT ONCE!
10712 * get_var_string_buf() uses a given buffer.
10713 * If the String variable has never been set, return an empty string.
10714 * Never returns NULL;
10715 */
10716 static char_u *
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010717get_tv_string(varp)
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010718 typeval *varp;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010719{
10720 static char_u mybuf[NUMBUFLEN];
10721
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010722 return get_tv_string_buf(varp, mybuf);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010723}
10724
10725 static char_u *
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010726get_tv_string_buf(varp, buf)
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010727 typeval *varp;
10728 char_u *buf;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010729{
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010730 switch (varp->v_type)
Bram Moolenaar071d4272004-06-13 20:20:40 +000010731 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010732 case VAR_NUMBER:
10733 sprintf((char *)buf, "%ld", (long)varp->vval.v_number);
10734 return buf;
10735 case VAR_FUNC:
10736 EMSG(_("E99: using Funcref as a String"));
10737 break;
10738 case VAR_LIST:
10739 EMSG(_("E99: using List as a String"));
10740 break;
10741 case VAR_STRING:
10742 if (varp->vval.v_string != NULL)
10743 return varp->vval.v_string;
10744 break;
10745 default:
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010746 EMSG2(_(e_intern2), "get_tv_string_buf()");
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010747 break;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010748 }
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010749 return (char_u *)"";
Bram Moolenaar071d4272004-06-13 20:20:40 +000010750}
10751
10752/*
10753 * Find variable "name" in the list of variables.
10754 * Return a pointer to it if found, NULL if not found.
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010755 * Careful: "a:0" variables don't have a name.
Bram Moolenaar071d4272004-06-13 20:20:40 +000010756 */
10757 static VAR
10758find_var(name, writing)
10759 char_u *name;
10760 int writing;
10761{
10762 int i;
10763 char_u *varname;
10764 garray_T *gap;
10765
Bram Moolenaar071d4272004-06-13 20:20:40 +000010766 if (name[0] == 'a' && name[1] == ':')
10767 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010768 /* Function arguments "a:".
10769 * NOTE: We use a typecast, because function arguments don't have a
10770 * name. The caller must not try to access the name! */
Bram Moolenaar071d4272004-06-13 20:20:40 +000010771 if (writing)
10772 {
10773 EMSG2(_(e_readonlyvar), name);
10774 return NULL;
10775 }
10776 name += 2;
10777 if (current_funccal == NULL)
10778 return NULL;
10779 if (VIM_ISDIGIT(*name))
10780 {
10781 i = atol((char *)name);
10782 if (i == 0) /* a:0 */
10783 return &current_funccal->a0_var;
10784 i += current_funccal->func->args.ga_len;
10785 if (i > current_funccal->argcount) /* a:999 */
10786 return NULL;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010787 return (VAR)&(current_funccal->argvars[i - 1]); /* a:1, a:2, etc. */
Bram Moolenaar071d4272004-06-13 20:20:40 +000010788 }
10789 if (STRCMP(name, "firstline") == 0)
10790 return &(current_funccal->firstline);
10791 if (STRCMP(name, "lastline") == 0)
10792 return &(current_funccal->lastline);
10793 for (i = 0; i < current_funccal->func->args.ga_len; ++i)
10794 if (STRCMP(name, ((char_u **)
10795 (current_funccal->func->args.ga_data))[i]) == 0)
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010796 return (VAR)&(current_funccal->argvars[i]); /* a:name */
Bram Moolenaar071d4272004-06-13 20:20:40 +000010797 return NULL;
10798 }
10799
10800 gap = find_var_ga(name, &varname);
10801 if (gap == NULL)
10802 return NULL;
10803 return find_var_in_ga(gap, varname);
10804}
10805
10806 static VAR
10807find_var_in_ga(gap, varname)
10808 garray_T *gap;
10809 char_u *varname;
10810{
10811 int i;
10812
10813 for (i = gap->ga_len; --i >= 0; )
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010814 if (VAR_GAP_ENTRY(i, gap).v_name != NULL
10815 && STRCMP(VAR_GAP_ENTRY(i, gap).v_name, varname) == 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +000010816 break;
10817 if (i < 0)
10818 return NULL;
10819 return &VAR_GAP_ENTRY(i, gap);
10820}
10821
10822/*
10823 * Find the growarray and start of name without ':' for a variable name.
10824 */
10825 static garray_T *
10826find_var_ga(name, varname)
10827 char_u *name;
10828 char_u **varname;
10829{
10830 if (name[1] != ':')
10831 {
10832 /* If not "x:name" there must not be any ":" in the name. */
10833 if (vim_strchr(name, ':') != NULL)
10834 return NULL;
10835 *varname = name;
10836 if (current_funccal == NULL)
10837 return &variables; /* global variable */
10838 return &current_funccal->l_vars; /* local function variable */
10839 }
10840 *varname = name + 2;
10841 if (*name == 'b') /* buffer variable */
10842 return &curbuf->b_vars;
10843 if (*name == 'w') /* window variable */
10844 return &curwin->w_vars;
10845 if (*name == 'g') /* global variable */
10846 return &variables;
10847 if (*name == 'l' && current_funccal != NULL)/* local function variable */
10848 return &current_funccal->l_vars;
10849 if (*name == 's' /* script variable */
10850 && current_SID > 0 && current_SID <= ga_scripts.ga_len)
10851 return &SCRIPT_VARS(current_SID);
10852 return NULL;
10853}
10854
10855/*
10856 * Get the string value of a (global/local) variable.
10857 * Returns NULL when it doesn't exist.
10858 */
10859 char_u *
10860get_var_value(name)
10861 char_u *name;
10862{
10863 VAR v;
10864
10865 v = find_var(name, FALSE);
10866 if (v == NULL)
10867 return NULL;
10868 return get_var_string(v);
10869}
10870
10871/*
10872 * Allocate a new growarry for a sourced script. It will be used while
10873 * sourcing this script and when executing functions defined in the script.
10874 */
10875 void
10876new_script_vars(id)
10877 scid_T id;
10878{
10879 if (ga_grow(&ga_scripts, (int)(id - ga_scripts.ga_len)) == OK)
10880 {
10881 while (ga_scripts.ga_len < id)
10882 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010883 vars_init(&SCRIPT_VARS(ga_scripts.ga_len + 1));
Bram Moolenaar071d4272004-06-13 20:20:40 +000010884 ++ga_scripts.ga_len;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010885 }
10886 }
10887}
10888
10889/*
10890 * Initialize internal variables for use.
10891 */
10892 void
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010893vars_init(gap)
Bram Moolenaar071d4272004-06-13 20:20:40 +000010894 garray_T *gap;
10895{
10896 ga_init2(gap, (int)sizeof(var), 4);
10897}
10898
10899/*
10900 * Clean up a list of internal variables.
10901 */
10902 void
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010903vars_clear(gap)
Bram Moolenaar071d4272004-06-13 20:20:40 +000010904 garray_T *gap;
10905{
10906 int i;
10907
10908 for (i = gap->ga_len; --i >= 0; )
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010909 clear_var(&VAR_GAP_ENTRY(i, gap));
Bram Moolenaar071d4272004-06-13 20:20:40 +000010910 ga_clear(gap);
10911}
10912
10913 static void
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010914clear_var(v)
Bram Moolenaar071d4272004-06-13 20:20:40 +000010915 VAR v;
10916{
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010917 vim_free(v->v_name);
10918 v->v_name = NULL;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010919 clear_tv(&v->tv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010920}
10921
10922/*
10923 * List the value of one internal variable.
10924 */
10925 static void
10926list_one_var(v, prefix)
10927 VAR v;
10928 char_u *prefix;
10929{
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010930 char_u *tofree;
10931 char_u *s;
Bram Moolenaar8a283e52005-01-06 23:28:25 +000010932 char_u numbuf[NUMBUFLEN];
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010933
Bram Moolenaar8a283e52005-01-06 23:28:25 +000010934 s = tv2string(&v->tv, &tofree, numbuf);
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010935 list_one_var_a(prefix, v->v_name, v->tv.v_type,
10936 s == NULL ? (char_u *)"" : s);
10937 vim_free(tofree);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010938}
10939
10940/*
10941 * List the value of one "v:" variable.
10942 */
10943 static void
10944list_vim_var(i)
10945 int i; /* index in vimvars[] */
10946{
10947 char_u *p;
10948 char_u numbuf[NUMBUFLEN];
10949
10950 if (vimvars[i].type == VAR_NUMBER)
10951 {
10952 p = numbuf;
10953 sprintf((char *)p, "%ld", (long)vimvars[i].val);
10954 }
10955 else if (vimvars[i].val == NULL)
10956 p = (char_u *)"";
10957 else
10958 p = vimvars[i].val;
10959 list_one_var_a((char_u *)"v:", (char_u *)vimvars[i].name,
10960 vimvars[i].type, p);
10961}
10962
10963 static void
10964list_one_var_a(prefix, name, type, string)
10965 char_u *prefix;
10966 char_u *name;
10967 int type;
10968 char_u *string;
10969{
10970 msg_attr(prefix, 0); /* don't use msg(), it overwrites "v:statusmsg" */
10971 if (name != NULL) /* "a:" vars don't have a name stored */
10972 msg_puts(name);
10973 msg_putchar(' ');
10974 msg_advance(22);
10975 if (type == VAR_NUMBER)
10976 msg_putchar('#');
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010977 else if (type == VAR_FUNC)
10978 msg_putchar('*');
10979 else if (type == VAR_LIST)
10980 {
10981 msg_putchar('[');
10982 if (*string == '[')
10983 ++string;
10984 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000010985 else
10986 msg_putchar(' ');
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010987
Bram Moolenaar071d4272004-06-13 20:20:40 +000010988 msg_outtrans(string);
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010989
10990 if (type == VAR_FUNC)
10991 msg_puts((char_u *)"()");
Bram Moolenaar071d4272004-06-13 20:20:40 +000010992}
10993
10994/*
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010995 * Set variable "name" to value in "tv".
Bram Moolenaar071d4272004-06-13 20:20:40 +000010996 * If the variable already exists, the value is updated.
10997 * Otherwise the variable is created.
10998 */
10999 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011000set_var(name, tv, copy)
Bram Moolenaar071d4272004-06-13 20:20:40 +000011001 char_u *name;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011002 typeval *tv;
11003 int copy; /* make copy of value in "tv" */
Bram Moolenaar071d4272004-06-13 20:20:40 +000011004{
11005 int i;
11006 VAR v;
11007 char_u *varname;
11008 garray_T *gap;
11009
11010 /*
11011 * Handle setting internal v: variables.
11012 */
11013 i = find_vim_var(name, (int)STRLEN(name));
11014 if (i >= 0)
11015 {
11016 if (vimvars[i].flags & VV_RO)
11017 EMSG2(_(e_readonlyvar), name);
Bram Moolenaar7b0294c2004-10-11 10:16:09 +000011018 else if ((vimvars[i].flags & VV_RO_SBX) && sandbox)
11019 EMSG2(_(e_readonlysbx), name);
Bram Moolenaar071d4272004-06-13 20:20:40 +000011020 else
11021 {
11022 if (vimvars[i].type == VAR_STRING)
11023 {
11024 vim_free(vimvars[i].val);
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011025 if (copy || tv->v_type != VAR_STRING)
11026 vimvars[i].val = vim_strsave(get_tv_string(tv));
Bram Moolenaar1c2fda22005-01-02 11:43:19 +000011027 else
11028 {
11029 /* Take over the string to avoid an extra alloc/free. */
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011030 vimvars[i].val = tv->vval.v_string;
11031 tv->vval.v_string = NULL;
Bram Moolenaar1c2fda22005-01-02 11:43:19 +000011032 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000011033 }
11034 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011035 vimvars[i].val = (char_u *)get_tv_number(tv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000011036 }
11037 return;
11038 }
11039
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011040 if (tv->v_type == VAR_FUNC)
Bram Moolenaar49cd9572005-01-03 21:06:01 +000011041 {
11042 if (!(vim_strchr((char_u *)"wbs", name[0]) != NULL && name[1] == ':')
11043 && !ASCII_ISUPPER((name[0] != NUL && name[1] == ':')
11044 ? name[2] : name[0]))
11045 {
11046 EMSG2(_("E999: Funcref variable name must start with a capital: %s"), name);
11047 return;
11048 }
11049 if (function_exists(name))
11050 {
11051 EMSG2(_("E999: Variable name conflicts with existing function: %s"), name);
11052 return;
11053 }
11054 }
11055
Bram Moolenaar071d4272004-06-13 20:20:40 +000011056 v = find_var(name, TRUE);
11057 if (v != NULL) /* existing variable, only need to free string */
11058 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011059 if (v->tv.v_type != tv->v_type
Bram Moolenaar49cd9572005-01-03 21:06:01 +000011060 && !((v->tv.v_type == VAR_STRING
11061 || v->tv.v_type == VAR_NUMBER)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011062 && (tv->v_type == VAR_STRING
11063 || tv->v_type == VAR_NUMBER)))
Bram Moolenaar49cd9572005-01-03 21:06:01 +000011064 {
11065 EMSG2(_("E999: Variable type mismatch for: %s"), name);
11066 return;
11067 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011068 clear_tv(&v->tv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000011069 }
11070 else /* add a new variable */
11071 {
11072 gap = find_var_ga(name, &varname);
11073 if (gap == NULL) /* illegal name */
11074 {
11075 EMSG2(_("E461: Illegal variable name: %s"), name);
11076 return;
11077 }
11078
11079 /* Try to use an empty entry */
11080 for (i = gap->ga_len; --i >= 0; )
Bram Moolenaar49cd9572005-01-03 21:06:01 +000011081 if (VAR_GAP_ENTRY(i, gap).v_name == NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000011082 break;
11083 if (i < 0) /* need to allocate more room */
11084 {
11085 if (ga_grow(gap, 1) == FAIL)
11086 return;
11087 i = gap->ga_len;
11088 }
11089 v = &VAR_GAP_ENTRY(i, gap);
Bram Moolenaar49cd9572005-01-03 21:06:01 +000011090 if ((v->v_name = vim_strsave(varname)) == NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000011091 return;
11092 if (i == gap->ga_len)
Bram Moolenaar071d4272004-06-13 20:20:40 +000011093 ++gap->ga_len;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011094 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011095 if (copy || tv->v_type == VAR_NUMBER)
11096 copy_tv(tv, &v->tv);
Bram Moolenaar1c2fda22005-01-02 11:43:19 +000011097 else
11098 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011099 v->tv = *tv;
11100 init_tv(tv);
Bram Moolenaar1c2fda22005-01-02 11:43:19 +000011101 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000011102}
11103
Bram Moolenaar49cd9572005-01-03 21:06:01 +000011104/*
11105 * Copy the values from typeval "from" to typeval "to".
11106 * When needed allocates string or increases reference count.
11107 * Does not make a copy of a list!
11108 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000011109 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011110copy_tv(from, to)
Bram Moolenaar49cd9572005-01-03 21:06:01 +000011111 typeval *from;
11112 typeval *to;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011113{
Bram Moolenaar49cd9572005-01-03 21:06:01 +000011114 to->v_type = from->v_type;
11115 switch (from->v_type)
11116 {
11117 case VAR_NUMBER:
11118 to->vval.v_number = from->vval.v_number;
11119 break;
11120 case VAR_STRING:
11121 case VAR_FUNC:
11122 if (from->vval.v_string == NULL)
11123 to->vval.v_string = NULL;
11124 else
11125 to->vval.v_string = vim_strsave(from->vval.v_string);
11126 break;
11127 case VAR_LIST:
11128 if (from->vval.v_list == NULL)
11129 to->vval.v_list = NULL;
11130 else
11131 {
11132 to->vval.v_list = from->vval.v_list;
11133 ++to->vval.v_list->lv_refcount;
11134 }
11135 break;
11136 default:
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011137 EMSG2(_(e_intern2), "copy_tv()");
Bram Moolenaar49cd9572005-01-03 21:06:01 +000011138 break;
11139 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000011140}
11141
11142/*
11143 * ":echo expr1 ..." print each argument separated with a space, add a
11144 * newline at the end.
11145 * ":echon expr1 ..." print each argument plain.
11146 */
11147 void
11148ex_echo(eap)
11149 exarg_T *eap;
11150{
11151 char_u *arg = eap->arg;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011152 typeval rettv;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000011153 char_u *tofree;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011154 char_u *p;
11155 int needclr = TRUE;
11156 int atstart = TRUE;
Bram Moolenaar8a283e52005-01-06 23:28:25 +000011157 char_u numbuf[NUMBUFLEN];
Bram Moolenaar071d4272004-06-13 20:20:40 +000011158
11159 if (eap->skip)
11160 ++emsg_skip;
11161 while (*arg != NUL && *arg != '|' && *arg != '\n' && !got_int)
11162 {
11163 p = arg;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011164 if (eval1(&arg, &rettv, !eap->skip) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000011165 {
11166 /*
11167 * Report the invalid expression unless the expression evaluation
11168 * has been cancelled due to an aborting error, an interrupt, or an
11169 * exception.
11170 */
11171 if (!aborting())
11172 EMSG2(_(e_invexpr2), p);
11173 break;
11174 }
11175 if (!eap->skip)
11176 {
11177 if (atstart)
11178 {
11179 atstart = FALSE;
11180 /* Call msg_start() after eval1(), evaluating the expression
11181 * may cause a message to appear. */
11182 if (eap->cmdidx == CMD_echo)
11183 msg_start();
11184 }
11185 else if (eap->cmdidx == CMD_echo)
11186 msg_puts_attr((char_u *)" ", echo_attr);
Bram Moolenaar8a283e52005-01-06 23:28:25 +000011187 for (p = tv2string(&rettv, &tofree, numbuf);
11188 *p != NUL && !got_int; ++p)
Bram Moolenaar071d4272004-06-13 20:20:40 +000011189 if (*p == '\n' || *p == '\r' || *p == TAB)
11190 {
11191 if (*p != TAB && needclr)
11192 {
11193 /* remove any text still there from the command */
11194 msg_clr_eos();
11195 needclr = FALSE;
11196 }
11197 msg_putchar_attr(*p, echo_attr);
11198 }
11199 else
11200 {
11201#ifdef FEAT_MBYTE
11202 if (has_mbyte)
11203 {
11204 int i = (*mb_ptr2len_check)(p);
11205
11206 (void)msg_outtrans_len_attr(p, i, echo_attr);
11207 p += i - 1;
11208 }
11209 else
11210#endif
11211 (void)msg_outtrans_len_attr(p, 1, echo_attr);
11212 }
Bram Moolenaar49cd9572005-01-03 21:06:01 +000011213 vim_free(tofree);
Bram Moolenaar071d4272004-06-13 20:20:40 +000011214 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011215 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000011216 arg = skipwhite(arg);
11217 }
11218 eap->nextcmd = check_nextcmd(arg);
11219
11220 if (eap->skip)
11221 --emsg_skip;
11222 else
11223 {
11224 /* remove text that may still be there from the command */
11225 if (needclr)
11226 msg_clr_eos();
11227 if (eap->cmdidx == CMD_echo)
11228 msg_end();
11229 }
11230}
11231
11232/*
11233 * ":echohl {name}".
11234 */
11235 void
11236ex_echohl(eap)
11237 exarg_T *eap;
11238{
11239 int id;
11240
11241 id = syn_name2id(eap->arg);
11242 if (id == 0)
11243 echo_attr = 0;
11244 else
11245 echo_attr = syn_id2attr(id);
11246}
11247
11248/*
11249 * ":execute expr1 ..." execute the result of an expression.
11250 * ":echomsg expr1 ..." Print a message
11251 * ":echoerr expr1 ..." Print an error
11252 * Each gets spaces around each argument and a newline at the end for
11253 * echo commands
11254 */
11255 void
11256ex_execute(eap)
11257 exarg_T *eap;
11258{
11259 char_u *arg = eap->arg;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011260 typeval rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011261 int ret = OK;
11262 char_u *p;
11263 garray_T ga;
11264 int len;
11265 int save_did_emsg;
11266
11267 ga_init2(&ga, 1, 80);
11268
11269 if (eap->skip)
11270 ++emsg_skip;
11271 while (*arg != NUL && *arg != '|' && *arg != '\n')
11272 {
11273 p = arg;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011274 if (eval1(&arg, &rettv, !eap->skip) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000011275 {
11276 /*
11277 * Report the invalid expression unless the expression evaluation
11278 * has been cancelled due to an aborting error, an interrupt, or an
11279 * exception.
11280 */
11281 if (!aborting())
11282 EMSG2(_(e_invexpr2), p);
11283 ret = FAIL;
11284 break;
11285 }
11286
11287 if (!eap->skip)
11288 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011289 p = get_tv_string(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000011290 len = (int)STRLEN(p);
11291 if (ga_grow(&ga, len + 2) == FAIL)
11292 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011293 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000011294 ret = FAIL;
11295 break;
11296 }
11297 if (ga.ga_len)
Bram Moolenaar071d4272004-06-13 20:20:40 +000011298 ((char_u *)(ga.ga_data))[ga.ga_len++] = ' ';
Bram Moolenaar071d4272004-06-13 20:20:40 +000011299 STRCPY((char_u *)(ga.ga_data) + ga.ga_len, p);
Bram Moolenaar071d4272004-06-13 20:20:40 +000011300 ga.ga_len += len;
11301 }
11302
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011303 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000011304 arg = skipwhite(arg);
11305 }
11306
11307 if (ret != FAIL && ga.ga_data != NULL)
11308 {
11309 if (eap->cmdidx == CMD_echomsg)
11310 MSG_ATTR(ga.ga_data, echo_attr);
11311 else if (eap->cmdidx == CMD_echoerr)
11312 {
11313 /* We don't want to abort following commands, restore did_emsg. */
11314 save_did_emsg = did_emsg;
11315 EMSG((char_u *)ga.ga_data);
11316 if (!force_abort)
11317 did_emsg = save_did_emsg;
11318 }
11319 else if (eap->cmdidx == CMD_execute)
11320 do_cmdline((char_u *)ga.ga_data,
11321 eap->getline, eap->cookie, DOCMD_NOWAIT|DOCMD_VERBOSE);
11322 }
11323
11324 ga_clear(&ga);
11325
11326 if (eap->skip)
11327 --emsg_skip;
11328
11329 eap->nextcmd = check_nextcmd(arg);
11330}
11331
11332/*
11333 * Skip over the name of an option: "&option", "&g:option" or "&l:option".
11334 * "arg" points to the "&" or '+' when called, to "option" when returning.
11335 * Returns NULL when no option name found. Otherwise pointer to the char
11336 * after the option name.
11337 */
11338 static char_u *
11339find_option_end(arg, opt_flags)
11340 char_u **arg;
11341 int *opt_flags;
11342{
11343 char_u *p = *arg;
11344
11345 ++p;
11346 if (*p == 'g' && p[1] == ':')
11347 {
11348 *opt_flags = OPT_GLOBAL;
11349 p += 2;
11350 }
11351 else if (*p == 'l' && p[1] == ':')
11352 {
11353 *opt_flags = OPT_LOCAL;
11354 p += 2;
11355 }
11356 else
11357 *opt_flags = 0;
11358
11359 if (!ASCII_ISALPHA(*p))
11360 return NULL;
11361 *arg = p;
11362
11363 if (p[0] == 't' && p[1] == '_' && p[2] != NUL && p[3] != NUL)
11364 p += 4; /* termcap option */
11365 else
11366 while (ASCII_ISALPHA(*p))
11367 ++p;
11368 return p;
11369}
11370
11371/*
11372 * ":function"
11373 */
11374 void
11375ex_function(eap)
11376 exarg_T *eap;
11377{
11378 char_u *theline;
11379 int j;
11380 int c;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011381 int saved_did_emsg;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011382 char_u *name = NULL;
11383 char_u *p;
11384 char_u *arg;
11385 garray_T newargs;
11386 garray_T newlines;
11387 int varargs = FALSE;
11388 int mustend = FALSE;
11389 int flags = 0;
11390 ufunc_T *fp;
11391 int indent;
11392 int nesting;
11393 char_u *skip_until = NULL;
11394 static char_u e_funcexts[] = N_("E122: Function %s already exists, add ! to replace it");
Bram Moolenaar49cd9572005-01-03 21:06:01 +000011395 VAR v;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011396
11397 /*
11398 * ":function" without argument: list functions.
11399 */
11400 if (ends_excmd(*eap->arg))
11401 {
11402 if (!eap->skip)
11403 for (fp = firstfunc; fp != NULL && !got_int; fp = fp->next)
11404 list_func_head(fp, FALSE);
11405 eap->nextcmd = check_nextcmd(eap->arg);
11406 return;
11407 }
11408
11409 p = eap->arg;
11410 name = trans_function_name(&p, eap->skip, FALSE);
11411 if (name == NULL && !eap->skip)
11412 {
11413 /*
11414 * Return on an invalid expression in braces, unless the expression
11415 * evaluation has been cancelled due to an aborting error, an
11416 * interrupt, or an exception.
11417 */
11418 if (!aborting())
11419 return;
11420 else
11421 eap->skip = TRUE;
11422 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000011423 /* An error in a function call during evaluation of an expression in magic
11424 * braces should not cause the function not to be defined. */
11425 saved_did_emsg = did_emsg;
11426 did_emsg = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011427
11428 /*
11429 * ":function func" with only function name: list function.
11430 */
11431 if (vim_strchr(p, '(') == NULL)
11432 {
11433 if (!ends_excmd(*skipwhite(p)))
11434 {
11435 EMSG(_(e_trailing));
11436 goto erret_name;
11437 }
11438 eap->nextcmd = check_nextcmd(p);
11439 if (eap->nextcmd != NULL)
11440 *p = NUL;
11441 if (!eap->skip && !got_int)
11442 {
11443 fp = find_func(name);
11444 if (fp != NULL)
11445 {
11446 list_func_head(fp, TRUE);
11447 for (j = 0; j < fp->lines.ga_len && !got_int; ++j)
11448 {
11449 msg_putchar('\n');
11450 msg_outnum((long)(j + 1));
11451 if (j < 9)
11452 msg_putchar(' ');
11453 if (j < 99)
11454 msg_putchar(' ');
11455 msg_prt_line(FUNCLINE(fp, j));
11456 out_flush(); /* show a line at a time */
11457 ui_breakcheck();
11458 }
11459 if (!got_int)
11460 {
11461 msg_putchar('\n');
11462 msg_puts((char_u *)" endfunction");
11463 }
11464 }
11465 else
11466 EMSG2(_("E123: Undefined function: %s"), eap->arg);
11467 }
11468 goto erret_name;
11469 }
11470
11471 /*
11472 * ":function name(arg1, arg2)" Define function.
11473 */
11474 p = skipwhite(p);
11475 if (*p != '(')
11476 {
11477 if (!eap->skip)
11478 {
11479 EMSG2(_("E124: Missing '(': %s"), eap->arg);
11480 goto erret_name;
11481 }
11482 /* attempt to continue by skipping some text */
11483 if (vim_strchr(p, '(') != NULL)
11484 p = vim_strchr(p, '(');
11485 }
11486 p = skipwhite(p + 1);
11487
11488 ga_init2(&newargs, (int)sizeof(char_u *), 3);
11489 ga_init2(&newlines, (int)sizeof(char_u *), 3);
11490
11491 /*
11492 * Isolate the arguments: "arg1, arg2, ...)"
11493 */
11494 while (*p != ')')
11495 {
11496 if (p[0] == '.' && p[1] == '.' && p[2] == '.')
11497 {
11498 varargs = TRUE;
11499 p += 3;
11500 mustend = TRUE;
11501 }
11502 else
11503 {
11504 arg = p;
11505 while (ASCII_ISALNUM(*p) || *p == '_')
11506 ++p;
11507 if (arg == p || isdigit(*arg)
11508 || (p - arg == 9 && STRNCMP(arg, "firstline", 9) == 0)
11509 || (p - arg == 8 && STRNCMP(arg, "lastline", 8) == 0))
11510 {
11511 if (!eap->skip)
11512 EMSG2(_("E125: Illegal argument: %s"), arg);
11513 break;
11514 }
11515 if (ga_grow(&newargs, 1) == FAIL)
11516 goto erret;
11517 c = *p;
11518 *p = NUL;
11519 arg = vim_strsave(arg);
11520 if (arg == NULL)
11521 goto erret;
11522 ((char_u **)(newargs.ga_data))[newargs.ga_len] = arg;
11523 *p = c;
11524 newargs.ga_len++;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011525 if (*p == ',')
11526 ++p;
11527 else
11528 mustend = TRUE;
11529 }
11530 p = skipwhite(p);
11531 if (mustend && *p != ')')
11532 {
11533 if (!eap->skip)
11534 EMSG2(_(e_invarg2), eap->arg);
11535 break;
11536 }
11537 }
11538 ++p; /* skip the ')' */
11539
11540 /* find extra arguments "range" and "abort" */
11541 for (;;)
11542 {
11543 p = skipwhite(p);
11544 if (STRNCMP(p, "range", 5) == 0)
11545 {
11546 flags |= FC_RANGE;
11547 p += 5;
11548 }
11549 else if (STRNCMP(p, "abort", 5) == 0)
11550 {
11551 flags |= FC_ABORT;
11552 p += 5;
11553 }
11554 else
11555 break;
11556 }
11557
11558 if (*p != NUL && *p != '"' && *p != '\n' && !eap->skip && !did_emsg)
11559 EMSG(_(e_trailing));
11560
11561 /*
11562 * Read the body of the function, until ":endfunction" is found.
11563 */
11564 if (KeyTyped)
11565 {
11566 /* Check if the function already exists, don't let the user type the
11567 * whole function before telling him it doesn't work! For a script we
11568 * need to skip the body to be able to find what follows. */
11569 if (!eap->skip && !eap->forceit && find_func(name) != NULL)
11570 EMSG2(_(e_funcexts), name);
11571
11572 msg_putchar('\n'); /* don't overwrite the function name */
11573 cmdline_row = msg_row;
11574 }
11575
11576 indent = 2;
11577 nesting = 0;
11578 for (;;)
11579 {
11580 msg_scroll = TRUE;
11581 need_wait_return = FALSE;
11582 if (eap->getline == NULL)
11583 theline = getcmdline(':', 0L, indent);
11584 else
11585 theline = eap->getline(':', eap->cookie, indent);
11586 if (KeyTyped)
11587 lines_left = Rows - 1;
11588 if (theline == NULL)
11589 {
11590 EMSG(_("E126: Missing :endfunction"));
11591 goto erret;
11592 }
11593
11594 if (skip_until != NULL)
11595 {
11596 /* between ":append" and "." and between ":python <<EOF" and "EOF"
11597 * don't check for ":endfunc". */
11598 if (STRCMP(theline, skip_until) == 0)
11599 {
11600 vim_free(skip_until);
11601 skip_until = NULL;
11602 }
11603 }
11604 else
11605 {
11606 /* skip ':' and blanks*/
11607 for (p = theline; vim_iswhite(*p) || *p == ':'; ++p)
11608 ;
11609
11610 /* Check for "endfunction" (should be more strict...). */
11611 if (STRNCMP(p, "endf", 4) == 0 && nesting-- == 0)
11612 {
11613 vim_free(theline);
11614 break;
11615 }
11616
11617 /* Increase indent inside "if", "while", and "try", decrease
11618 * at "end". */
11619 if (indent > 2 && STRNCMP(p, "end", 3) == 0)
11620 indent -= 2;
11621 else if (STRNCMP(p, "if", 2) == 0 || STRNCMP(p, "wh", 2) == 0
11622 || STRNCMP(p, "try", 3) == 0)
11623 indent += 2;
11624
11625 /* Check for defining a function inside this function. */
11626 if (STRNCMP(p, "fu", 2) == 0)
11627 {
11628 p = skipwhite(skiptowhite(p));
11629 p += eval_fname_script(p);
11630 if (ASCII_ISALPHA(*p))
11631 {
11632 vim_free(trans_function_name(&p, TRUE, FALSE));
11633 if (*skipwhite(p) == '(')
11634 {
11635 ++nesting;
11636 indent += 2;
11637 }
11638 }
11639 }
11640
11641 /* Check for ":append" or ":insert". */
11642 p = skip_range(p, NULL);
11643 if ((p[0] == 'a' && (!ASCII_ISALPHA(p[1]) || p[1] == 'p'))
11644 || (p[0] == 'i'
11645 && (!ASCII_ISALPHA(p[1]) || (p[1] == 'n'
11646 && (!ASCII_ISALPHA(p[2]) || (p[2] == 's'))))))
11647 skip_until = vim_strsave((char_u *)".");
11648
11649 /* Check for ":python <<EOF", ":tcl <<EOF", etc. */
11650 arg = skipwhite(skiptowhite(p));
11651 if (arg[0] == '<' && arg[1] =='<'
11652 && ((p[0] == 'p' && p[1] == 'y'
11653 && (!ASCII_ISALPHA(p[2]) || p[2] == 't'))
11654 || (p[0] == 'p' && p[1] == 'e'
11655 && (!ASCII_ISALPHA(p[2]) || p[2] == 'r'))
11656 || (p[0] == 't' && p[1] == 'c'
11657 && (!ASCII_ISALPHA(p[2]) || p[2] == 'l'))
11658 || (p[0] == 'r' && p[1] == 'u' && p[2] == 'b'
11659 && (!ASCII_ISALPHA(p[3]) || p[3] == 'y'))
Bram Moolenaar325b7a22004-07-05 15:58:32 +000011660 || (p[0] == 'm' && p[1] == 'z'
11661 && (!ASCII_ISALPHA(p[2]) || p[2] == 's'))
Bram Moolenaar071d4272004-06-13 20:20:40 +000011662 ))
11663 {
11664 /* ":python <<" continues until a dot, like ":append" */
11665 p = skipwhite(arg + 2);
11666 if (*p == NUL)
11667 skip_until = vim_strsave((char_u *)".");
11668 else
11669 skip_until = vim_strsave(p);
11670 }
11671 }
11672
11673 /* Add the line to the function. */
11674 if (ga_grow(&newlines, 1) == FAIL)
11675 goto erret;
11676 ((char_u **)(newlines.ga_data))[newlines.ga_len] = theline;
11677 newlines.ga_len++;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011678 }
11679
11680 /* Don't define the function when skipping commands or when an error was
11681 * detected. */
11682 if (eap->skip || did_emsg)
11683 goto erret;
11684
11685 /*
11686 * If there are no errors, add the function
11687 */
Bram Moolenaar49cd9572005-01-03 21:06:01 +000011688 v = find_var(name, FALSE);
11689 if (v != NULL && v->tv.v_type == VAR_FUNC)
11690 {
11691 EMSG2(_("E999: Function name conflicts with variable: %s"), name);
11692 goto erret;
11693 }
11694
Bram Moolenaar071d4272004-06-13 20:20:40 +000011695 fp = find_func(name);
11696 if (fp != NULL)
11697 {
11698 if (!eap->forceit)
11699 {
11700 EMSG2(_(e_funcexts), name);
11701 goto erret;
11702 }
11703 if (fp->calls)
11704 {
11705 EMSG2(_("E127: Cannot redefine function %s: It is in use"), name);
11706 goto erret;
11707 }
11708 /* redefine existing function */
11709 ga_clear_strings(&(fp->args));
11710 ga_clear_strings(&(fp->lines));
11711 vim_free(name);
11712 }
11713 else
11714 {
11715 fp = (ufunc_T *)alloc((unsigned)sizeof(ufunc_T));
11716 if (fp == NULL)
11717 goto erret;
11718 /* insert the new function in the function list */
11719 fp->next = firstfunc;
11720 firstfunc = fp;
11721 fp->name = name;
11722 }
11723 fp->args = newargs;
11724 fp->lines = newlines;
11725 fp->varargs = varargs;
11726 fp->flags = flags;
11727 fp->calls = 0;
11728 fp->script_ID = current_SID;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011729 did_emsg |= saved_did_emsg;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011730 vim_free(skip_until);
11731 return;
11732
11733erret:
11734 vim_free(skip_until);
11735 ga_clear_strings(&newargs);
11736 ga_clear_strings(&newlines);
11737erret_name:
11738 vim_free(name);
Bram Moolenaar071d4272004-06-13 20:20:40 +000011739 did_emsg |= saved_did_emsg;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011740}
11741
11742/*
11743 * Get a function name, translating "<SID>" and "<SNR>".
11744 * Returns the function name in allocated memory, or NULL for failure.
11745 * Advances "pp" to just after the function name (if no error).
11746 */
11747 static char_u *
11748trans_function_name(pp, skip, internal)
11749 char_u **pp;
11750 int skip; /* only find the end, don't evaluate */
11751 int internal; /* TRUE if internal function name OK */
11752{
11753 char_u *name;
11754 char_u *start;
11755 char_u *end;
11756 int lead;
11757 char_u sid_buf[20];
11758 char_u *temp_string = NULL;
11759 char_u *expr_start, *expr_end;
11760 int len;
11761
11762 /* A name starting with "<SID>" or "<SNR>" is local to a script. */
11763 start = *pp;
11764 lead = eval_fname_script(start);
11765 if (lead > 0)
11766 start += lead;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011767 end = find_name_end(start, &expr_start, &expr_end, FALSE);
Bram Moolenaar071d4272004-06-13 20:20:40 +000011768 if (end == start)
11769 {
11770 if (!skip)
11771 EMSG(_("E129: Function name required"));
11772 return NULL;
11773 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000011774 if (expr_start != NULL && !skip)
11775 {
11776 /* expand magic curlies */
11777 temp_string = make_expanded_name(start, expr_start, expr_end, end);
11778 if (temp_string == NULL)
11779 {
11780 /*
11781 * Report an invalid expression in braces, unless the expression
11782 * evaluation has been cancelled due to an aborting error, an
11783 * interrupt, or an exception.
11784 */
11785 if (!aborting())
11786 EMSG2(_(e_invarg2), start);
11787 else
11788 *pp = end;
11789 return NULL;
11790 }
11791 start = temp_string;
11792 len = (int)STRLEN(temp_string);
11793 }
11794 else
Bram Moolenaar071d4272004-06-13 20:20:40 +000011795 len = (int)(end - start);
11796
11797 /*
11798 * Copy the function name to allocated memory.
11799 * Accept <SID>name() inside a script, translate into <SNR>123_name().
11800 * Accept <SNR>123_name() outside a script.
11801 */
11802 if (skip)
11803 lead = 0; /* do nothing */
11804 else if (lead > 0)
11805 {
11806 lead = 3;
11807 if (eval_fname_sid(*pp)) /* If it's "<SID>" */
11808 {
11809 if (current_SID <= 0)
11810 {
11811 EMSG(_(e_usingsid));
11812 return NULL;
11813 }
11814 sprintf((char *)sid_buf, "%ld_", (long)current_SID);
11815 lead += (int)STRLEN(sid_buf);
11816 }
11817 }
11818 else if (!internal && !ASCII_ISUPPER(*start))
11819 {
11820 EMSG2(_("E128: Function name must start with a capital: %s"), start);
11821 return NULL;
11822 }
11823 name = alloc((unsigned)(len + lead + 1));
11824 if (name != NULL)
11825 {
11826 if (lead > 0)
11827 {
11828 name[0] = K_SPECIAL;
11829 name[1] = KS_EXTRA;
11830 name[2] = (int)KE_SNR;
11831 if (eval_fname_sid(*pp)) /* If it's "<SID>" */
11832 STRCPY(name + 3, sid_buf);
11833 }
11834 mch_memmove(name + lead, start, (size_t)len);
11835 name[len + lead] = NUL;
11836 }
11837 *pp = end;
11838
11839 vim_free(temp_string);
11840 return name;
11841}
11842
11843/*
11844 * Return 5 if "p" starts with "<SID>" or "<SNR>" (ignoring case).
11845 * Return 2 if "p" starts with "s:".
11846 * Return 0 otherwise.
11847 */
11848 static int
11849eval_fname_script(p)
11850 char_u *p;
11851{
11852 if (p[0] == '<' && (STRNICMP(p + 1, "SID>", 4) == 0
11853 || STRNICMP(p + 1, "SNR>", 4) == 0))
11854 return 5;
11855 if (p[0] == 's' && p[1] == ':')
11856 return 2;
11857 return 0;
11858}
11859
11860/*
11861 * Return TRUE if "p" starts with "<SID>" or "s:".
11862 * Only works if eval_fname_script() returned non-zero for "p"!
11863 */
11864 static int
11865eval_fname_sid(p)
11866 char_u *p;
11867{
11868 return (*p == 's' || TOUPPER_ASC(p[2]) == 'I');
11869}
11870
11871/*
11872 * List the head of the function: "name(arg1, arg2)".
11873 */
11874 static void
11875list_func_head(fp, indent)
11876 ufunc_T *fp;
11877 int indent;
11878{
11879 int j;
11880
11881 msg_start();
11882 if (indent)
11883 MSG_PUTS(" ");
11884 MSG_PUTS("function ");
11885 if (fp->name[0] == K_SPECIAL)
11886 {
11887 MSG_PUTS_ATTR("<SNR>", hl_attr(HLF_8));
11888 msg_puts(fp->name + 3);
11889 }
11890 else
11891 msg_puts(fp->name);
11892 msg_putchar('(');
11893 for (j = 0; j < fp->args.ga_len; ++j)
11894 {
11895 if (j)
11896 MSG_PUTS(", ");
11897 msg_puts(FUNCARG(fp, j));
11898 }
11899 if (fp->varargs)
11900 {
11901 if (j)
11902 MSG_PUTS(", ");
11903 MSG_PUTS("...");
11904 }
11905 msg_putchar(')');
11906}
11907
11908/*
11909 * Find a function by name, return pointer to it in ufuncs.
11910 * Return NULL for unknown function.
11911 */
11912 static ufunc_T *
11913find_func(name)
11914 char_u *name;
11915{
11916 ufunc_T *fp;
11917
11918 for (fp = firstfunc; fp != NULL; fp = fp->next)
11919 if (STRCMP(name, fp->name) == 0)
11920 break;
11921 return fp;
11922}
11923
Bram Moolenaar49cd9572005-01-03 21:06:01 +000011924/*
11925 * Return TRUE if a function "name" exists.
11926 */
11927 static int
11928function_exists(name)
11929 char_u *name;
11930{
11931 char_u *p = name;
11932 int n = FALSE;
11933
11934 p = trans_function_name(&p, FALSE, TRUE);
11935 if (p != NULL)
11936 {
11937 if (ASCII_ISUPPER(*p) || p[0] == K_SPECIAL)
11938 n = (find_func(p) != NULL);
11939 else if (ASCII_ISLOWER(*p))
11940 n = (find_internal_func(p) >= 0);
11941 vim_free(p);
11942 }
11943 return n;
11944}
11945
Bram Moolenaar071d4272004-06-13 20:20:40 +000011946#if defined(FEAT_CMDL_COMPL) || defined(PROTO)
11947
11948/*
11949 * Function given to ExpandGeneric() to obtain the list of user defined
11950 * function names.
11951 */
11952 char_u *
11953get_user_func_name(xp, idx)
11954 expand_T *xp;
11955 int idx;
11956{
11957 static ufunc_T *fp = NULL;
11958
11959 if (idx == 0)
11960 fp = firstfunc;
11961 if (fp != NULL)
11962 {
11963 if (STRLEN(fp->name) + 4 >= IOSIZE)
11964 return fp->name; /* prevents overflow */
11965
11966 cat_func_name(IObuff, fp);
11967 if (xp->xp_context != EXPAND_USER_FUNC)
11968 {
11969 STRCAT(IObuff, "(");
11970 if (!fp->varargs && fp->args.ga_len == 0)
11971 STRCAT(IObuff, ")");
11972 }
11973
11974 fp = fp->next;
11975 return IObuff;
11976 }
11977 return NULL;
11978}
11979
11980#endif /* FEAT_CMDL_COMPL */
11981
11982/*
11983 * Copy the function name of "fp" to buffer "buf".
11984 * "buf" must be able to hold the function name plus three bytes.
11985 * Takes care of script-local function names.
11986 */
11987 static void
11988cat_func_name(buf, fp)
11989 char_u *buf;
11990 ufunc_T *fp;
11991{
11992 if (fp->name[0] == K_SPECIAL)
11993 {
11994 STRCPY(buf, "<SNR>");
11995 STRCAT(buf, fp->name + 3);
11996 }
11997 else
11998 STRCPY(buf, fp->name);
11999}
12000
12001/*
12002 * ":delfunction {name}"
12003 */
12004 void
12005ex_delfunction(eap)
12006 exarg_T *eap;
12007{
12008 ufunc_T *fp = NULL, *pfp;
12009 char_u *p;
12010 char_u *name;
12011
12012 p = eap->arg;
12013 name = trans_function_name(&p, eap->skip, FALSE);
12014 if (name == NULL)
12015 return;
12016 if (!ends_excmd(*skipwhite(p)))
12017 {
12018 vim_free(name);
12019 EMSG(_(e_trailing));
12020 return;
12021 }
12022 eap->nextcmd = check_nextcmd(p);
12023 if (eap->nextcmd != NULL)
12024 *p = NUL;
12025
12026 if (!eap->skip)
12027 fp = find_func(name);
12028 vim_free(name);
12029
12030 if (!eap->skip)
12031 {
12032 if (fp == NULL)
12033 {
12034 EMSG2(_("E130: Undefined function: %s"), eap->arg);
12035 return;
12036 }
12037 if (fp->calls)
12038 {
12039 EMSG2(_("E131: Cannot delete function %s: It is in use"), eap->arg);
12040 return;
12041 }
12042
12043 /* clear this function */
12044 vim_free(fp->name);
12045 ga_clear_strings(&(fp->args));
12046 ga_clear_strings(&(fp->lines));
12047
12048 /* remove the function from the function list */
12049 if (firstfunc == fp)
12050 firstfunc = fp->next;
12051 else
12052 {
12053 for (pfp = firstfunc; pfp != NULL; pfp = pfp->next)
12054 if (pfp->next == fp)
12055 {
12056 pfp->next = fp->next;
12057 break;
12058 }
12059 }
12060 vim_free(fp);
12061 }
12062}
12063
12064/*
12065 * Call a user function.
12066 */
12067 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012068call_user_func(fp, argcount, argvars, rettv, firstline, lastline)
Bram Moolenaar071d4272004-06-13 20:20:40 +000012069 ufunc_T *fp; /* pointer to function */
12070 int argcount; /* nr of args */
Bram Moolenaar49cd9572005-01-03 21:06:01 +000012071 typeval *argvars; /* arguments */
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012072 typeval *rettv; /* return value */
Bram Moolenaar071d4272004-06-13 20:20:40 +000012073 linenr_T firstline; /* first line of range */
12074 linenr_T lastline; /* last line of range */
12075{
12076 char_u *save_sourcing_name;
12077 linenr_T save_sourcing_lnum;
12078 scid_T save_current_SID;
12079 struct funccall fc;
12080 struct funccall *save_fcp = current_funccal;
12081 int save_did_emsg;
12082 static int depth = 0;
12083
12084 /* If depth of calling is getting too high, don't execute the function */
12085 if (depth >= p_mfd)
12086 {
12087 EMSG(_("E132: Function call depth is higher than 'maxfuncdepth'"));
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012088 rettv->v_type = VAR_NUMBER;
12089 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012090 return;
12091 }
12092 ++depth;
12093
12094 line_breakcheck(); /* check for CTRL-C hit */
12095
12096 /* set local variables */
Bram Moolenaar49cd9572005-01-03 21:06:01 +000012097 vars_init(&fc.l_vars);
Bram Moolenaar071d4272004-06-13 20:20:40 +000012098 fc.func = fp;
12099 fc.argcount = argcount;
12100 fc.argvars = argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012101 fc.rettv = rettv;
12102 rettv->vval.v_number = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012103 fc.linenr = 0;
12104 fc.returned = FALSE;
12105 fc.level = ex_nesting_level;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000012106 fc.a0_var.tv.v_type = VAR_NUMBER;
12107 fc.a0_var.tv.vval.v_number = argcount - fp->args.ga_len;
12108 fc.a0_var.v_name = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012109 current_funccal = &fc;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000012110 fc.firstline.tv.v_type = VAR_NUMBER;
12111 fc.firstline.tv.vval.v_number = firstline;
12112 fc.firstline.v_name = NULL;
12113 fc.lastline.tv.v_type = VAR_NUMBER;
12114 fc.lastline.tv.vval.v_number = lastline;
12115 fc.lastline.v_name = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012116 /* Check if this function has a breakpoint. */
12117 fc.breakpoint = dbg_find_breakpoint(FALSE, fp->name, (linenr_T)0);
12118 fc.dbg_tick = debug_tick;
12119
12120 /* Don't redraw while executing the function. */
12121 ++RedrawingDisabled;
12122 save_sourcing_name = sourcing_name;
12123 save_sourcing_lnum = sourcing_lnum;
12124 sourcing_lnum = 1;
12125 sourcing_name = alloc((unsigned)((save_sourcing_name == NULL ? 0
12126 : STRLEN(save_sourcing_name)) + STRLEN(fp->name) + 13));
12127 if (sourcing_name != NULL)
12128 {
12129 if (save_sourcing_name != NULL
12130 && STRNCMP(save_sourcing_name, "function ", 9) == 0)
12131 sprintf((char *)sourcing_name, "%s..", save_sourcing_name);
12132 else
12133 STRCPY(sourcing_name, "function ");
12134 cat_func_name(sourcing_name + STRLEN(sourcing_name), fp);
12135
12136 if (p_verbose >= 12)
12137 {
12138 ++no_wait_return;
12139 msg_scroll = TRUE; /* always scroll up, don't overwrite */
12140 msg_str((char_u *)_("calling %s"), sourcing_name);
12141 if (p_verbose >= 14)
12142 {
12143 int i;
12144 char_u buf[MSG_BUF_LEN];
12145
12146 msg_puts((char_u *)"(");
12147 for (i = 0; i < argcount; ++i)
12148 {
12149 if (i > 0)
12150 msg_puts((char_u *)", ");
Bram Moolenaar49cd9572005-01-03 21:06:01 +000012151 if (argvars[i].v_type == VAR_NUMBER)
12152 msg_outnum((long)argvars[i].vval.v_number);
Bram Moolenaar071d4272004-06-13 20:20:40 +000012153 else
12154 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012155 trunc_string(get_tv_string(&argvars[i]),
Bram Moolenaar071d4272004-06-13 20:20:40 +000012156 buf, MSG_BUF_LEN);
12157 msg_puts((char_u *)"\"");
12158 msg_puts(buf);
12159 msg_puts((char_u *)"\"");
12160 }
12161 }
12162 msg_puts((char_u *)")");
12163 }
12164 msg_puts((char_u *)"\n"); /* don't overwrite this either */
12165 cmdline_row = msg_row;
12166 --no_wait_return;
12167 }
12168 }
12169 save_current_SID = current_SID;
12170 current_SID = fp->script_ID;
12171 save_did_emsg = did_emsg;
12172 did_emsg = FALSE;
12173
12174 /* call do_cmdline() to execute the lines */
12175 do_cmdline(NULL, get_func_line, (void *)&fc,
12176 DOCMD_NOWAIT|DOCMD_VERBOSE|DOCMD_REPEAT);
12177
12178 --RedrawingDisabled;
12179
12180 /* when the function was aborted because of an error, return -1 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012181 if ((did_emsg && (fp->flags & FC_ABORT)) || rettv->v_type == VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +000012182 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012183 clear_tv(rettv);
12184 rettv->v_type = VAR_NUMBER;
12185 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012186 }
12187
12188 /* when being verbose, mention the return value */
12189 if (p_verbose >= 12)
12190 {
12191 char_u *sn, *val;
12192
12193 ++no_wait_return;
12194 msg_scroll = TRUE; /* always scroll up, don't overwrite */
12195
12196 /* Make sure the output fits in IObuff. */
12197 sn = sourcing_name;
12198 if (STRLEN(sourcing_name) > IOSIZE / 2 - 50)
12199 sn = sourcing_name + STRLEN(sourcing_name) - (IOSIZE / 2 - 50);
12200
12201 if (aborting())
12202 smsg((char_u *)_("%s aborted"), sn);
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012203 else if (fc.rettv->v_type == VAR_NUMBER)
Bram Moolenaar071d4272004-06-13 20:20:40 +000012204 smsg((char_u *)_("%s returning #%ld"), sn,
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012205 (long)fc.rettv->vval.v_number);
12206 else if (fc.rettv->v_type == VAR_STRING)
Bram Moolenaar071d4272004-06-13 20:20:40 +000012207 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012208 val = get_tv_string(fc.rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000012209 if (STRLEN(val) > IOSIZE / 2 - 50)
12210 val = val + STRLEN(val) - (IOSIZE / 2 - 50);
12211 smsg((char_u *)_("%s returning \"%s\""), sn, val);
12212 }
12213 msg_puts((char_u *)"\n"); /* don't overwrite this either */
12214 cmdline_row = msg_row;
12215 --no_wait_return;
12216 }
12217
12218 vim_free(sourcing_name);
12219 sourcing_name = save_sourcing_name;
12220 sourcing_lnum = save_sourcing_lnum;
12221 current_SID = save_current_SID;
12222
12223 if (p_verbose >= 12 && sourcing_name != NULL)
12224 {
12225 ++no_wait_return;
12226 msg_scroll = TRUE; /* always scroll up, don't overwrite */
12227 msg_str((char_u *)_("continuing in %s"), sourcing_name);
12228 msg_puts((char_u *)"\n"); /* don't overwrite this either */
12229 cmdline_row = msg_row;
12230 --no_wait_return;
12231 }
12232
12233 did_emsg |= save_did_emsg;
12234 current_funccal = save_fcp;
12235
Bram Moolenaar49cd9572005-01-03 21:06:01 +000012236 vars_clear(&fc.l_vars); /* free all local variables */
Bram Moolenaar071d4272004-06-13 20:20:40 +000012237 --depth;
12238}
12239
12240/*
12241 * ":return [expr]"
12242 */
12243 void
12244ex_return(eap)
12245 exarg_T *eap;
12246{
12247 char_u *arg = eap->arg;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012248 typeval rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012249 int returning = FALSE;
12250
12251 if (current_funccal == NULL)
12252 {
12253 EMSG(_("E133: :return not inside a function"));
12254 return;
12255 }
12256
12257 if (eap->skip)
12258 ++emsg_skip;
12259
12260 eap->nextcmd = NULL;
12261 if ((*arg != NUL && *arg != '|' && *arg != '\n')
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012262 && eval0(arg, &rettv, &eap->nextcmd, !eap->skip) != FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000012263 {
12264 if (!eap->skip)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012265 returning = do_return(eap, FALSE, TRUE, &rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000012266 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012267 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000012268 }
12269 /* It's safer to return also on error. */
12270 else if (!eap->skip)
12271 {
12272 /*
12273 * Return unless the expression evaluation has been cancelled due to an
12274 * aborting error, an interrupt, or an exception.
12275 */
12276 if (!aborting())
12277 returning = do_return(eap, FALSE, TRUE, NULL);
12278 }
12279
12280 /* When skipping or the return gets pending, advance to the next command
12281 * in this line (!returning). Otherwise, ignore the rest of the line.
12282 * Following lines will be ignored by get_func_line(). */
12283 if (returning)
12284 eap->nextcmd = NULL;
12285 else if (eap->nextcmd == NULL) /* no argument */
12286 eap->nextcmd = check_nextcmd(arg);
12287
12288 if (eap->skip)
12289 --emsg_skip;
12290}
12291
12292/*
12293 * Return from a function. Possibly makes the return pending. Also called
12294 * for a pending return at the ":endtry" or after returning from an extra
12295 * do_cmdline(). "reanimate" is used in the latter case. "is_cmd" is set
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012296 * when called due to a ":return" command. "rettv" may point to a typeval
12297 * with the return rettv. Returns TRUE when the return can be carried out,
Bram Moolenaar071d4272004-06-13 20:20:40 +000012298 * FALSE when the return gets pending.
12299 */
12300 int
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012301do_return(eap, reanimate, is_cmd, rettv)
Bram Moolenaar071d4272004-06-13 20:20:40 +000012302 exarg_T *eap;
12303 int reanimate;
12304 int is_cmd;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012305 void *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012306{
12307 int idx;
12308 struct condstack *cstack = eap->cstack;
12309
12310 if (reanimate)
12311 /* Undo the return. */
12312 current_funccal->returned = FALSE;
12313
12314 /*
12315 * Cleanup (and inactivate) conditionals, but stop when a try conditional
12316 * not in its finally clause (which then is to be executed next) is found.
12317 * In this case, make the ":return" pending for execution at the ":endtry".
12318 * Otherwise, return normally.
12319 */
12320 idx = cleanup_conditionals(eap->cstack, 0, TRUE);
12321 if (idx >= 0)
12322 {
12323 cstack->cs_pending[idx] = CSTP_RETURN;
12324
12325 if (!is_cmd && !reanimate)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012326 /* A pending return again gets pending. "rettv" points to an
12327 * allocated variable with the rettv of the original ":return"'s
Bram Moolenaar071d4272004-06-13 20:20:40 +000012328 * argument if present or is NULL else. */
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012329 cstack->cs_rettv[idx] = rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012330 else
12331 {
12332 /* When undoing a return in order to make it pending, get the stored
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012333 * return rettv. */
Bram Moolenaar071d4272004-06-13 20:20:40 +000012334 if (reanimate)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012335 rettv = current_funccal->rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012336
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012337 if (rettv != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000012338 {
12339 /* Store the value of the pending return. */
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012340 if ((cstack->cs_rettv[idx] = alloc_tv()) != NULL)
12341 *(typeval *)cstack->cs_rettv[idx] = *(typeval *)rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012342 else
12343 EMSG(_(e_outofmem));
12344 }
12345 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012346 cstack->cs_rettv[idx] = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012347
12348 if (reanimate)
12349 {
12350 /* The pending return value could be overwritten by a ":return"
12351 * without argument in a finally clause; reset the default
12352 * return value. */
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012353 current_funccal->rettv->v_type = VAR_NUMBER;
12354 current_funccal->rettv->vval.v_number = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012355 }
12356 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012357 report_make_pending(CSTP_RETURN, rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000012358 }
12359 else
12360 {
12361 current_funccal->returned = TRUE;
12362
12363 /* If the return is carried out now, store the return value. For
12364 * a return immediately after reanimation, the value is already
12365 * there. */
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012366 if (!reanimate && rettv != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000012367 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012368 clear_tv(current_funccal->rettv);
12369 *current_funccal->rettv = *(typeval *)rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012370 if (!is_cmd)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012371 vim_free(rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000012372 }
12373 }
12374
12375 return idx < 0;
12376}
12377
12378/*
12379 * Free the variable with a pending return value.
12380 */
12381 void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012382discard_pending_return(rettv)
12383 void *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012384{
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012385 free_tv((typeval *)rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000012386}
12387
12388/*
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012389 * Generate a return command for producing the value of "rettv". The result
Bram Moolenaar071d4272004-06-13 20:20:40 +000012390 * is an allocated string. Used by report_pending() for verbose messages.
12391 */
12392 char_u *
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012393get_return_cmd(rettv)
12394 void *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012395{
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012396 char_u *s;
12397 char_u *tofree = NULL;
Bram Moolenaar8a283e52005-01-06 23:28:25 +000012398 char_u numbuf[NUMBUFLEN];
Bram Moolenaar071d4272004-06-13 20:20:40 +000012399
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012400 if (rettv == NULL)
12401 s = (char_u *)"";
Bram Moolenaar071d4272004-06-13 20:20:40 +000012402 else
Bram Moolenaar8a283e52005-01-06 23:28:25 +000012403 s = tv2string((typeval *)rettv, &tofree, numbuf);
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012404
12405 STRCPY(IObuff, ":return ");
12406 STRNCPY(IObuff + 8, s, IOSIZE - 8);
12407 if (STRLEN(s) + 8 >= IOSIZE)
12408 STRCPY(IObuff + IOSIZE - 4, "...");
12409 vim_free(tofree);
12410 return vim_strsave(IObuff);
Bram Moolenaar071d4272004-06-13 20:20:40 +000012411}
12412
12413/*
12414 * Get next function line.
12415 * Called by do_cmdline() to get the next line.
12416 * Returns allocated string, or NULL for end of function.
12417 */
12418/* ARGSUSED */
12419 char_u *
12420get_func_line(c, cookie, indent)
12421 int c; /* not used */
12422 void *cookie;
12423 int indent; /* not used */
12424{
12425 struct funccall *fcp = (struct funccall *)cookie;
12426 char_u *retval;
12427 garray_T *gap; /* growarray with function lines */
12428
12429 /* If breakpoints have been added/deleted need to check for it. */
12430 if (fcp->dbg_tick != debug_tick)
12431 {
12432 fcp->breakpoint = dbg_find_breakpoint(FALSE, fcp->func->name,
12433 sourcing_lnum);
12434 fcp->dbg_tick = debug_tick;
12435 }
12436
12437 gap = &fcp->func->lines;
12438 if ((fcp->func->flags & FC_ABORT) && did_emsg && !aborted_in_try())
12439 retval = NULL;
12440 else if (fcp->returned || fcp->linenr >= gap->ga_len)
12441 retval = NULL;
12442 else
12443 {
12444 retval = vim_strsave(((char_u **)(gap->ga_data))[fcp->linenr++]);
12445 sourcing_lnum = fcp->linenr;
12446 }
12447
12448 /* Did we encounter a breakpoint? */
12449 if (fcp->breakpoint != 0 && fcp->breakpoint <= sourcing_lnum)
12450 {
12451 dbg_breakpoint(fcp->func->name, sourcing_lnum);
12452 /* Find next breakpoint. */
12453 fcp->breakpoint = dbg_find_breakpoint(FALSE, fcp->func->name,
12454 sourcing_lnum);
12455 fcp->dbg_tick = debug_tick;
12456 }
12457
12458 return retval;
12459}
12460
12461/*
12462 * Return TRUE if the currently active function should be ended, because a
12463 * return was encountered or an error occured. Used inside a ":while".
12464 */
12465 int
12466func_has_ended(cookie)
12467 void *cookie;
12468{
12469 struct funccall *fcp = (struct funccall *)cookie;
12470
12471 /* Ignore the "abort" flag if the abortion behavior has been changed due to
12472 * an error inside a try conditional. */
12473 return (((fcp->func->flags & FC_ABORT) && did_emsg && !aborted_in_try())
12474 || fcp->returned);
12475}
12476
12477/*
12478 * return TRUE if cookie indicates a function which "abort"s on errors.
12479 */
12480 int
12481func_has_abort(cookie)
12482 void *cookie;
12483{
12484 return ((struct funccall *)cookie)->func->flags & FC_ABORT;
12485}
12486
12487#if defined(FEAT_VIMINFO) || defined(FEAT_SESSION)
12488typedef enum
12489{
12490 VAR_FLAVOUR_DEFAULT,
12491 VAR_FLAVOUR_SESSION,
12492 VAR_FLAVOUR_VIMINFO
12493} var_flavour_T;
12494
12495static var_flavour_T var_flavour __ARGS((char_u *varname));
12496
12497 static var_flavour_T
12498var_flavour(varname)
12499 char_u *varname;
12500{
12501 char_u *p = varname;
12502
12503 if (ASCII_ISUPPER(*p))
12504 {
12505 while (*(++p))
12506 if (ASCII_ISLOWER(*p))
12507 return VAR_FLAVOUR_SESSION;
12508 return VAR_FLAVOUR_VIMINFO;
12509 }
12510 else
12511 return VAR_FLAVOUR_DEFAULT;
12512}
12513#endif
12514
12515#if defined(FEAT_VIMINFO) || defined(PROTO)
12516/*
12517 * Restore global vars that start with a capital from the viminfo file
12518 */
12519 int
12520read_viminfo_varlist(virp, writing)
12521 vir_T *virp;
12522 int writing;
12523{
12524 char_u *tab;
12525 int is_string = FALSE;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +000012526 typeval tv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012527
12528 if (!writing && (find_viminfo_parameter('!') != NULL))
12529 {
12530 tab = vim_strchr(virp->vir_line + 1, '\t');
12531 if (tab != NULL)
12532 {
12533 *tab++ = '\0'; /* isolate the variable name */
12534 if (*tab == 'S') /* string var */
12535 is_string = TRUE;
12536
12537 tab = vim_strchr(tab, '\t');
12538 if (tab != NULL)
12539 {
Bram Moolenaar071d4272004-06-13 20:20:40 +000012540 if (is_string)
12541 {
Bram Moolenaar3d60ec22005-01-05 22:19:46 +000012542 tv.v_type = VAR_STRING;
12543 tv.vval.v_string = viminfo_readstring(virp,
Bram Moolenaar071d4272004-06-13 20:20:40 +000012544 (int)(tab - virp->vir_line + 1), TRUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +000012545 }
12546 else
12547 {
Bram Moolenaar3d60ec22005-01-05 22:19:46 +000012548 tv.v_type = VAR_NUMBER;
12549 tv.vval.v_number = atol((char *)tab + 1);
Bram Moolenaar071d4272004-06-13 20:20:40 +000012550 }
Bram Moolenaar3d60ec22005-01-05 22:19:46 +000012551 set_var(virp->vir_line + 1, &tv, FALSE);
12552 if (is_string)
12553 vim_free(tv.vval.v_string);
Bram Moolenaar071d4272004-06-13 20:20:40 +000012554 }
12555 }
12556 }
12557
12558 return viminfo_readline(virp);
12559}
12560
12561/*
12562 * Write global vars that start with a capital to the viminfo file
12563 */
12564 void
12565write_viminfo_varlist(fp)
12566 FILE *fp;
12567{
12568 garray_T *gap = &variables; /* global variable */
12569 VAR this_var;
12570 int i;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012571 char *s;
12572 char_u *tofree;
Bram Moolenaar8a283e52005-01-06 23:28:25 +000012573 char_u numbuf[NUMBUFLEN];
Bram Moolenaar071d4272004-06-13 20:20:40 +000012574
12575 if (find_viminfo_parameter('!') == NULL)
12576 return;
12577
12578 fprintf(fp, _("\n# global variables:\n"));
12579 for (i = gap->ga_len; --i >= 0; )
12580 {
12581 this_var = &VAR_GAP_ENTRY(i, gap);
Bram Moolenaar49cd9572005-01-03 21:06:01 +000012582 if (this_var->v_name != NULL
12583 && var_flavour(this_var->v_name) == VAR_FLAVOUR_VIMINFO)
Bram Moolenaar071d4272004-06-13 20:20:40 +000012584 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012585 switch (this_var->tv.v_type)
12586 {
12587 case VAR_STRING: s = "STR"; break;
12588 case VAR_NUMBER: s = "NUM"; break;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +000012589 default: continue;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012590 }
12591 fprintf(fp, "!%s\t%s\t", this_var->v_name, s);
Bram Moolenaar8a283e52005-01-06 23:28:25 +000012592 viminfo_writestring(fp, tv2string(&this_var->tv, &tofree, numbuf));
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012593 vim_free(tofree);
Bram Moolenaar071d4272004-06-13 20:20:40 +000012594 }
12595 }
12596}
12597#endif
12598
12599#if defined(FEAT_SESSION) || defined(PROTO)
12600 int
12601store_session_globals(fd)
12602 FILE *fd;
12603{
12604 garray_T *gap = &variables; /* global variable */
12605 VAR this_var;
12606 int i;
12607 char_u *p, *t;
12608
12609 for (i = gap->ga_len; --i >= 0; )
12610 {
12611 this_var = &VAR_GAP_ENTRY(i, gap);
Bram Moolenaar3d60ec22005-01-05 22:19:46 +000012612 if (this_var->v_name != NULL
12613 && (this_var->tv.v_type == VAR_NUMBER
12614 || this_var->tv.v_type == VAR_STRING)
12615 && var_flavour(this_var->v_name) == VAR_FLAVOUR_SESSION)
Bram Moolenaar071d4272004-06-13 20:20:40 +000012616 {
Bram Moolenaar3d60ec22005-01-05 22:19:46 +000012617 /* Escape special characters with a backslash. Turn a LF and
12618 * CR into \n and \r. */
12619 p = vim_strsave_escaped(get_var_string(this_var),
Bram Moolenaar071d4272004-06-13 20:20:40 +000012620 (char_u *)"\\\"\n\r");
Bram Moolenaar3d60ec22005-01-05 22:19:46 +000012621 if (p == NULL) /* out of memory */
12622 continue;
12623 for (t = p; *t != NUL; ++t)
12624 if (*t == '\n')
12625 *t = 'n';
12626 else if (*t == '\r')
12627 *t = 'r';
12628 if ((fprintf(fd, "let %s = %c%s%c",
12629 this_var->v_name,
12630 (this_var->tv.v_type == VAR_STRING) ? '"' : ' ',
12631 p,
12632 (this_var->tv.v_type == VAR_STRING) ? '"' : ' ') < 0)
12633 || put_eol(fd) == FAIL)
12634 {
Bram Moolenaar071d4272004-06-13 20:20:40 +000012635 vim_free(p);
Bram Moolenaar3d60ec22005-01-05 22:19:46 +000012636 return FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012637 }
Bram Moolenaar3d60ec22005-01-05 22:19:46 +000012638 vim_free(p);
Bram Moolenaar071d4272004-06-13 20:20:40 +000012639 }
12640 }
12641 return OK;
12642}
12643#endif
12644
12645#endif /* FEAT_EVAL */
12646
12647#if defined(FEAT_MODIFY_FNAME) || defined(FEAT_EVAL) || defined(PROTO)
12648
12649
12650#ifdef WIN3264
12651/*
12652 * Functions for ":8" filename modifier: get 8.3 version of a filename.
12653 */
12654static int get_short_pathname __ARGS((char_u **fnamep, char_u **bufp, int *fnamelen));
12655static int shortpath_for_invalid_fname __ARGS((char_u **fname, char_u **bufp, int *fnamelen));
12656static int shortpath_for_partial __ARGS((char_u **fnamep, char_u **bufp, int *fnamelen));
12657
12658/*
12659 * Get the short pathname of a file.
12660 * Returns 1 on success. *fnamelen is 0 for nonexistant path.
12661 */
12662 static int
12663get_short_pathname(fnamep, bufp, fnamelen)
12664 char_u **fnamep;
12665 char_u **bufp;
12666 int *fnamelen;
12667{
12668 int l,len;
12669 char_u *newbuf;
12670
12671 len = *fnamelen;
12672
12673 l = GetShortPathName(*fnamep, *fnamep, len);
12674 if (l > len - 1)
12675 {
12676 /* If that doesn't work (not enough space), then save the string
12677 * and try again with a new buffer big enough
12678 */
12679 newbuf = vim_strnsave(*fnamep, l);
12680 if (newbuf == NULL)
12681 return 0;
12682
12683 vim_free(*bufp);
12684 *fnamep = *bufp = newbuf;
12685
12686 l = GetShortPathName(*fnamep,*fnamep,l+1);
12687
12688 /* Really should always succeed, as the buffer is big enough */
12689 }
12690
12691 *fnamelen = l;
12692 return 1;
12693}
12694
12695/*
12696 * Create a short path name. Returns the length of the buffer it needs.
12697 * Doesn't copy over the end of the buffer passed in.
12698 */
12699 static int
12700shortpath_for_invalid_fname(fname, bufp, fnamelen)
12701 char_u **fname;
12702 char_u **bufp;
12703 int *fnamelen;
12704{
12705 char_u *s, *p, *pbuf2, *pbuf3;
12706 char_u ch;
12707 int l,len,len2,plen,slen;
12708
12709 /* Make a copy */
12710 len2 = *fnamelen;
12711 pbuf2 = vim_strnsave(*fname, len2);
12712 pbuf3 = NULL;
12713
12714 s = pbuf2 + len2 - 1; /* Find the end */
12715 slen = 1;
12716 plen = len2;
12717
12718 l = 0;
Bram Moolenaar1cd871b2004-12-19 22:46:22 +000012719 if (after_pathsep(pbuf2, s + 1))
Bram Moolenaar071d4272004-06-13 20:20:40 +000012720 {
12721 --s;
12722 ++slen;
12723 --plen;
12724 }
12725
12726 do
12727 {
12728 /* Go back one path-seperator */
Bram Moolenaar1cd871b2004-12-19 22:46:22 +000012729 while (s > pbuf2 && !after_pathsep(pbuf2, s + 1))
Bram Moolenaar071d4272004-06-13 20:20:40 +000012730 {
12731 --s;
12732 ++slen;
12733 --plen;
12734 }
12735 if (s <= pbuf2)
12736 break;
12737
12738 /* Remeber the character that is about to be blatted */
12739 ch = *s;
12740 *s = 0; /* get_short_pathname requires a null-terminated string */
12741
12742 /* Try it in situ */
12743 p = pbuf2;
12744 if (!get_short_pathname(&p, &pbuf3, &plen))
12745 {
12746 vim_free(pbuf2);
12747 return -1;
12748 }
12749 *s = ch; /* Preserve the string */
12750 } while (plen == 0);
12751
12752 if (plen > 0)
12753 {
12754 /* Remeber the length of the new string. */
12755 *fnamelen = len = plen + slen;
12756 vim_free(*bufp);
12757 if (len > len2)
12758 {
12759 /* If there's not enough space in the currently allocated string,
12760 * then copy it to a buffer big enough.
12761 */
12762 *fname= *bufp = vim_strnsave(p, len);
12763 if (*fname == NULL)
12764 return -1;
12765 }
12766 else
12767 {
12768 /* Transfer pbuf2 to being the main buffer (it's big enough) */
12769 *fname = *bufp = pbuf2;
12770 if (p != pbuf2)
12771 strncpy(*fname, p, plen);
12772 pbuf2 = NULL;
12773 }
12774 /* Concat the next bit */
12775 strncpy(*fname + plen, s, slen);
12776 (*fname)[len] = '\0';
12777 }
12778 vim_free(pbuf3);
12779 vim_free(pbuf2);
12780 return 0;
12781}
12782
12783/*
12784 * Get a pathname for a partial path.
12785 */
12786 static int
12787shortpath_for_partial(fnamep, bufp, fnamelen)
12788 char_u **fnamep;
12789 char_u **bufp;
12790 int *fnamelen;
12791{
12792 int sepcount, len, tflen;
12793 char_u *p;
12794 char_u *pbuf, *tfname;
12795 int hasTilde;
12796
12797 /* Count up the path seperators from the RHS.. so we know which part
12798 * of the path to return.
12799 */
12800 sepcount = 0;
Bram Moolenaar1cd871b2004-12-19 22:46:22 +000012801 for (p = *fnamep; p < *fnamep + *fnamelen; mb_ptr_adv(p))
Bram Moolenaar071d4272004-06-13 20:20:40 +000012802 if (vim_ispathsep(*p))
12803 ++sepcount;
12804
12805 /* Need full path first (use expand_env() to remove a "~/") */
12806 hasTilde = (**fnamep == '~');
12807 if (hasTilde)
12808 pbuf = tfname = expand_env_save(*fnamep);
12809 else
12810 pbuf = tfname = FullName_save(*fnamep, FALSE);
12811
12812 len = tflen = STRLEN(tfname);
12813
12814 if (!get_short_pathname(&tfname, &pbuf, &len))
12815 return -1;
12816
12817 if (len == 0)
12818 {
12819 /* Don't have a valid filename, so shorten the rest of the
12820 * path if we can. This CAN give us invalid 8.3 filenames, but
12821 * there's not a lot of point in guessing what it might be.
12822 */
12823 len = tflen;
12824 if (shortpath_for_invalid_fname(&tfname, &pbuf, &len) == -1)
12825 return -1;
12826 }
12827
12828 /* Count the paths backward to find the beginning of the desired string. */
12829 for (p = tfname + len - 1; p >= tfname; --p)
Bram Moolenaar1cd871b2004-12-19 22:46:22 +000012830 {
12831#ifdef FEAT_MBYTE
12832 if (has_mbyte)
12833 p -= mb_head_off(tfname, p);
12834#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000012835 if (vim_ispathsep(*p))
12836 {
12837 if (sepcount == 0 || (hasTilde && sepcount == 1))
12838 break;
12839 else
12840 sepcount --;
12841 }
Bram Moolenaar1cd871b2004-12-19 22:46:22 +000012842 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000012843 if (hasTilde)
12844 {
12845 --p;
12846 if (p >= tfname)
12847 *p = '~';
12848 else
12849 return -1;
12850 }
12851 else
12852 ++p;
12853
12854 /* Copy in the string - p indexes into tfname - allocated at pbuf */
12855 vim_free(*bufp);
12856 *fnamelen = (int)STRLEN(p);
12857 *bufp = pbuf;
12858 *fnamep = p;
12859
12860 return 0;
12861}
12862#endif /* WIN3264 */
12863
12864/*
12865 * Adjust a filename, according to a string of modifiers.
12866 * *fnamep must be NUL terminated when called. When returning, the length is
12867 * determined by *fnamelen.
12868 * Returns valid flags.
12869 * When there is an error, *fnamep is set to NULL.
12870 */
12871 int
12872modify_fname(src, usedlen, fnamep, bufp, fnamelen)
12873 char_u *src; /* string with modifiers */
12874 int *usedlen; /* characters after src that are used */
12875 char_u **fnamep; /* file name so far */
12876 char_u **bufp; /* buffer for allocated file name or NULL */
12877 int *fnamelen; /* length of fnamep */
12878{
12879 int valid = 0;
12880 char_u *tail;
12881 char_u *s, *p, *pbuf;
12882 char_u dirname[MAXPATHL];
12883 int c;
12884 int has_fullname = 0;
12885#ifdef WIN3264
12886 int has_shortname = 0;
12887#endif
12888
12889repeat:
12890 /* ":p" - full path/file_name */
12891 if (src[*usedlen] == ':' && src[*usedlen + 1] == 'p')
12892 {
12893 has_fullname = 1;
12894
12895 valid |= VALID_PATH;
12896 *usedlen += 2;
12897
12898 /* Expand "~/path" for all systems and "~user/path" for Unix and VMS */
12899 if ((*fnamep)[0] == '~'
12900#if !defined(UNIX) && !(defined(VMS) && defined(USER_HOME))
12901 && ((*fnamep)[1] == '/'
12902# ifdef BACKSLASH_IN_FILENAME
12903 || (*fnamep)[1] == '\\'
12904# endif
12905 || (*fnamep)[1] == NUL)
12906
12907#endif
12908 )
12909 {
12910 *fnamep = expand_env_save(*fnamep);
12911 vim_free(*bufp); /* free any allocated file name */
12912 *bufp = *fnamep;
12913 if (*fnamep == NULL)
12914 return -1;
12915 }
12916
12917 /* When "/." or "/.." is used: force expansion to get rid of it. */
Bram Moolenaar1cd871b2004-12-19 22:46:22 +000012918 for (p = *fnamep; *p != NUL; mb_ptr_adv(p))
Bram Moolenaar071d4272004-06-13 20:20:40 +000012919 {
12920 if (vim_ispathsep(*p)
12921 && p[1] == '.'
12922 && (p[2] == NUL
12923 || vim_ispathsep(p[2])
12924 || (p[2] == '.'
12925 && (p[3] == NUL || vim_ispathsep(p[3])))))
12926 break;
12927 }
12928
12929 /* FullName_save() is slow, don't use it when not needed. */
12930 if (*p != NUL || !vim_isAbsName(*fnamep))
12931 {
12932 *fnamep = FullName_save(*fnamep, *p != NUL);
12933 vim_free(*bufp); /* free any allocated file name */
12934 *bufp = *fnamep;
12935 if (*fnamep == NULL)
12936 return -1;
12937 }
12938
12939 /* Append a path separator to a directory. */
12940 if (mch_isdir(*fnamep))
12941 {
12942 /* Make room for one or two extra characters. */
12943 *fnamep = vim_strnsave(*fnamep, (int)STRLEN(*fnamep) + 2);
12944 vim_free(*bufp); /* free any allocated file name */
12945 *bufp = *fnamep;
12946 if (*fnamep == NULL)
12947 return -1;
12948 add_pathsep(*fnamep);
12949 }
12950 }
12951
12952 /* ":." - path relative to the current directory */
12953 /* ":~" - path relative to the home directory */
12954 /* ":8" - shortname path - postponed till after */
12955 while (src[*usedlen] == ':'
12956 && ((c = src[*usedlen + 1]) == '.' || c == '~' || c == '8'))
12957 {
12958 *usedlen += 2;
12959 if (c == '8')
12960 {
12961#ifdef WIN3264
12962 has_shortname = 1; /* Postpone this. */
12963#endif
12964 continue;
12965 }
12966 pbuf = NULL;
12967 /* Need full path first (use expand_env() to remove a "~/") */
12968 if (!has_fullname)
12969 {
12970 if (c == '.' && **fnamep == '~')
12971 p = pbuf = expand_env_save(*fnamep);
12972 else
12973 p = pbuf = FullName_save(*fnamep, FALSE);
12974 }
12975 else
12976 p = *fnamep;
12977
12978 has_fullname = 0;
12979
12980 if (p != NULL)
12981 {
12982 if (c == '.')
12983 {
12984 mch_dirname(dirname, MAXPATHL);
12985 s = shorten_fname(p, dirname);
12986 if (s != NULL)
12987 {
12988 *fnamep = s;
12989 if (pbuf != NULL)
12990 {
12991 vim_free(*bufp); /* free any allocated file name */
12992 *bufp = pbuf;
12993 pbuf = NULL;
12994 }
12995 }
12996 }
12997 else
12998 {
12999 home_replace(NULL, p, dirname, MAXPATHL, TRUE);
13000 /* Only replace it when it starts with '~' */
13001 if (*dirname == '~')
13002 {
13003 s = vim_strsave(dirname);
13004 if (s != NULL)
13005 {
13006 *fnamep = s;
13007 vim_free(*bufp);
13008 *bufp = s;
13009 }
13010 }
13011 }
13012 vim_free(pbuf);
13013 }
13014 }
13015
13016 tail = gettail(*fnamep);
13017 *fnamelen = (int)STRLEN(*fnamep);
13018
13019 /* ":h" - head, remove "/file_name", can be repeated */
13020 /* Don't remove the first "/" or "c:\" */
13021 while (src[*usedlen] == ':' && src[*usedlen + 1] == 'h')
13022 {
13023 valid |= VALID_HEAD;
13024 *usedlen += 2;
13025 s = get_past_head(*fnamep);
Bram Moolenaar1cd871b2004-12-19 22:46:22 +000013026 while (tail > s && after_pathsep(s, tail))
Bram Moolenaar071d4272004-06-13 20:20:40 +000013027 --tail;
13028 *fnamelen = (int)(tail - *fnamep);
13029#ifdef VMS
13030 if (*fnamelen > 0)
13031 *fnamelen += 1; /* the path separator is part of the path */
13032#endif
Bram Moolenaar1cd871b2004-12-19 22:46:22 +000013033 while (tail > s && !after_pathsep(s, tail))
13034 mb_ptr_back(*fnamep, tail);
Bram Moolenaar071d4272004-06-13 20:20:40 +000013035 }
13036
13037 /* ":8" - shortname */
13038 if (src[*usedlen] == ':' && src[*usedlen + 1] == '8')
13039 {
13040 *usedlen += 2;
13041#ifdef WIN3264
13042 has_shortname = 1;
13043#endif
13044 }
13045
13046#ifdef WIN3264
13047 /* Check shortname after we have done 'heads' and before we do 'tails'
13048 */
13049 if (has_shortname)
13050 {
13051 pbuf = NULL;
13052 /* Copy the string if it is shortened by :h */
13053 if (*fnamelen < (int)STRLEN(*fnamep))
13054 {
13055 p = vim_strnsave(*fnamep, *fnamelen);
13056 if (p == 0)
13057 return -1;
13058 vim_free(*bufp);
13059 *bufp = *fnamep = p;
13060 }
13061
13062 /* Split into two implementations - makes it easier. First is where
13063 * there isn't a full name already, second is where there is.
13064 */
13065 if (!has_fullname && !vim_isAbsName(*fnamep))
13066 {
13067 if (shortpath_for_partial(fnamep, bufp, fnamelen) == -1)
13068 return -1;
13069 }
13070 else
13071 {
13072 int l;
13073
13074 /* Simple case, already have the full-name
13075 * Nearly always shorter, so try first time. */
13076 l = *fnamelen;
13077 if (!get_short_pathname(fnamep, bufp, &l))
13078 return -1;
13079
13080 if (l == 0)
13081 {
13082 /* Couldn't find the filename.. search the paths.
13083 */
13084 l = *fnamelen;
13085 if (shortpath_for_invalid_fname(fnamep, bufp, &l ) == -1)
13086 return -1;
13087 }
13088 *fnamelen = l;
13089 }
13090 }
13091#endif /* WIN3264 */
13092
13093 /* ":t" - tail, just the basename */
13094 if (src[*usedlen] == ':' && src[*usedlen + 1] == 't')
13095 {
13096 *usedlen += 2;
13097 *fnamelen -= (int)(tail - *fnamep);
13098 *fnamep = tail;
13099 }
13100
13101 /* ":e" - extension, can be repeated */
13102 /* ":r" - root, without extension, can be repeated */
13103 while (src[*usedlen] == ':'
13104 && (src[*usedlen + 1] == 'e' || src[*usedlen + 1] == 'r'))
13105 {
13106 /* find a '.' in the tail:
13107 * - for second :e: before the current fname
13108 * - otherwise: The last '.'
13109 */
13110 if (src[*usedlen + 1] == 'e' && *fnamep > tail)
13111 s = *fnamep - 2;
13112 else
13113 s = *fnamep + *fnamelen - 1;
13114 for ( ; s > tail; --s)
13115 if (s[0] == '.')
13116 break;
13117 if (src[*usedlen + 1] == 'e') /* :e */
13118 {
13119 if (s > tail)
13120 {
13121 *fnamelen += (int)(*fnamep - (s + 1));
13122 *fnamep = s + 1;
13123#ifdef VMS
13124 /* cut version from the extension */
13125 s = *fnamep + *fnamelen - 1;
13126 for ( ; s > *fnamep; --s)
13127 if (s[0] == ';')
13128 break;
13129 if (s > *fnamep)
13130 *fnamelen = s - *fnamep;
13131#endif
13132 }
13133 else if (*fnamep <= tail)
13134 *fnamelen = 0;
13135 }
13136 else /* :r */
13137 {
13138 if (s > tail) /* remove one extension */
13139 *fnamelen = (int)(s - *fnamep);
13140 }
13141 *usedlen += 2;
13142 }
13143
13144 /* ":s?pat?foo?" - substitute */
13145 /* ":gs?pat?foo?" - global substitute */
13146 if (src[*usedlen] == ':'
13147 && (src[*usedlen + 1] == 's'
13148 || (src[*usedlen + 1] == 'g' && src[*usedlen + 2] == 's')))
13149 {
13150 char_u *str;
13151 char_u *pat;
13152 char_u *sub;
13153 int sep;
13154 char_u *flags;
13155 int didit = FALSE;
13156
13157 flags = (char_u *)"";
13158 s = src + *usedlen + 2;
13159 if (src[*usedlen + 1] == 'g')
13160 {
13161 flags = (char_u *)"g";
13162 ++s;
13163 }
13164
13165 sep = *s++;
13166 if (sep)
13167 {
13168 /* find end of pattern */
13169 p = vim_strchr(s, sep);
13170 if (p != NULL)
13171 {
13172 pat = vim_strnsave(s, (int)(p - s));
13173 if (pat != NULL)
13174 {
13175 s = p + 1;
13176 /* find end of substitution */
13177 p = vim_strchr(s, sep);
13178 if (p != NULL)
13179 {
13180 sub = vim_strnsave(s, (int)(p - s));
13181 str = vim_strnsave(*fnamep, *fnamelen);
13182 if (sub != NULL && str != NULL)
13183 {
13184 *usedlen = (int)(p + 1 - src);
13185 s = do_string_sub(str, pat, sub, flags);
13186 if (s != NULL)
13187 {
13188 *fnamep = s;
13189 *fnamelen = (int)STRLEN(s);
13190 vim_free(*bufp);
13191 *bufp = s;
13192 didit = TRUE;
13193 }
13194 }
13195 vim_free(sub);
13196 vim_free(str);
13197 }
13198 vim_free(pat);
13199 }
13200 }
13201 /* after using ":s", repeat all the modifiers */
13202 if (didit)
13203 goto repeat;
13204 }
13205 }
13206
13207 return valid;
13208}
13209
13210/*
13211 * Perform a substitution on "str" with pattern "pat" and substitute "sub".
13212 * "flags" can be "g" to do a global substitute.
13213 * Returns an allocated string, NULL for error.
13214 */
13215 char_u *
13216do_string_sub(str, pat, sub, flags)
13217 char_u *str;
13218 char_u *pat;
13219 char_u *sub;
13220 char_u *flags;
13221{
13222 int sublen;
13223 regmatch_T regmatch;
13224 int i;
13225 int do_all;
13226 char_u *tail;
13227 garray_T ga;
13228 char_u *ret;
13229 char_u *save_cpo;
13230
13231 /* Make 'cpoptions' empty, so that the 'l' flag doesn't work here */
13232 save_cpo = p_cpo;
13233 p_cpo = (char_u *)"";
13234
13235 ga_init2(&ga, 1, 200);
13236
13237 do_all = (flags[0] == 'g');
13238
13239 regmatch.rm_ic = p_ic;
13240 regmatch.regprog = vim_regcomp(pat, RE_MAGIC + RE_STRING);
13241 if (regmatch.regprog != NULL)
13242 {
13243 tail = str;
13244 while (vim_regexec_nl(&regmatch, str, (colnr_T)(tail - str)))
13245 {
13246 /*
13247 * Get some space for a temporary buffer to do the substitution
13248 * into. It will contain:
13249 * - The text up to where the match is.
13250 * - The substituted text.
13251 * - The text after the match.
13252 */
13253 sublen = vim_regsub(&regmatch, sub, tail, FALSE, TRUE, FALSE);
13254 if (ga_grow(&ga, (int)(STRLEN(tail) + sublen -
13255 (regmatch.endp[0] - regmatch.startp[0]))) == FAIL)
13256 {
13257 ga_clear(&ga);
13258 break;
13259 }
13260
13261 /* copy the text up to where the match is */
13262 i = (int)(regmatch.startp[0] - tail);
13263 mch_memmove((char_u *)ga.ga_data + ga.ga_len, tail, (size_t)i);
13264 /* add the substituted text */
13265 (void)vim_regsub(&regmatch, sub, (char_u *)ga.ga_data
13266 + ga.ga_len + i, TRUE, TRUE, FALSE);
13267 ga.ga_len += i + sublen - 1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013268 /* avoid getting stuck on a match with an empty string */
13269 if (tail == regmatch.endp[0])
13270 {
13271 if (*tail == NUL)
13272 break;
13273 *((char_u *)ga.ga_data + ga.ga_len) = *tail++;
13274 ++ga.ga_len;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013275 }
13276 else
13277 {
13278 tail = regmatch.endp[0];
13279 if (*tail == NUL)
13280 break;
13281 }
13282 if (!do_all)
13283 break;
13284 }
13285
13286 if (ga.ga_data != NULL)
13287 STRCPY((char *)ga.ga_data + ga.ga_len, tail);
13288
13289 vim_free(regmatch.regprog);
13290 }
13291
13292 ret = vim_strsave(ga.ga_data == NULL ? str : (char_u *)ga.ga_data);
13293 ga_clear(&ga);
13294 p_cpo = save_cpo;
13295
13296 return ret;
13297}
13298
13299#endif /* defined(FEAT_MODIFY_FNAME) || defined(FEAT_EVAL) */