blob: e812e5329ffc2d2ed0623c96d56f65262a4bd20d [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/*
85 * Structure to hold the info about a list.
86 */
87struct listvar_S
88{
89 int lv_refcount; /* reference count */
90 listitem *lv_first; /* first item, NULL if none */
91 listitem *lv_last; /* last item, NULL if none */
92};
93
94typedef struct listvar_S listvar;
95
96#define VAR_LIST_MAXNEST 100 /* maximum nesting of lists */
Bram Moolenaarc70646c2005-01-04 21:52:38 +000097static char *e_letunexp = N_("E18: Unexpected characters in :let");
98static char *e_listidx = N_("E999: list index out of range: %ld");
99static char *e_undefvar = N_("E121: Undefined variable: %s");
100static char *e_missbrac = N_("E111: Missing ']'");
101static char *e_intern2 = N_("E999: Internal error: %s");
Bram Moolenaar49cd9572005-01-03 21:06:01 +0000102
103/*
Bram Moolenaar071d4272004-06-13 20:20:40 +0000104 * All user-defined global variables are stored in "variables".
105 */
106garray_T variables = {0, 0, sizeof(var), 4, NULL};
107
108/*
109 * Array to hold an array with variables local to each sourced script.
110 */
111static garray_T ga_scripts = {0, 0, sizeof(garray_T), 4, NULL};
112#define SCRIPT_VARS(id) (((garray_T *)ga_scripts.ga_data)[(id) - 1])
113
114
115#define VAR_ENTRY(idx) (((VAR)(variables.ga_data))[idx])
116#define VAR_GAP_ENTRY(idx, gap) (((VAR)(gap->ga_data))[idx])
117#define BVAR_ENTRY(idx) (((VAR)(curbuf->b_vars.ga_data))[idx])
118#define WVAR_ENTRY(idx) (((VAR)(curwin->w_vars.ga_data))[idx])
119
120static int echo_attr = 0; /* attributes used for ":echo" */
121
122/*
123 * Structure to hold info for a user function.
124 */
125typedef struct ufunc ufunc_T;
126
127struct ufunc
128{
129 ufunc_T *next; /* next function in list */
130 char_u *name; /* name of function; can start with <SNR>123_
131 (<SNR> is K_SPECIAL KS_EXTRA KE_SNR) */
132 int varargs; /* variable nr of arguments */
133 int flags;
134 int calls; /* nr of active calls */
135 garray_T args; /* arguments */
136 garray_T lines; /* function lines */
137 scid_T script_ID; /* ID of script where function was defined,
138 used for s: variables */
139};
140
141/* function flags */
142#define FC_ABORT 1 /* abort function on error */
143#define FC_RANGE 2 /* function accepts range */
144
145/*
146 * All user-defined functions are found in the forward-linked function list.
147 * The first function is pointed at by firstfunc.
148 */
149ufunc_T *firstfunc = NULL;
150
151#define FUNCARG(fp, j) ((char_u **)(fp->args.ga_data))[j]
152#define FUNCLINE(fp, j) ((char_u **)(fp->lines.ga_data))[j]
153
154/* structure to hold info for a function that is currently being executed. */
155struct funccall
156{
157 ufunc_T *func; /* function being called */
158 int linenr; /* next line to be executed */
159 int returned; /* ":return" used */
160 int argcount; /* nr of arguments */
Bram Moolenaar49cd9572005-01-03 21:06:01 +0000161 typeval *argvars; /* arguments */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000162 var a0_var; /* "a:0" variable */
163 var firstline; /* "a:firstline" variable */
164 var lastline; /* "a:lastline" variable */
165 garray_T l_vars; /* local function variables */
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000166 typeval *rettv; /* return value */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000167 linenr_T breakpoint; /* next line with breakpoint or zero */
168 int dbg_tick; /* debug_tick when breakpoint was set */
169 int level; /* top nesting level of executed function */
170};
171
172/*
173 * Return the name of the executed function.
174 */
175 char_u *
176func_name(cookie)
177 void *cookie;
178{
179 return ((struct funccall *)cookie)->func->name;
180}
181
182/*
183 * Return the address holding the next breakpoint line for a funccall cookie.
184 */
185 linenr_T *
186func_breakpoint(cookie)
187 void *cookie;
188{
189 return &((struct funccall *)cookie)->breakpoint;
190}
191
192/*
193 * Return the address holding the debug tick for a funccall cookie.
194 */
195 int *
196func_dbg_tick(cookie)
197 void *cookie;
198{
199 return &((struct funccall *)cookie)->dbg_tick;
200}
201
202/*
203 * Return the nesting level for a funccall cookie.
204 */
205 int
206func_level(cookie)
207 void *cookie;
208{
209 return ((struct funccall *)cookie)->level;
210}
211
212/* pointer to funccal for currently active function */
213struct funccall *current_funccal = NULL;
214
215/*
216 * Return TRUE when a function was ended by a ":return" command.
217 */
218 int
219current_func_returned()
220{
221 return current_funccal->returned;
222}
223
224
225/*
226 * Array to hold the value of v: variables.
227 */
228#include "version.h"
229
230/* values for flags: */
Bram Moolenaar7b0294c2004-10-11 10:16:09 +0000231#define VV_COMPAT 1 /* compatible, also used without "v:" */
232#define VV_RO 2 /* read-only */
233#define VV_RO_SBX 4 /* read-only in the sandbox*/
Bram Moolenaar071d4272004-06-13 20:20:40 +0000234
235struct vimvar
236{
237 char *name; /* name of variable, without v: */
238 int len; /* length of name */
239 char_u *val; /* current value (can also be a number!) */
240 char type; /* VAR_NUMBER or VAR_STRING */
Bram Moolenaar7b0294c2004-10-11 10:16:09 +0000241 char flags; /* VV_COMPAT, VV_RO, VV_RO_SBX */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000242} vimvars[VV_LEN] =
243{ /* The order here must match the VV_ defines in vim.h! */
244 {"count", sizeof("count") - 1, NULL, VAR_NUMBER, VV_COMPAT+VV_RO},
245 {"count1", sizeof("count1") - 1, NULL, VAR_NUMBER, VV_RO},
246 {"prevcount", sizeof("prevcount") - 1, NULL, VAR_NUMBER, VV_RO},
247 {"errmsg", sizeof("errmsg") - 1, NULL, VAR_STRING, VV_COMPAT},
248 {"warningmsg", sizeof("warningmsg") - 1, NULL, VAR_STRING, 0},
249 {"statusmsg", sizeof("statusmsg") - 1, NULL, VAR_STRING, 0},
250 {"shell_error", sizeof("shell_error") - 1, NULL, VAR_NUMBER,
251 VV_COMPAT+VV_RO},
252 {"this_session", sizeof("this_session") - 1, NULL, VAR_STRING, VV_COMPAT},
253 {"version", sizeof("version") - 1, (char_u *)VIM_VERSION_100,
254 VAR_NUMBER, VV_COMPAT+VV_RO},
Bram Moolenaar7b0294c2004-10-11 10:16:09 +0000255 {"lnum", sizeof("lnum") - 1, NULL, VAR_NUMBER, VV_RO_SBX},
Bram Moolenaar071d4272004-06-13 20:20:40 +0000256 {"termresponse", sizeof("termresponse") - 1, NULL, VAR_STRING, VV_RO},
257 {"fname", sizeof("fname") - 1, NULL, VAR_STRING, VV_RO},
258 {"lang", sizeof("lang") - 1, NULL, VAR_STRING, VV_RO},
259 {"lc_time", sizeof("lc_time") - 1, NULL, VAR_STRING, VV_RO},
260 {"ctype", sizeof("ctype") - 1, NULL, VAR_STRING, VV_RO},
261 {"charconvert_from", sizeof("charconvert_from") - 1, NULL, VAR_STRING, VV_RO},
262 {"charconvert_to", sizeof("charconvert_to") - 1, NULL, VAR_STRING, VV_RO},
263 {"fname_in", sizeof("fname_in") - 1, NULL, VAR_STRING, VV_RO},
264 {"fname_out", sizeof("fname_out") - 1, NULL, VAR_STRING, VV_RO},
265 {"fname_new", sizeof("fname_new") - 1, NULL, VAR_STRING, VV_RO},
266 {"fname_diff", sizeof("fname_diff") - 1, NULL, VAR_STRING, VV_RO},
267 {"cmdarg", sizeof("cmdarg") - 1, NULL, VAR_STRING, VV_RO},
Bram Moolenaar7b0294c2004-10-11 10:16:09 +0000268 {"foldstart", sizeof("foldstart") - 1, NULL, VAR_NUMBER, VV_RO_SBX},
269 {"foldend", sizeof("foldend") - 1, NULL, VAR_NUMBER, VV_RO_SBX},
270 {"folddashes", sizeof("folddashes") - 1, NULL, VAR_STRING, VV_RO_SBX},
271 {"foldlevel", sizeof("foldlevel") - 1, NULL, VAR_NUMBER, VV_RO_SBX},
Bram Moolenaar071d4272004-06-13 20:20:40 +0000272 {"progname", sizeof("progname") - 1, NULL, VAR_STRING, VV_RO},
273 {"servername", sizeof("servername") - 1, NULL, VAR_STRING, VV_RO},
274 {"dying", sizeof("dying") - 1, NULL, VAR_NUMBER, VV_RO},
275 {"exception", sizeof("exception") - 1, NULL, VAR_STRING, VV_RO},
276 {"throwpoint", sizeof("throwpoint") - 1, NULL, VAR_STRING, VV_RO},
277 {"register", sizeof("register") - 1, NULL, VAR_STRING, VV_RO},
278 {"cmdbang", sizeof("cmdbang") - 1, NULL, VAR_NUMBER, VV_RO},
Bram Moolenaar843ee412004-06-30 16:16:41 +0000279 {"insertmode", sizeof("insertmode") - 1, NULL, VAR_STRING, VV_RO},
Bram Moolenaar071d4272004-06-13 20:20:40 +0000280};
281
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000282static int eval0 __ARGS((char_u *arg, typeval *rettv, char_u **nextcmd, int evaluate));
283static int eval1 __ARGS((char_u **arg, typeval *rettv, int evaluate));
284static int eval2 __ARGS((char_u **arg, typeval *rettv, int evaluate));
285static int eval3 __ARGS((char_u **arg, typeval *rettv, int evaluate));
286static int eval4 __ARGS((char_u **arg, typeval *rettv, int evaluate));
287static int eval5 __ARGS((char_u **arg, typeval *rettv, int evaluate));
288static int eval6 __ARGS((char_u **arg, typeval *rettv, int evaluate));
289static int eval7 __ARGS((char_u **arg, typeval *rettv, int evaluate));
290static int eval_index __ARGS((char_u **arg, typeval *rettv, int evaluate));
291static int get_option_tv __ARGS((char_u **arg, typeval *rettv, int evaluate));
292static int get_string_tv __ARGS((char_u **arg, typeval *rettv, int evaluate));
293static int get_lit_string_tv __ARGS((char_u **arg, typeval *rettv, int evaluate));
294static int get_list_tv __ARGS((char_u **arg, typeval *rettv, int evaluate));
Bram Moolenaar49cd9572005-01-03 21:06:01 +0000295static listvar *list_alloc __ARGS((void));
296static void list_unref __ARGS((listvar *l));
297static void list_free __ARGS((listvar *l));
298static listitem *listitem_alloc __ARGS((void));
299static void listitem_free __ARGS((listitem *item));
300static long list_len __ARGS((listvar *l));
301static listitem *list_find __ARGS((listvar *l, long n));
302static void list_append __ARGS((listvar *l, listitem *item));
303static int list_append_tv __ARGS((listvar *l, typeval *tv));
304static listvar *list_copy __ARGS((listvar *orig, int deep));
305static listitem *list_getrem __ARGS((listvar *l, long n));
306static char_u *list2string __ARGS((typeval *tv));
307static char_u *tv2string __ARGS((typeval *tv, char_u **tofree));
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000308static int get_env_tv __ARGS((char_u **arg, typeval *rettv, int evaluate));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000309static int find_internal_func __ARGS((char_u *name));
Bram Moolenaar49cd9572005-01-03 21:06:01 +0000310static char_u *deref_func_name __ARGS((char_u *name, int *lenp));
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000311static 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));
312static 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));
313static void f_append __ARGS((typeval *argvars, typeval *rettv));
314static void f_argc __ARGS((typeval *argvars, typeval *rettv));
315static void f_argidx __ARGS((typeval *argvars, typeval *rettv));
316static void f_argv __ARGS((typeval *argvars, typeval *rettv));
317static void f_browse __ARGS((typeval *argvars, typeval *rettv));
318static void f_browsedir __ARGS((typeval *argvars, typeval *rettv));
Bram Moolenaar49cd9572005-01-03 21:06:01 +0000319static buf_T *find_buffer __ARGS((typeval *avar));
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000320static void f_bufexists __ARGS((typeval *argvars, typeval *rettv));
321static void f_buflisted __ARGS((typeval *argvars, typeval *rettv));
322static void f_bufloaded __ARGS((typeval *argvars, typeval *rettv));
323static buf_T *get_buf_tv __ARGS((typeval *tv));
324static void f_bufname __ARGS((typeval *argvars, typeval *rettv));
325static void f_bufnr __ARGS((typeval *argvars, typeval *rettv));
326static void f_bufwinnr __ARGS((typeval *argvars, typeval *rettv));
327static void f_byte2line __ARGS((typeval *argvars, typeval *rettv));
328static void f_byteidx __ARGS((typeval *argvars, typeval *rettv));
329static void f_char2nr __ARGS((typeval *argvars, typeval *rettv));
330static void f_cindent __ARGS((typeval *argvars, typeval *rettv));
331static void f_col __ARGS((typeval *argvars, typeval *rettv));
332static void f_confirm __ARGS((typeval *argvars, typeval *rettv));
333static void f_copy __ARGS((typeval *argvars, typeval *rettv));
334static void f_cscope_connection __ARGS((typeval *argvars, typeval *rettv));
335static void f_cursor __ARGS((typeval *argsvars, typeval *rettv));
336static void f_deepcopy __ARGS((typeval *argvars, typeval *rettv));
337static void f_delete __ARGS((typeval *argvars, typeval *rettv));
338static void f_did_filetype __ARGS((typeval *argvars, typeval *rettv));
339static void f_diff_filler __ARGS((typeval *argvars, typeval *rettv));
340static void f_diff_hlID __ARGS((typeval *argvars, typeval *rettv));
341static void f_escape __ARGS((typeval *argvars, typeval *rettv));
342static void f_eventhandler __ARGS((typeval *argvars, typeval *rettv));
343static void f_executable __ARGS((typeval *argvars, typeval *rettv));
344static void f_exists __ARGS((typeval *argvars, typeval *rettv));
345static void f_expand __ARGS((typeval *argvars, typeval *rettv));
346static void f_filereadable __ARGS((typeval *argvars, typeval *rettv));
347static void f_filewritable __ARGS((typeval *argvars, typeval *rettv));
348static void f_finddir __ARGS((typeval *argvars, typeval *rettv));
349static void f_findfile __ARGS((typeval *argvars, typeval *rettv));
350static void f_findfilendir __ARGS((typeval *argvars, typeval *rettv, int dir));
351static void f_fnamemodify __ARGS((typeval *argvars, typeval *rettv));
352static void f_foldclosed __ARGS((typeval *argvars, typeval *rettv));
353static void f_foldclosedend __ARGS((typeval *argvars, typeval *rettv));
354static void foldclosed_both __ARGS((typeval *argvars, typeval *rettv, int end));
355static void f_foldlevel __ARGS((typeval *argvars, typeval *rettv));
356static void f_foldtext __ARGS((typeval *argvars, typeval *rettv));
357static void f_foldtextresult __ARGS((typeval *argvars, typeval *rettv));
358static void f_foreground __ARGS((typeval *argvars, typeval *rettv));
359static void f_function __ARGS((typeval *argvars, typeval *rettv));
360static void f_getbufvar __ARGS((typeval *argvars, typeval *rettv));
361static void f_getchar __ARGS((typeval *argvars, typeval *rettv));
362static void f_getcharmod __ARGS((typeval *argvars, typeval *rettv));
363static void f_getcmdline __ARGS((typeval *argvars, typeval *rettv));
364static void f_getcmdpos __ARGS((typeval *argvars, typeval *rettv));
365static void f_getcwd __ARGS((typeval *argvars, typeval *rettv));
366static void f_getfontname __ARGS((typeval *argvars, typeval *rettv));
367static void f_getfperm __ARGS((typeval *argvars, typeval *rettv));
368static void f_getfsize __ARGS((typeval *argvars, typeval *rettv));
369static void f_getftime __ARGS((typeval *argvars, typeval *rettv));
370static void f_getftype __ARGS((typeval *argvars, typeval *rettv));
371static void f_getline __ARGS((typeval *argvars, typeval *rettv));
372static void f_getreg __ARGS((typeval *argvars, typeval *rettv));
373static void f_getregtype __ARGS((typeval *argvars, typeval *rettv));
374static void f_getwinposx __ARGS((typeval *argvars, typeval *rettv));
375static void f_getwinposy __ARGS((typeval *argvars, typeval *rettv));
376static void f_getwinvar __ARGS((typeval *argvars, typeval *rettv));
377static void f_glob __ARGS((typeval *argvars, typeval *rettv));
378static void f_globpath __ARGS((typeval *argvars, typeval *rettv));
379static void f_has __ARGS((typeval *argvars, typeval *rettv));
380static void f_hasmapto __ARGS((typeval *argvars, typeval *rettv));
381static void f_histadd __ARGS((typeval *argvars, typeval *rettv));
382static void f_histdel __ARGS((typeval *argvars, typeval *rettv));
383static void f_histget __ARGS((typeval *argvars, typeval *rettv));
384static void f_histnr __ARGS((typeval *argvars, typeval *rettv));
385static void f_hlexists __ARGS((typeval *argvars, typeval *rettv));
386static void f_hlID __ARGS((typeval *argvars, typeval *rettv));
387static void f_hostname __ARGS((typeval *argvars, typeval *rettv));
388static void f_iconv __ARGS((typeval *argvars, typeval *rettv));
389static void f_indent __ARGS((typeval *argvars, typeval *rettv));
390static void f_insert __ARGS((typeval *argvars, typeval *rettv));
391static void f_isdirectory __ARGS((typeval *argvars, typeval *rettv));
392static void f_input __ARGS((typeval *argvars, typeval *rettv));
393static void f_inputdialog __ARGS((typeval *argvars, typeval *rettv));
394static void f_inputrestore __ARGS((typeval *argvars, typeval *rettv));
395static void f_inputsave __ARGS((typeval *argvars, typeval *rettv));
396static void f_inputsecret __ARGS((typeval *argvars, typeval *rettv));
397static void f_last_buffer_nr __ARGS((typeval *argvars, typeval *rettv));
398static void f_len __ARGS((typeval *argvars, typeval *rettv));
399static void f_libcall __ARGS((typeval *argvars, typeval *rettv));
400static void f_libcallnr __ARGS((typeval *argvars, typeval *rettv));
401static void libcall_common __ARGS((typeval *argvars, typeval *rettv, int type));
402static void f_line __ARGS((typeval *argvars, typeval *rettv));
403static void f_line2byte __ARGS((typeval *argvars, typeval *rettv));
404static void f_lispindent __ARGS((typeval *argvars, typeval *rettv));
405static void f_localtime __ARGS((typeval *argvars, typeval *rettv));
406static void f_maparg __ARGS((typeval *argvars, typeval *rettv));
407static void f_mapcheck __ARGS((typeval *argvars, typeval *rettv));
408static void get_maparg __ARGS((typeval *argvars, typeval *rettv, int exact));
409static void f_match __ARGS((typeval *argvars, typeval *rettv));
410static void f_matchend __ARGS((typeval *argvars, typeval *rettv));
411static void f_matchstr __ARGS((typeval *argvars, typeval *rettv));
412static void f_mode __ARGS((typeval *argvars, typeval *rettv));
413static void f_nextnonblank __ARGS((typeval *argvars, typeval *rettv));
414static void f_nr2char __ARGS((typeval *argvars, typeval *rettv));
415static void f_prevnonblank __ARGS((typeval *argvars, typeval *rettv));
416static void f_setbufvar __ARGS((typeval *argvars, typeval *rettv));
417static void f_setcmdpos __ARGS((typeval *argvars, typeval *rettv));
418static void f_setwinvar __ARGS((typeval *argvars, typeval *rettv));
419static void f_remove __ARGS((typeval *argvars, typeval *rettv));
420static void f_rename __ARGS((typeval *argvars, typeval *rettv));
421static void f_resolve __ARGS((typeval *argvars, typeval *rettv));
422static void f_search __ARGS((typeval *argvars, typeval *rettv));
423static void f_searchpair __ARGS((typeval *argvars, typeval *rettv));
Bram Moolenaar49cd9572005-01-03 21:06:01 +0000424static int get_search_arg __ARGS((typeval *varp, int *flagsp));
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000425static void f_remote_expr __ARGS((typeval *argvars, typeval *rettv));
426static void f_remote_foreground __ARGS((typeval *argvars, typeval *rettv));
427static void f_remote_peek __ARGS((typeval *argvars, typeval *rettv));
428static void f_remote_read __ARGS((typeval *argvars, typeval *rettv));
429static void f_remote_send __ARGS((typeval *argvars, typeval *rettv));
430static void f_repeat __ARGS((typeval *argvars, typeval *rettv));
431static void f_server2client __ARGS((typeval *argvars, typeval *rettv));
432static void f_serverlist __ARGS((typeval *argvars, typeval *rettv));
433static void f_setline __ARGS((typeval *argvars, typeval *rettv));
434static void f_setreg __ARGS((typeval *argvars, typeval *rettv));
435static void f_simplify __ARGS((typeval *argvars, typeval *rettv));
436static void find_some_match __ARGS((typeval *argvars, typeval *rettv, int start));
437static void f_strftime __ARGS((typeval *argvars, typeval *rettv));
438static void f_stridx __ARGS((typeval *argvars, typeval *rettv));
439static void f_string __ARGS((typeval *argvars, typeval *rettv));
440static void f_strlen __ARGS((typeval *argvars, typeval *rettv));
441static void f_strpart __ARGS((typeval *argvars, typeval *rettv));
442static void f_strridx __ARGS((typeval *argvars, typeval *rettv));
443static void f_strtrans __ARGS((typeval *argvars, typeval *rettv));
444static void f_synID __ARGS((typeval *argvars, typeval *rettv));
445static void f_synIDattr __ARGS((typeval *argvars, typeval *rettv));
446static void f_synIDtrans __ARGS((typeval *argvars, typeval *rettv));
447static void f_system __ARGS((typeval *argvars, typeval *rettv));
448static void f_submatch __ARGS((typeval *argvars, typeval *rettv));
449static void f_substitute __ARGS((typeval *argvars, typeval *rettv));
450static void f_tempname __ARGS((typeval *argvars, typeval *rettv));
451static void f_tolower __ARGS((typeval *argvars, typeval *rettv));
452static void f_toupper __ARGS((typeval *argvars, typeval *rettv));
453static void f_tr __ARGS((typeval *argvars, typeval *rettv));
454static void f_type __ARGS((typeval *argvars, typeval *rettv));
455static void f_virtcol __ARGS((typeval *argvars, typeval *rettv));
456static void f_visualmode __ARGS((typeval *argvars, typeval *rettv));
457static void f_winbufnr __ARGS((typeval *argvars, typeval *rettv));
458static void f_wincol __ARGS((typeval *argvars, typeval *rettv));
459static void f_winheight __ARGS((typeval *argvars, typeval *rettv));
460static void f_winline __ARGS((typeval *argvars, typeval *rettv));
461static void f_winnr __ARGS((typeval *argvars, typeval *rettv));
462static void f_winrestcmd __ARGS((typeval *argvars, typeval *rettv));
463static void f_winwidth __ARGS((typeval *argvars, typeval *rettv));
Bram Moolenaar49cd9572005-01-03 21:06:01 +0000464static win_T *find_win_by_nr __ARGS((typeval *vp));
465static pos_T *var2fpos __ARGS((typeval *varp, int lnum));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000466static int get_env_len __ARGS((char_u **arg));
467static int get_id_len __ARGS((char_u **arg));
468static int get_func_len __ARGS((char_u **arg, char_u **alias, int evaluate));
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000469static 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 +0000470static int eval_isnamec __ARGS((int c));
471static int find_vim_var __ARGS((char_u *name, int len));
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000472static int get_var_tv __ARGS((char_u *name, int len, typeval *rettv));
473static typeval *alloc_tv __ARGS((void));
474static typeval *alloc_string_tv __ARGS((char_u *string));
475static void free_tv __ARGS((typeval *varp));
476static void clear_tv __ARGS((typeval *varp));
477static void init_tv __ARGS((typeval *varp));
478static long get_tv_number __ARGS((typeval *varp));
479static linenr_T get_tv_lnum __ARGS((typeval *argvars));
480static char_u *get_tv_string __ARGS((typeval *varp));
481static char_u *get_tv_string_buf __ARGS((typeval *varp, char_u *buf));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000482static VAR find_var __ARGS((char_u *name, int writing));
483static VAR find_var_in_ga __ARGS((garray_T *gap, char_u *varname));
484static garray_T *find_var_ga __ARGS((char_u *name, char_u **varname));
Bram Moolenaar49cd9572005-01-03 21:06:01 +0000485static void clear_var __ARGS((VAR v));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000486static void list_one_var __ARGS((VAR v, char_u *prefix));
487static void list_vim_var __ARGS((int i));
488static void list_one_var_a __ARGS((char_u *prefix, char_u *name, int type, char_u *string));
Bram Moolenaar49cd9572005-01-03 21:06:01 +0000489static void set_var __ARGS((char_u *name, typeval *varp, int copy));
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000490static void copy_tv __ARGS((typeval *from, typeval *to));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000491static char_u *find_option_end __ARGS((char_u **arg, int *opt_flags));
492static char_u *trans_function_name __ARGS((char_u **pp, int skip, int internal));
493static int eval_fname_script __ARGS((char_u *p));
494static int eval_fname_sid __ARGS((char_u *p));
495static void list_func_head __ARGS((ufunc_T *fp, int indent));
496static void cat_func_name __ARGS((char_u *buf, ufunc_T *fp));
497static ufunc_T *find_func __ARGS((char_u *name));
Bram Moolenaar49cd9572005-01-03 21:06:01 +0000498static int function_exists __ARGS((char_u *name));
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000499static 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 +0000500
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000501#define get_var_string(p) get_tv_string(&(p)->tv)
502#define get_var_string_buf(p, b) get_tv_string_buf(&(p)->tv, (b))
503#define get_var_number(p) get_tv_number(&((p)->tv))
Bram Moolenaar071d4272004-06-13 20:20:40 +0000504
Bram Moolenaar071d4272004-06-13 20:20:40 +0000505static 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 +0000506
507static void list_all_vars __ARGS((void));
508static char_u *list_arg_vars __ARGS((exarg_T *eap, char_u *arg));
509static char_u *ex_let_one __ARGS((char_u *arg, typeval *tv, int copy, char_u *endchars));
510static char_u *set_var_idx __ARGS((char_u *name, char_u *ip, typeval *rettv, int copy, char_u *endchars));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000511
512/*
513 * Set an internal variable to a string value. Creates the variable if it does
514 * not already exist.
515 */
516 void
517set_internal_string_var(name, value)
518 char_u *name;
519 char_u *value;
520{
Bram Moolenaar49cd9572005-01-03 21:06:01 +0000521 char_u *val;
522 typeval *tvp;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000523
524 val = vim_strsave(value);
525 if (val != NULL)
526 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000527 tvp = alloc_string_tv(val);
Bram Moolenaar49cd9572005-01-03 21:06:01 +0000528 if (tvp != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000529 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +0000530 set_var(name, tvp, FALSE);
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000531 free_tv(tvp);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000532 }
533 }
534}
535
536# if defined(FEAT_MBYTE) || defined(PROTO)
537 int
538eval_charconvert(enc_from, enc_to, fname_from, fname_to)
539 char_u *enc_from;
540 char_u *enc_to;
541 char_u *fname_from;
542 char_u *fname_to;
543{
544 int err = FALSE;
545
546 set_vim_var_string(VV_CC_FROM, enc_from, -1);
547 set_vim_var_string(VV_CC_TO, enc_to, -1);
548 set_vim_var_string(VV_FNAME_IN, fname_from, -1);
549 set_vim_var_string(VV_FNAME_OUT, fname_to, -1);
550 if (eval_to_bool(p_ccv, &err, NULL, FALSE))
551 err = TRUE;
552 set_vim_var_string(VV_CC_FROM, NULL, -1);
553 set_vim_var_string(VV_CC_TO, NULL, -1);
554 set_vim_var_string(VV_FNAME_IN, NULL, -1);
555 set_vim_var_string(VV_FNAME_OUT, NULL, -1);
556
557 if (err)
558 return FAIL;
559 return OK;
560}
561# endif
562
563# if defined(FEAT_POSTSCRIPT) || defined(PROTO)
564 int
565eval_printexpr(fname, args)
566 char_u *fname;
567 char_u *args;
568{
569 int err = FALSE;
570
571 set_vim_var_string(VV_FNAME_IN, fname, -1);
572 set_vim_var_string(VV_CMDARG, args, -1);
573 if (eval_to_bool(p_pexpr, &err, NULL, FALSE))
574 err = TRUE;
575 set_vim_var_string(VV_FNAME_IN, NULL, -1);
576 set_vim_var_string(VV_CMDARG, NULL, -1);
577
578 if (err)
579 {
580 mch_remove(fname);
581 return FAIL;
582 }
583 return OK;
584}
585# endif
586
587# if defined(FEAT_DIFF) || defined(PROTO)
588 void
589eval_diff(origfile, newfile, outfile)
590 char_u *origfile;
591 char_u *newfile;
592 char_u *outfile;
593{
594 int err = FALSE;
595
596 set_vim_var_string(VV_FNAME_IN, origfile, -1);
597 set_vim_var_string(VV_FNAME_NEW, newfile, -1);
598 set_vim_var_string(VV_FNAME_OUT, outfile, -1);
599 (void)eval_to_bool(p_dex, &err, NULL, FALSE);
600 set_vim_var_string(VV_FNAME_IN, NULL, -1);
601 set_vim_var_string(VV_FNAME_NEW, NULL, -1);
602 set_vim_var_string(VV_FNAME_OUT, NULL, -1);
603}
604
605 void
606eval_patch(origfile, difffile, outfile)
607 char_u *origfile;
608 char_u *difffile;
609 char_u *outfile;
610{
611 int err;
612
613 set_vim_var_string(VV_FNAME_IN, origfile, -1);
614 set_vim_var_string(VV_FNAME_DIFF, difffile, -1);
615 set_vim_var_string(VV_FNAME_OUT, outfile, -1);
616 (void)eval_to_bool(p_pex, &err, NULL, FALSE);
617 set_vim_var_string(VV_FNAME_IN, NULL, -1);
618 set_vim_var_string(VV_FNAME_DIFF, NULL, -1);
619 set_vim_var_string(VV_FNAME_OUT, NULL, -1);
620}
621# endif
622
623/*
624 * Top level evaluation function, returning a boolean.
625 * Sets "error" to TRUE if there was an error.
626 * Return TRUE or FALSE.
627 */
628 int
629eval_to_bool(arg, error, nextcmd, skip)
630 char_u *arg;
631 int *error;
632 char_u **nextcmd;
633 int skip; /* only parse, don't execute */
634{
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000635 typeval tv;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000636 int retval = FALSE;
637
638 if (skip)
639 ++emsg_skip;
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000640 if (eval0(arg, &tv, nextcmd, !skip) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000641 *error = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000642 else
643 {
644 *error = FALSE;
645 if (!skip)
646 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000647 retval = (get_tv_number(&tv) != 0);
648 clear_tv(&tv);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000649 }
650 }
651 if (skip)
652 --emsg_skip;
653
654 return retval;
655}
656
657/*
658 * Top level evaluation function, returning a string. If "skip" is TRUE,
659 * only parsing to "nextcmd" is done, without reporting errors. Return
660 * pointer to allocated memory, or NULL for failure or when "skip" is TRUE.
661 */
662 char_u *
663eval_to_string_skip(arg, nextcmd, skip)
664 char_u *arg;
665 char_u **nextcmd;
666 int skip; /* only parse, don't execute */
667{
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000668 typeval tv;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000669 char_u *retval;
670
671 if (skip)
672 ++emsg_skip;
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000673 if (eval0(arg, &tv, nextcmd, !skip) == FAIL || skip)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000674 retval = NULL;
675 else
676 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000677 retval = vim_strsave(get_tv_string(&tv));
678 clear_tv(&tv);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000679 }
680 if (skip)
681 --emsg_skip;
682
683 return retval;
684}
685
686/*
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000687 * Skip over an expression at "*pp".
688 * Return FAIL for an error, OK otherwise.
689 */
690 int
691skip_expr(pp)
692 char_u **pp;
693{
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000694 typeval rettv;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000695
696 *pp = skipwhite(*pp);
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000697 return eval1(pp, &rettv, FALSE);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000698}
699
700/*
Bram Moolenaar071d4272004-06-13 20:20:40 +0000701 * Top level evaluation function, returning a string.
702 * Return pointer to allocated memory, or NULL for failure.
703 */
704 char_u *
705eval_to_string(arg, nextcmd)
706 char_u *arg;
707 char_u **nextcmd;
708{
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000709 typeval tv;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000710 char_u *retval;
711
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000712 if (eval0(arg, &tv, nextcmd, TRUE) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000713 retval = NULL;
714 else
715 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000716 retval = vim_strsave(get_tv_string(&tv));
717 clear_tv(&tv);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000718 }
719
720 return retval;
721}
722
723/*
724 * Call eval_to_string() with "sandbox" set and not using local variables.
725 */
726 char_u *
727eval_to_string_safe(arg, nextcmd)
728 char_u *arg;
729 char_u **nextcmd;
730{
731 char_u *retval;
732 void *save_funccalp;
733
734 save_funccalp = save_funccal();
735 ++sandbox;
736 retval = eval_to_string(arg, nextcmd);
737 --sandbox;
738 restore_funccal(save_funccalp);
739 return retval;
740}
741
742#if 0 /* not used */
743/*
744 * Top level evaluation function, returning a string.
745 * Advances "arg" to the first non-blank after the evaluated expression.
746 * Return pointer to allocated memory, or NULL for failure.
747 * Doesn't give error messages.
748 */
749 char_u *
750eval_arg_to_string(arg)
751 char_u **arg;
752{
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000753 typeval rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000754 char_u *retval;
755 int ret;
756
757 ++emsg_off;
758
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000759 ret = eval1(arg, &rettv, TRUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000760 if (ret == FAIL)
761 retval = NULL;
762 else
763 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000764 retval = vim_strsave(get_tv_string(&rettv));
765 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000766 }
767
768 --emsg_off;
769
770 return retval;
771}
772#endif
773
774/*
775 * Top level evaluation function, returning a number.
776 * Evaluates "expr" silently.
777 * Returns -1 for an error.
778 */
779 int
780eval_to_number(expr)
781 char_u *expr;
782{
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000783 typeval rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000784 int retval;
785 char_u *p = expr;
786
787 ++emsg_off;
788
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000789 if (eval1(&p, &rettv, TRUE) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000790 retval = -1;
791 else
792 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000793 retval = get_tv_number(&rettv);
794 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000795 }
796 --emsg_off;
797
798 return retval;
799}
800
801#if (defined(FEAT_USR_CMDS) && defined(FEAT_CMDL_COMPL)) || defined(PROTO)
802/*
803 * Call some vimL function and return the result as a string
804 * Uses argv[argc] for the function arguments.
805 */
806 char_u *
807call_vim_function(func, argc, argv, safe)
808 char_u *func;
809 int argc;
810 char_u **argv;
811 int safe; /* use the sandbox */
812{
813 char_u *retval = NULL;
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000814 typeval rettv;
Bram Moolenaar49cd9572005-01-03 21:06:01 +0000815 typeval *argvars;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000816 long n;
817 int len;
818 int i;
819 int doesrange;
820 void *save_funccalp = NULL;
821
Bram Moolenaar49cd9572005-01-03 21:06:01 +0000822 argvars = (typeval *)alloc((unsigned)(argc * sizeof(typeval)));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000823 if (argvars == NULL)
824 return NULL;
825
826 for (i = 0; i < argc; i++)
827 {
Bram Moolenaarcfbc5ee2004-07-02 15:38:35 +0000828 /* Pass a NULL or empty argument as an empty string */
829 if (argv[i] == NULL || *argv[i] == NUL)
830 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +0000831 argvars[i].v_type = VAR_STRING;
832 argvars[i].vval.v_string = (char_u *)"";
Bram Moolenaarcfbc5ee2004-07-02 15:38:35 +0000833 continue;
834 }
835
Bram Moolenaar071d4272004-06-13 20:20:40 +0000836 /* Recognize a number argument, the others must be strings. */
837 vim_str2nr(argv[i], NULL, &len, TRUE, TRUE, &n, NULL);
838 if (len != 0 && len == (int)STRLEN(argv[i]))
839 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +0000840 argvars[i].v_type = VAR_NUMBER;
841 argvars[i].vval.v_number = n;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000842 }
843 else
844 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +0000845 argvars[i].v_type = VAR_STRING;
846 argvars[i].vval.v_string = argv[i];
Bram Moolenaar071d4272004-06-13 20:20:40 +0000847 }
848 }
849
850 if (safe)
851 {
852 save_funccalp = save_funccal();
853 ++sandbox;
854 }
855
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000856 rettv.v_type = VAR_UNKNOWN; /* clear_tv() uses this */
857 if (call_func(func, (int)STRLEN(func), &rettv, argc, argvars,
Bram Moolenaar071d4272004-06-13 20:20:40 +0000858 curwin->w_cursor.lnum, curwin->w_cursor.lnum,
859 &doesrange, TRUE) == OK)
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000860 retval = vim_strsave(get_tv_string(&rettv));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000861
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000862 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000863 vim_free(argvars);
864
865 if (safe)
866 {
867 --sandbox;
868 restore_funccal(save_funccalp);
869 }
870 return retval;
871}
872#endif
873
874/*
875 * Save the current function call pointer, and set it to NULL.
876 * Used when executing autocommands and for ":source".
877 */
878 void *
879save_funccal()
880{
881 struct funccall *fc;
882
883 fc = current_funccal;
884 current_funccal = NULL;
885 return (void *)fc;
886}
887
888 void
889restore_funccal(fc)
890 void *fc;
891{
892 current_funccal = (struct funccall *)fc;
893}
894
895#ifdef FEAT_FOLDING
896/*
897 * Evaluate 'foldexpr'. Returns the foldlevel, and any character preceding
898 * it in "*cp". Doesn't give error messages.
899 */
900 int
901eval_foldexpr(arg, cp)
902 char_u *arg;
903 int *cp;
904{
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000905 typeval tv;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000906 int retval;
907 char_u *s;
908
909 ++emsg_off;
910 ++sandbox;
911 *cp = NUL;
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000912 if (eval0(arg, &tv, NULL, TRUE) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000913 retval = 0;
914 else
915 {
916 /* If the result is a number, just return the number. */
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000917 if (tv.v_type == VAR_NUMBER)
918 retval = tv.vval.v_number;
919 else if (tv.v_type == VAR_UNKNOWN
920 || tv.vval.v_string == NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000921 retval = 0;
922 else
923 {
924 /* If the result is a string, check if there is a non-digit before
925 * the number. */
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000926 s = tv.vval.v_string;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000927 if (!VIM_ISDIGIT(*s) && *s != '-')
928 *cp = *s++;
929 retval = atol((char *)s);
930 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000931 clear_tv(&tv);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000932 }
933 --emsg_off;
934 --sandbox;
935
936 return retval;
937}
938#endif
939
Bram Moolenaar071d4272004-06-13 20:20:40 +0000940/*
941 * Expands out the 'magic' {}'s in a variable/function name.
942 * Note that this can call itself recursively, to deal with
943 * constructs like foo{bar}{baz}{bam}
944 * The four pointer arguments point to "foo{expre}ss{ion}bar"
945 * "in_start" ^
946 * "expr_start" ^
947 * "expr_end" ^
948 * "in_end" ^
949 *
950 * Returns a new allocated string, which the caller must free.
951 * Returns NULL for failure.
952 */
953 static char_u *
954make_expanded_name(in_start, expr_start, expr_end, in_end)
955 char_u *in_start;
956 char_u *expr_start;
957 char_u *expr_end;
958 char_u *in_end;
959{
960 char_u c1;
961 char_u *retval = NULL;
962 char_u *temp_result;
963 char_u *nextcmd = NULL;
964
965 if (expr_end == NULL || in_end == NULL)
966 return NULL;
967 *expr_start = NUL;
968 *expr_end = NUL;
969 c1 = *in_end;
970 *in_end = NUL;
971
972 temp_result = eval_to_string(expr_start + 1, &nextcmd);
973 if (temp_result != NULL && nextcmd == NULL)
974 {
975 retval = alloc((unsigned)(STRLEN(temp_result) + (expr_start - in_start)
976 + (in_end - expr_end) + 1));
977
978 if (retval != NULL)
979 {
980 STRCPY(retval, in_start);
981 STRCAT(retval, temp_result);
982 STRCAT(retval, expr_end + 1);
983 }
984 }
985 vim_free(temp_result);
986
987 *in_end = c1; /* put char back for error messages */
988 *expr_start = '{';
989 *expr_end = '}';
990
991 if (retval != NULL)
992 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000993 temp_result = find_name_end(retval, &expr_start, &expr_end, FALSE);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000994 if (expr_start != NULL)
995 {
996 /* Further expansion! */
997 temp_result = make_expanded_name(retval, expr_start,
998 expr_end, temp_result);
999 vim_free(retval);
1000 retval = temp_result;
1001 }
1002 }
1003
1004 return retval;
1005
1006}
Bram Moolenaar071d4272004-06-13 20:20:40 +00001007
1008/*
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001009 * ":let" list all variable values
1010 * ":let var1 var2" list variable values
1011 * ":let var = expr" assignment command.
1012 * ":let [var1, var2] = expr" unpack list.
Bram Moolenaar071d4272004-06-13 20:20:40 +00001013 */
1014 void
1015ex_let(eap)
1016 exarg_T *eap;
1017{
1018 char_u *arg = eap->arg;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001019 char_u *expr = NULL;
1020 typeval rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001021 int i;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001022 int var_count = 0;
1023 int semicolon = 0;
1024 listvar *l;
1025 listitem *item;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001026
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001027 if (*arg != '[')
1028 expr = vim_strchr(find_name_end(arg, NULL, NULL, TRUE), '=');
1029 if (*arg != '[' && expr == NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001030 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001031 if (!ends_excmd(*arg))
1032 /* ":let var1 var2" */
1033 arg = list_arg_vars(eap, arg);
1034 else if (!eap->skip)
1035 /* ":let" */
1036 list_all_vars();
Bram Moolenaar071d4272004-06-13 20:20:40 +00001037 eap->nextcmd = check_nextcmd(arg);
1038 }
1039 else
1040 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001041 if (*arg == '[')
1042 {
1043 /* ":let [a, b] = expr": find the matching ']' to get to the
1044 * expression. */
1045 while (1)
1046 {
1047 arg = skipwhite(arg + 1);
1048 if (vim_strchr((char_u *)"$@&", *arg) != NULL)
1049 ++arg;
1050 expr = find_name_end(arg, NULL, NULL, TRUE);
1051 if (expr == arg)
1052 {
1053 EMSG2(_(e_invarg2), arg);
1054 return;
1055 }
1056 ++var_count;
1057
1058 arg = skipwhite(expr);
1059 if (*arg == ']')
1060 break;
1061 else if (*arg == ';')
1062 {
1063 if (semicolon == 1)
1064 {
1065 EMSG(_("Double ; in :let"));
1066 return;
1067 }
1068 semicolon = 1;
1069 }
1070 else if (*arg != ',')
1071 {
1072 EMSG2(_(e_invarg2), arg);
1073 return;
1074 }
1075 }
1076
1077 /* check for '=' after the ']' */
1078 expr = skipwhite(arg + 1);
1079 if (*expr != '=')
1080 {
1081 EMSG(_(e_letunexp));
1082 return;
1083 }
1084 }
1085
Bram Moolenaar071d4272004-06-13 20:20:40 +00001086 if (eap->skip)
1087 ++emsg_skip;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001088 i = eval0(expr + 1, &rettv, &eap->nextcmd, !eap->skip);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001089 if (eap->skip)
1090 {
1091 if (i != FAIL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001092 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001093 --emsg_skip;
1094 }
1095 else if (i != FAIL)
1096 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001097 /* Move "arg" back to the variable name(s). */
1098 arg = eap->arg;
1099 if (*arg != '[')
Bram Moolenaar071d4272004-06-13 20:20:40 +00001100 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001101 /* ":let var = expr" */
1102 (void)ex_let_one(arg, &rettv, FALSE, (char_u *)"=");
Bram Moolenaar071d4272004-06-13 20:20:40 +00001103 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001104 else
1105 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001106 /* ":let [v1, v2] = list" */
1107 l = rettv.vval.v_list;
1108 if (rettv.v_type != VAR_LIST || l == NULL)
1109 EMSG(_("E999: List required"));
1110 else
1111 {
1112 i = list_len(l);
1113 if (semicolon == 0 && var_count < i)
1114 EMSG(_("E999: Less targets than List items"));
1115 else if (var_count - semicolon > i)
1116 EMSG(_("E999: More targets than List items"));
1117 else
1118 {
1119 item = l->lv_first;
1120 while (*arg != ']')
1121 {
1122 arg = skipwhite(arg + 1);
1123 arg = ex_let_one(arg, &item->li_tv,
1124 TRUE, (char_u *)",;]");
1125 item = item->li_next;
1126 if (arg == NULL)
1127 break;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001128
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001129 arg = skipwhite(arg);
1130 if (*arg == ';')
1131 {
1132 /* Put the rest of the list (may be empty) in
1133 * the var after ';'. */
1134 l = list_alloc();
1135 if (l == NULL)
1136 break;
1137 while (item != NULL)
1138 {
1139 list_append_tv(l, &item->li_tv);
1140 item = item->li_next;
1141 }
1142 list_unref(rettv.vval.v_list);
1143 rettv.vval.v_list = l;
1144 l->lv_refcount = 1;
1145 (void)ex_let_one(skipwhite(arg + 1), &rettv,
1146 FALSE, (char_u *)"]");
1147 break;
1148 }
1149 else if (*arg != ',' && *arg != ']')
1150 {
1151 EMSG2(_(e_intern2), "ex_let()");
1152 break;
1153 }
1154 }
1155 }
1156 }
1157 }
1158 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001159 }
1160 }
1161}
1162
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001163 static void
1164list_all_vars()
1165{
1166 int i;
1167
1168 /*
1169 * List all variables.
1170 */
1171 for (i = 0; i < variables.ga_len && !got_int; ++i)
1172 if (VAR_ENTRY(i).v_name != NULL)
1173 list_one_var(&VAR_ENTRY(i), (char_u *)"");
1174 for (i = 0; i < curbuf->b_vars.ga_len && !got_int; ++i)
1175 if (BVAR_ENTRY(i).v_name != NULL)
1176 list_one_var(&BVAR_ENTRY(i), (char_u *)"b:");
1177 for (i = 0; i < curwin->w_vars.ga_len && !got_int; ++i)
1178 if (WVAR_ENTRY(i).v_name != NULL)
1179 list_one_var(&WVAR_ENTRY(i), (char_u *)"w:");
1180 for (i = 0; i < VV_LEN && !got_int; ++i)
1181 if (vimvars[i].type == VAR_NUMBER || vimvars[i].val != NULL)
1182 list_vim_var(i);
1183}
1184
1185/*
1186 * List variables in "arg".
1187 */
1188 static char_u *
1189list_arg_vars(eap, arg)
1190 exarg_T *eap;
1191 char_u *arg;
1192{
1193 int error = FALSE;
1194 char_u *temp_string = NULL;
1195 int arg_len;
1196 char_u *expr_start;
1197 char_u *expr_end;
1198 char_u *name_end;
1199 int c1 = 0, c2;
1200 int i;
1201 VAR varp;
1202 char_u *name;
1203
1204 while (!ends_excmd(*arg) && !got_int)
1205 {
1206 /* Find the end of the name. */
1207 name_end = find_name_end(arg, &expr_start, &expr_end, FALSE);
1208
1209 if (!vim_iswhite(*name_end) && !ends_excmd(*name_end))
1210 {
1211 emsg_severe = TRUE;
1212 EMSG(_(e_trailing));
1213 break;
1214 }
1215 if (!error && !eap->skip)
1216 {
1217 if (expr_start != NULL)
1218 {
1219 temp_string = make_expanded_name(arg, expr_start,
1220 expr_end, name_end);
1221 if (temp_string == NULL)
1222 {
1223 /*
1224 * Report an invalid expression in braces, unless
1225 * the expression evaluation has been cancelled due
1226 * to an aborting error, an interrupt, or an
1227 * exception.
1228 */
1229 if (!aborting())
1230 {
1231 emsg_severe = TRUE;
1232 EMSG2(_(e_invarg2), arg);
1233 break;
1234 }
1235 error = TRUE;
1236 arg = skipwhite(name_end);
1237 continue;
1238 }
1239 arg = temp_string;
1240 arg_len = STRLEN(temp_string);
1241 }
1242 else
1243 {
1244 c1 = *name_end;
1245 *name_end = NUL;
1246 arg_len = (int)(name_end - arg);
1247 }
1248 i = find_vim_var(arg, arg_len);
1249 if (i >= 0)
1250 list_vim_var(i);
1251 else if (STRCMP("b:changedtick", arg) == 0)
1252 {
1253 char_u numbuf[NUMBUFLEN];
1254
1255 sprintf((char *)numbuf, "%ld",
1256 (long)curbuf->b_changedtick);
1257 list_one_var_a((char_u *)"b:", (char_u *)"changedtick",
1258 VAR_NUMBER, numbuf);
1259 }
1260 else
1261 {
1262 varp = find_var(arg, FALSE);
1263 if (varp == NULL)
1264 {
1265 /* Skip further arguments but do continue to
1266 * search for a trailing command. */
1267 EMSG2(_("E106: Unknown variable: \"%s\""), arg);
1268 error = TRUE;
1269 }
1270 else
1271 {
1272 name = vim_strchr(arg, ':');
1273 if (name != NULL)
1274 {
1275 /* "a:" vars have no name stored, use whole arg */
1276 if (arg[0] == 'a' && arg[1] == ':')
1277 c2 = NUL;
1278 else
1279 {
1280 c2 = *++name;
1281 *name = NUL;
1282 }
1283 list_one_var(varp, arg);
1284 if (c2 != NUL)
1285 *name = c2;
1286 }
1287 else
1288 list_one_var(varp, (char_u *)"");
1289 }
1290 }
1291 if (expr_start != NULL)
1292 vim_free(temp_string);
1293 else
1294 *name_end = c1;
1295 }
1296 arg = skipwhite(name_end);
1297 }
1298
1299 return arg;
1300}
1301
1302/*
1303 * Set one item of ":let var = expr" or ":let [v1, v2] = list" to its value.
1304 * Returns a pointer to the char just after the var name.
1305 * Returns NULL if there is an error.
1306 */
1307 static char_u *
1308ex_let_one(arg, tv, copy, endchars)
1309 char_u *arg; /* points to variable name */
1310 typeval *tv; /* value to assign to variable */
1311 int copy; /* copy value from "tv" */
1312 char_u *endchars; /* valid chars after variable name */
1313{
1314 int c1;
1315 char_u *name;
1316 char_u *p;
1317 char_u *arg_end = NULL;
1318 int len;
1319 int opt_flags;
1320
1321 /*
1322 * ":let $VAR = expr": Set environment variable.
1323 */
1324 if (*arg == '$')
1325 {
1326 /* Find the end of the name. */
1327 ++arg;
1328 name = arg;
1329 len = get_env_len(&arg);
1330 if (len == 0)
1331 EMSG2(_(e_invarg2), name - 1);
1332 else
1333 {
1334 if (vim_strchr(endchars, *skipwhite(arg)) == NULL)
1335 EMSG(_(e_letunexp));
1336 else
1337 {
1338 c1 = name[len];
1339 name[len] = NUL;
1340 p = get_tv_string(tv);
1341 vim_setenv(name, p);
1342 if (STRICMP(name, "HOME") == 0)
1343 init_homedir();
1344 else if (didset_vim && STRICMP(name, "VIM") == 0)
1345 didset_vim = FALSE;
1346 else if (didset_vimruntime && STRICMP(name, "VIMRUNTIME") == 0)
1347 didset_vimruntime = FALSE;
1348 name[len] = c1;
1349 arg_end = arg;
1350 }
1351 }
1352 }
1353
1354 /*
1355 * ":let &option = expr": Set option value.
1356 * ":let &l:option = expr": Set local option value.
1357 * ":let &g:option = expr": Set global option value.
1358 */
1359 else if (*arg == '&')
1360 {
1361 /* Find the end of the name. */
1362 p = find_option_end(&arg, &opt_flags);
1363 if (p == NULL || vim_strchr(endchars, *skipwhite(p)) == NULL)
1364 EMSG(_(e_letunexp));
1365 else
1366 {
1367 c1 = *p;
1368 *p = NUL;
1369 set_option_value(arg, get_tv_number(tv),
1370 get_tv_string(tv), opt_flags);
1371 *p = c1;
1372 arg_end = p;
1373 }
1374 }
1375
1376 /*
1377 * ":let @r = expr": Set register contents.
1378 */
1379 else if (*arg == '@')
1380 {
1381 ++arg;
1382 if (vim_strchr(endchars, *skipwhite(arg + 1)) == NULL)
1383 EMSG(_(e_letunexp));
1384 else
1385 {
1386 write_reg_contents(*arg == '@' ? '"' : *arg,
1387 get_tv_string(tv), -1, FALSE);
1388 arg_end = arg + 1;
1389 }
1390 }
1391
1392 /*
1393 * ":let var = expr": Set internal variable.
1394 */
1395 else if (eval_isnamec(*arg) && !VIM_ISDIGIT(*arg))
1396 {
1397 char_u *exp_name = NULL;
1398 char_u *expr_start, *expr_end;
1399
1400 /* Find the end of the name. */
1401 p = find_name_end(arg, &expr_start, &expr_end, FALSE);
1402 if (expr_start != NULL)
1403 {
1404 exp_name = make_expanded_name(arg, expr_start, expr_end, p);
1405 arg = exp_name;
1406 }
1407
1408 if (arg == NULL)
1409 {
1410 /* Report an invalid expression in braces, unless the
1411 * expression evaluation has been cancelled due to an
1412 * aborting error, an interrupt, or an exception. */
1413 if (!aborting())
1414 EMSG2(_(e_invarg2), arg);
1415 }
1416 else if (*p == '[')
1417 arg_end = set_var_idx(arg, p, tv, copy, endchars);
1418 else if (vim_strchr(endchars, *skipwhite(p)) == NULL)
1419 EMSG(_(e_letunexp));
1420 else if (STRNCMP(arg, "b:changedtick", 13) == 0
1421 && !eval_isnamec(arg[13]))
1422 EMSG2(_(e_readonlyvar), arg);
1423 else
1424 {
1425 c1 = *p;
1426 *p = NUL;
1427 set_var(arg, tv, copy);
1428 *p = c1;
1429 arg_end = p;
1430 }
1431
1432 vim_free(exp_name);
1433 }
1434
1435 else
1436 EMSG2(_(e_invarg2), arg);
1437
1438 return arg_end;
1439}
1440
1441/*
1442 * Set a variable with an index: "name[expr]", "name[expr][expr]", etc.
1443 * Only works if "name" is an existing List.
1444 * "ip" points to the first '['.
1445 * Returns a pointer to just after the last used ']'; NULL for error.
1446 */
1447 static char_u *
1448set_var_idx(name, ip, rettv, copy, endchars)
1449 char_u *name;
1450 char_u *ip;
1451 typeval *rettv;
1452 int copy;
1453 char_u *endchars;
1454{
1455 VAR v;
1456 int c1;
1457 char_u *p;
1458 typeval var1;
1459 typeval *tv;
1460 long n;
1461 listitem *item;
1462
1463 c1 = *ip;
1464 *ip = NUL;
1465 v = find_var(name, TRUE);
1466 if (v == NULL)
1467 EMSG2(_(e_undefvar), name);
1468 *ip = c1;
1469 if (v == NULL)
1470 return NULL;
1471
1472 tv = &v->tv;
1473 for (p = ip; *p == '['; p = skipwhite(p + 1))
1474 {
1475 if (tv->v_type != VAR_LIST || tv->vval.v_list == NULL)
1476 {
1477 EMSG(_("E999: Can only index a List"));
1478 p = NULL;
1479 break;
1480 }
1481 p = skipwhite(p + 1);
1482 if (eval1(&p, &var1, TRUE) == FAIL) /* recursive! */
1483 {
1484 p = NULL;
1485 break;
1486 }
1487 if (*p != ']')
1488 {
1489 EMSG(_(e_missbrac));
1490 clear_tv(&var1);
1491 p = NULL;
1492 break;
1493 }
1494 n = get_tv_number(&var1);
1495 clear_tv(&var1);
1496 item = list_find(tv->vval.v_list, n);
1497 if (item == NULL)
1498 {
1499 EMSGN(_(e_listidx), n);
1500 p = NULL;
1501 break;
1502 }
1503 tv = &item->li_tv;
1504 }
1505
1506 if (p != NULL)
1507 {
1508 if (vim_strchr(endchars, *p) == NULL)
1509 {
1510 EMSG(_(e_letunexp));
1511 p = NULL;
1512 }
1513 else
1514 {
1515 clear_tv(tv);
1516 if (copy)
1517 copy_tv(tv, rettv);
1518 else
1519 {
1520 *tv = *rettv;
1521 init_tv(rettv);
1522 }
1523 }
1524 }
1525 return p;
1526}
1527
Bram Moolenaar071d4272004-06-13 20:20:40 +00001528#if defined(FEAT_CMDL_COMPL) || defined(PROTO)
1529
1530 void
1531set_context_for_expression(xp, arg, cmdidx)
1532 expand_T *xp;
1533 char_u *arg;
1534 cmdidx_T cmdidx;
1535{
1536 int got_eq = FALSE;
1537 int c;
1538
1539 xp->xp_context = cmdidx == CMD_let ? EXPAND_USER_VARS
1540 : cmdidx == CMD_call ? EXPAND_FUNCTIONS
1541 : EXPAND_EXPRESSION;
1542 while ((xp->xp_pattern = vim_strpbrk(arg,
1543 (char_u *)"\"'+-*/%.=!?~|&$([<>,#")) != NULL)
1544 {
1545 c = *xp->xp_pattern;
1546 if (c == '&')
1547 {
1548 c = xp->xp_pattern[1];
1549 if (c == '&')
1550 {
1551 ++xp->xp_pattern;
1552 xp->xp_context = cmdidx != CMD_let || got_eq
1553 ? EXPAND_EXPRESSION : EXPAND_NOTHING;
1554 }
1555 else if (c != ' ')
1556 xp->xp_context = EXPAND_SETTINGS;
1557 }
1558 else if (c == '$')
1559 {
1560 /* environment variable */
1561 xp->xp_context = EXPAND_ENV_VARS;
1562 }
1563 else if (c == '=')
1564 {
1565 got_eq = TRUE;
1566 xp->xp_context = EXPAND_EXPRESSION;
1567 }
1568 else if (c == '<'
1569 && xp->xp_context == EXPAND_FUNCTIONS
1570 && vim_strchr(xp->xp_pattern, '(') == NULL)
1571 {
1572 /* Function name can start with "<SNR>" */
1573 break;
1574 }
1575 else if (cmdidx != CMD_let || got_eq)
1576 {
1577 if (c == '"') /* string */
1578 {
1579 while ((c = *++xp->xp_pattern) != NUL && c != '"')
1580 if (c == '\\' && xp->xp_pattern[1] != NUL)
1581 ++xp->xp_pattern;
1582 xp->xp_context = EXPAND_NOTHING;
1583 }
1584 else if (c == '\'') /* literal string */
1585 {
1586 while ((c = *++xp->xp_pattern) != NUL && c != '\'')
1587 /* skip */ ;
1588 xp->xp_context = EXPAND_NOTHING;
1589 }
1590 else if (c == '|')
1591 {
1592 if (xp->xp_pattern[1] == '|')
1593 {
1594 ++xp->xp_pattern;
1595 xp->xp_context = EXPAND_EXPRESSION;
1596 }
1597 else
1598 xp->xp_context = EXPAND_COMMANDS;
1599 }
1600 else
1601 xp->xp_context = EXPAND_EXPRESSION;
1602 }
1603 else
1604 xp->xp_context = EXPAND_NOTHING;
1605 arg = xp->xp_pattern;
1606 if (*arg != NUL)
1607 while ((c = *++arg) != NUL && (c == ' ' || c == '\t'))
1608 /* skip */ ;
1609 }
1610 xp->xp_pattern = arg;
1611}
1612
1613#endif /* FEAT_CMDL_COMPL */
1614
1615/*
1616 * ":1,25call func(arg1, arg2)" function call.
1617 */
1618 void
1619ex_call(eap)
1620 exarg_T *eap;
1621{
1622 char_u *arg = eap->arg;
1623 char_u *startarg;
1624 char_u *alias;
1625 char_u *name;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001626 typeval rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001627 int len;
1628 linenr_T lnum;
1629 int doesrange;
1630 int failed = FALSE;
1631
1632 name = arg;
1633 len = get_func_len(&arg, &alias, !eap->skip);
1634 if (len == 0)
1635 goto end;
1636 if (alias != NULL)
1637 name = alias;
1638
1639 startarg = arg;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001640 rettv.v_type = VAR_UNKNOWN; /* clear_tv() uses this */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001641
1642 if (*startarg != '(')
1643 {
1644 EMSG2(_("E107: Missing braces: %s"), name);
1645 goto end;
1646 }
1647
1648 /*
1649 * When skipping, evaluate the function once, to find the end of the
1650 * arguments.
1651 * When the function takes a range, this is discovered after the first
1652 * call, and the loop is broken.
1653 */
1654 if (eap->skip)
1655 {
1656 ++emsg_skip;
1657 lnum = eap->line2; /* do it once, also with an invalid range */
1658 }
1659 else
1660 lnum = eap->line1;
1661 for ( ; lnum <= eap->line2; ++lnum)
1662 {
1663 if (!eap->skip && eap->addr_count > 0)
1664 {
1665 curwin->w_cursor.lnum = lnum;
1666 curwin->w_cursor.col = 0;
1667 }
1668 arg = startarg;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001669 if (get_func_tv(name, len, &rettv, &arg,
Bram Moolenaar071d4272004-06-13 20:20:40 +00001670 eap->line1, eap->line2, &doesrange, !eap->skip) == FAIL)
1671 {
1672 failed = TRUE;
1673 break;
1674 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001675 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001676 if (doesrange || eap->skip)
1677 break;
1678 /* Stop when immediately aborting on error, or when an interrupt
Bram Moolenaar49cd9572005-01-03 21:06:01 +00001679 * occurred or an exception was thrown but not caught.
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001680 * get_func_tv() returned OK, so that the check for trailing
Bram Moolenaar49cd9572005-01-03 21:06:01 +00001681 * characters below is executed. */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001682 if (aborting())
1683 break;
1684 }
1685 if (eap->skip)
1686 --emsg_skip;
1687
1688 if (!failed)
1689 {
1690 /* Check for trailing illegal characters and a following command. */
1691 if (!ends_excmd(*arg))
1692 {
1693 emsg_severe = TRUE;
1694 EMSG(_(e_trailing));
1695 }
1696 else
1697 eap->nextcmd = check_nextcmd(arg);
1698 }
1699
1700end:
1701 if (alias != NULL)
1702 vim_free(alias);
1703}
1704
1705/*
1706 * ":unlet[!] var1 ... " command.
1707 */
1708 void
1709ex_unlet(eap)
1710 exarg_T *eap;
1711{
1712 char_u *arg = eap->arg;
1713 char_u *name_end;
1714 char_u cc;
1715 char_u *expr_start;
1716 char_u *expr_end;
1717 int error = FALSE;
1718
1719 do
1720 {
1721 /* Find the end of the name. */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001722 name_end = find_name_end(arg, &expr_start, &expr_end, FALSE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001723
1724 if (!vim_iswhite(*name_end) && !ends_excmd(*name_end))
1725 {
1726 emsg_severe = TRUE;
1727 EMSG(_(e_trailing));
1728 break;
1729 }
1730
1731 if (!error && !eap->skip)
1732 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00001733 if (expr_start != NULL)
1734 {
1735 char_u *temp_string;
1736
1737 temp_string = make_expanded_name(arg, expr_start,
1738 expr_end, name_end);
1739 if (temp_string == NULL)
1740 {
1741 /*
1742 * Report an invalid expression in braces, unless the
1743 * expression evaluation has been cancelled due to an
1744 * aborting error, an interrupt, or an exception.
1745 */
1746 if (!aborting())
1747 {
1748 emsg_severe = TRUE;
1749 EMSG2(_(e_invarg2), arg);
1750 break;
1751 }
1752 error = TRUE;
1753 }
1754 else
1755 {
1756 if (do_unlet(temp_string) == FAIL && !eap->forceit)
1757 {
1758 EMSG2(_("E108: No such variable: \"%s\""), temp_string);
1759 error = TRUE;
1760 }
1761 vim_free(temp_string);
1762 }
1763 }
1764 else
Bram Moolenaar071d4272004-06-13 20:20:40 +00001765 {
1766 cc = *name_end;
1767 *name_end = NUL;
1768
1769 if (do_unlet(arg) == FAIL && !eap->forceit)
1770 {
1771 EMSG2(_("E108: No such variable: \"%s\""), arg);
1772 error = TRUE;
1773 }
1774
1775 *name_end = cc;
1776 }
1777 }
1778 arg = skipwhite(name_end);
1779 } while (!ends_excmd(*arg));
1780
1781 eap->nextcmd = check_nextcmd(arg);
1782}
1783
1784/*
1785 * "unlet" a variable. Return OK if it existed, FAIL if not.
1786 */
1787 int
1788do_unlet(name)
1789 char_u *name;
1790{
1791 VAR v;
1792
1793 v = find_var(name, TRUE);
1794 if (v != NULL)
1795 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +00001796 clear_var(v);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001797 return OK;
1798 }
1799 return FAIL;
1800}
1801
1802#if (defined(FEAT_MENU) && defined(FEAT_MULTI_LANG)) || defined(PROTO)
1803/*
1804 * Delete all "menutrans_" variables.
1805 */
1806 void
1807del_menutrans_vars()
1808{
1809 int i;
1810
1811 for (i = 0; i < variables.ga_len; ++i)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00001812 if (VAR_ENTRY(i).v_name != NULL
1813 && STRNCMP(VAR_ENTRY(i).v_name, "menutrans_", 10) == 0)
1814 clear_var(&VAR_ENTRY(i));
Bram Moolenaar071d4272004-06-13 20:20:40 +00001815}
1816#endif
1817
1818#if defined(FEAT_CMDL_COMPL) || defined(PROTO)
1819
1820/*
1821 * Local string buffer for the next two functions to store a variable name
1822 * with its prefix. Allocated in cat_prefix_varname(), freed later in
1823 * get_user_var_name().
1824 */
1825
1826static char_u *cat_prefix_varname __ARGS((int prefix, char_u *name));
1827
1828static char_u *varnamebuf = NULL;
1829static int varnamebuflen = 0;
1830
1831/*
1832 * Function to concatenate a prefix and a variable name.
1833 */
1834 static char_u *
1835cat_prefix_varname(prefix, name)
1836 int prefix;
1837 char_u *name;
1838{
1839 int len;
1840
1841 len = (int)STRLEN(name) + 3;
1842 if (len > varnamebuflen)
1843 {
1844 vim_free(varnamebuf);
1845 len += 10; /* some additional space */
1846 varnamebuf = alloc(len);
1847 if (varnamebuf == NULL)
1848 {
1849 varnamebuflen = 0;
1850 return NULL;
1851 }
1852 varnamebuflen = len;
1853 }
1854 *varnamebuf = prefix;
1855 varnamebuf[1] = ':';
1856 STRCPY(varnamebuf + 2, name);
1857 return varnamebuf;
1858}
1859
1860/*
1861 * Function given to ExpandGeneric() to obtain the list of user defined
1862 * (global/buffer/window/built-in) variable names.
1863 */
1864/*ARGSUSED*/
1865 char_u *
1866get_user_var_name(xp, idx)
1867 expand_T *xp;
1868 int idx;
1869{
1870 static int gidx;
1871 static int bidx;
1872 static int widx;
1873 static int vidx;
1874 char_u *name;
1875
1876 if (idx == 0)
1877 gidx = bidx = widx = vidx = 0;
1878 if (gidx < variables.ga_len) /* Global variables */
1879 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +00001880 while ((name = VAR_ENTRY(gidx++).v_name) == NULL
Bram Moolenaar071d4272004-06-13 20:20:40 +00001881 && gidx < variables.ga_len)
1882 /* skip */;
1883 if (name != NULL)
1884 {
1885 if (STRNCMP("g:", xp->xp_pattern, 2) == 0)
1886 return cat_prefix_varname('g', name);
1887 else
1888 return name;
1889 }
1890 }
1891 if (bidx < curbuf->b_vars.ga_len) /* Current buffer variables */
1892 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +00001893 while ((name = BVAR_ENTRY(bidx++).v_name) == NULL
Bram Moolenaar071d4272004-06-13 20:20:40 +00001894 && bidx < curbuf->b_vars.ga_len)
1895 /* skip */;
1896 if (name != NULL)
1897 return cat_prefix_varname('b', name);
1898 }
1899 if (bidx == curbuf->b_vars.ga_len)
1900 {
1901 ++bidx;
1902 return (char_u *)"b:changedtick";
1903 }
1904 if (widx < curwin->w_vars.ga_len) /* Current window variables */
1905 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +00001906 while ((name = WVAR_ENTRY(widx++).v_name) == NULL
Bram Moolenaar071d4272004-06-13 20:20:40 +00001907 && widx < curwin->w_vars.ga_len)
1908 /* skip */;
1909 if (name != NULL)
1910 return cat_prefix_varname('w', name);
1911 }
1912 if (vidx < VV_LEN) /* Built-in variables */
1913 return cat_prefix_varname('v', (char_u *)vimvars[vidx++].name);
1914
1915 vim_free(varnamebuf);
1916 varnamebuf = NULL;
1917 varnamebuflen = 0;
1918 return NULL;
1919}
1920
1921#endif /* FEAT_CMDL_COMPL */
1922
1923/*
1924 * types for expressions.
1925 */
1926typedef enum
1927{
1928 TYPE_UNKNOWN = 0
1929 , TYPE_EQUAL /* == */
1930 , TYPE_NEQUAL /* != */
1931 , TYPE_GREATER /* > */
1932 , TYPE_GEQUAL /* >= */
1933 , TYPE_SMALLER /* < */
1934 , TYPE_SEQUAL /* <= */
1935 , TYPE_MATCH /* =~ */
1936 , TYPE_NOMATCH /* !~ */
1937} exptype_T;
1938
1939/*
1940 * The "evaluate" argument: When FALSE, the argument is only parsed but not
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001941 * executed. The function may return OK, but the rettv will be of type
Bram Moolenaar071d4272004-06-13 20:20:40 +00001942 * VAR_UNKNOWN. The function still returns FAIL for a syntax error.
1943 */
1944
1945/*
1946 * Handle zero level expression.
1947 * This calls eval1() and handles error message and nextcmd.
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001948 * Put the result in "rettv" when returning OK and "evaluate" is TRUE.
Bram Moolenaar071d4272004-06-13 20:20:40 +00001949 * Return OK or FAIL.
1950 */
1951 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001952eval0(arg, rettv, nextcmd, evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001953 char_u *arg;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001954 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001955 char_u **nextcmd;
1956 int evaluate;
1957{
1958 int ret;
1959 char_u *p;
1960
1961 p = skipwhite(arg);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001962 ret = eval1(&p, rettv, evaluate);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001963 if (ret == FAIL || !ends_excmd(*p))
1964 {
1965 if (ret != FAIL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001966 clear_tv(rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001967 /*
1968 * Report the invalid expression unless the expression evaluation has
1969 * been cancelled due to an aborting error, an interrupt, or an
1970 * exception.
1971 */
1972 if (!aborting())
1973 EMSG2(_(e_invexpr2), arg);
1974 ret = FAIL;
1975 }
1976 if (nextcmd != NULL)
1977 *nextcmd = check_nextcmd(p);
1978
1979 return ret;
1980}
1981
1982/*
1983 * Handle top level expression:
1984 * expr1 ? expr0 : expr0
1985 *
1986 * "arg" must point to the first non-white of the expression.
1987 * "arg" is advanced to the next non-white after the recognized expression.
1988 *
1989 * Return OK or FAIL.
1990 */
1991 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001992eval1(arg, rettv, evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001993 char_u **arg;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001994 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001995 int evaluate;
1996{
1997 int result;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00001998 typeval var2;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001999
2000 /*
2001 * Get the first variable.
2002 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002003 if (eval2(arg, rettv, evaluate) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002004 return FAIL;
2005
2006 if ((*arg)[0] == '?')
2007 {
2008 result = FALSE;
2009 if (evaluate)
2010 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002011 if (get_tv_number(rettv) != 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002012 result = TRUE;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002013 clear_tv(rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002014 }
2015
2016 /*
2017 * Get the second variable.
2018 */
2019 *arg = skipwhite(*arg + 1);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002020 if (eval1(arg, rettv, evaluate && result) == FAIL) /* recursive! */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002021 return FAIL;
2022
2023 /*
2024 * Check for the ":".
2025 */
2026 if ((*arg)[0] != ':')
2027 {
2028 EMSG(_("E109: Missing ':' after '?'"));
2029 if (evaluate && result)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002030 clear_tv(rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002031 return FAIL;
2032 }
2033
2034 /*
2035 * Get the third variable.
2036 */
2037 *arg = skipwhite(*arg + 1);
2038 if (eval1(arg, &var2, evaluate && !result) == FAIL) /* recursive! */
2039 {
2040 if (evaluate && result)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002041 clear_tv(rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002042 return FAIL;
2043 }
2044 if (evaluate && !result)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002045 *rettv = var2;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002046 }
2047
2048 return OK;
2049}
2050
2051/*
2052 * Handle first level expression:
2053 * expr2 || expr2 || expr2 logical OR
2054 *
2055 * "arg" must point to the first non-white of the expression.
2056 * "arg" is advanced to the next non-white after the recognized expression.
2057 *
2058 * Return OK or FAIL.
2059 */
2060 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002061eval2(arg, rettv, evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002062 char_u **arg;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002063 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002064 int evaluate;
2065{
Bram Moolenaar49cd9572005-01-03 21:06:01 +00002066 typeval var2;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002067 long result;
2068 int first;
2069
2070 /*
2071 * Get the first variable.
2072 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002073 if (eval3(arg, rettv, evaluate) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002074 return FAIL;
2075
2076 /*
2077 * Repeat until there is no following "||".
2078 */
2079 first = TRUE;
2080 result = FALSE;
2081 while ((*arg)[0] == '|' && (*arg)[1] == '|')
2082 {
2083 if (evaluate && first)
2084 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002085 if (get_tv_number(rettv) != 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002086 result = TRUE;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002087 clear_tv(rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002088 first = FALSE;
2089 }
2090
2091 /*
2092 * Get the second variable.
2093 */
2094 *arg = skipwhite(*arg + 2);
2095 if (eval3(arg, &var2, evaluate && !result) == FAIL)
2096 return FAIL;
2097
2098 /*
2099 * Compute the result.
2100 */
2101 if (evaluate && !result)
2102 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002103 if (get_tv_number(&var2) != 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002104 result = TRUE;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002105 clear_tv(&var2);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002106 }
2107 if (evaluate)
2108 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002109 rettv->v_type = VAR_NUMBER;
2110 rettv->vval.v_number = result;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002111 }
2112 }
2113
2114 return OK;
2115}
2116
2117/*
2118 * Handle second level expression:
2119 * expr3 && expr3 && expr3 logical AND
2120 *
2121 * "arg" must point to the first non-white of the expression.
2122 * "arg" is advanced to the next non-white after the recognized expression.
2123 *
2124 * Return OK or FAIL.
2125 */
2126 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002127eval3(arg, rettv, evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002128 char_u **arg;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002129 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002130 int evaluate;
2131{
Bram Moolenaar49cd9572005-01-03 21:06:01 +00002132 typeval var2;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002133 long result;
2134 int first;
2135
2136 /*
2137 * Get the first variable.
2138 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002139 if (eval4(arg, rettv, evaluate) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002140 return FAIL;
2141
2142 /*
2143 * Repeat until there is no following "&&".
2144 */
2145 first = TRUE;
2146 result = TRUE;
2147 while ((*arg)[0] == '&' && (*arg)[1] == '&')
2148 {
2149 if (evaluate && first)
2150 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002151 if (get_tv_number(rettv) == 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002152 result = FALSE;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002153 clear_tv(rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002154 first = FALSE;
2155 }
2156
2157 /*
2158 * Get the second variable.
2159 */
2160 *arg = skipwhite(*arg + 2);
2161 if (eval4(arg, &var2, evaluate && result) == FAIL)
2162 return FAIL;
2163
2164 /*
2165 * Compute the result.
2166 */
2167 if (evaluate && result)
2168 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002169 if (get_tv_number(&var2) == 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002170 result = FALSE;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002171 clear_tv(&var2);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002172 }
2173 if (evaluate)
2174 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002175 rettv->v_type = VAR_NUMBER;
2176 rettv->vval.v_number = result;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002177 }
2178 }
2179
2180 return OK;
2181}
2182
2183/*
2184 * Handle third level expression:
2185 * var1 == var2
2186 * var1 =~ var2
2187 * var1 != var2
2188 * var1 !~ var2
2189 * var1 > var2
2190 * var1 >= var2
2191 * var1 < var2
2192 * var1 <= var2
2193 *
2194 * "arg" must point to the first non-white of the expression.
2195 * "arg" is advanced to the next non-white after the recognized expression.
2196 *
2197 * Return OK or FAIL.
2198 */
2199 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002200eval4(arg, rettv, evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002201 char_u **arg;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002202 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002203 int evaluate;
2204{
Bram Moolenaar49cd9572005-01-03 21:06:01 +00002205 typeval var2;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002206 char_u *p;
2207 int i;
2208 exptype_T type = TYPE_UNKNOWN;
2209 int len = 2;
2210 long n1, n2;
2211 char_u *s1, *s2;
2212 char_u buf1[NUMBUFLEN], buf2[NUMBUFLEN];
2213 regmatch_T regmatch;
2214 int ic;
2215 char_u *save_cpo;
2216
2217 /*
2218 * Get the first variable.
2219 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002220 if (eval5(arg, rettv, evaluate) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002221 return FAIL;
2222
2223 p = *arg;
2224 switch (p[0])
2225 {
2226 case '=': if (p[1] == '=')
2227 type = TYPE_EQUAL;
2228 else if (p[1] == '~')
2229 type = TYPE_MATCH;
2230 break;
2231 case '!': if (p[1] == '=')
2232 type = TYPE_NEQUAL;
2233 else if (p[1] == '~')
2234 type = TYPE_NOMATCH;
2235 break;
2236 case '>': if (p[1] != '=')
2237 {
2238 type = TYPE_GREATER;
2239 len = 1;
2240 }
2241 else
2242 type = TYPE_GEQUAL;
2243 break;
2244 case '<': if (p[1] != '=')
2245 {
2246 type = TYPE_SMALLER;
2247 len = 1;
2248 }
2249 else
2250 type = TYPE_SEQUAL;
2251 break;
2252 }
2253
2254 /*
2255 * If there is a comparitive operator, use it.
2256 */
2257 if (type != TYPE_UNKNOWN)
2258 {
2259 /* extra question mark appended: ignore case */
2260 if (p[len] == '?')
2261 {
2262 ic = TRUE;
2263 ++len;
2264 }
2265 /* extra '#' appended: match case */
2266 else if (p[len] == '#')
2267 {
2268 ic = FALSE;
2269 ++len;
2270 }
2271 /* nothing appened: use 'ignorecase' */
2272 else
2273 ic = p_ic;
2274
2275 /*
2276 * Get the second variable.
2277 */
2278 *arg = skipwhite(p + len);
2279 if (eval5(arg, &var2, evaluate) == FAIL)
2280 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002281 clear_tv(rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002282 return FAIL;
2283 }
2284
2285 if (evaluate)
2286 {
2287 /*
2288 * If one of the two variables is a number, compare as a number.
2289 * When using "=~" or "!~", always compare as string.
2290 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002291 if ((rettv->v_type == VAR_NUMBER || var2.v_type == VAR_NUMBER)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002292 && type != TYPE_MATCH && type != TYPE_NOMATCH)
2293 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002294 n1 = get_tv_number(rettv);
2295 n2 = get_tv_number(&var2);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002296 switch (type)
2297 {
2298 case TYPE_EQUAL: n1 = (n1 == n2); break;
2299 case TYPE_NEQUAL: n1 = (n1 != n2); break;
2300 case TYPE_GREATER: n1 = (n1 > n2); break;
2301 case TYPE_GEQUAL: n1 = (n1 >= n2); break;
2302 case TYPE_SMALLER: n1 = (n1 < n2); break;
2303 case TYPE_SEQUAL: n1 = (n1 <= n2); break;
2304 case TYPE_UNKNOWN:
2305 case TYPE_MATCH:
2306 case TYPE_NOMATCH: break; /* avoid gcc warning */
2307 }
2308 }
2309 else
2310 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002311 s1 = get_tv_string_buf(rettv, buf1);
2312 s2 = get_tv_string_buf(&var2, buf2);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002313 if (type != TYPE_MATCH && type != TYPE_NOMATCH)
2314 i = ic ? MB_STRICMP(s1, s2) : STRCMP(s1, s2);
2315 else
2316 i = 0;
2317 n1 = FALSE;
2318 switch (type)
2319 {
2320 case TYPE_EQUAL: n1 = (i == 0); break;
2321 case TYPE_NEQUAL: n1 = (i != 0); break;
2322 case TYPE_GREATER: n1 = (i > 0); break;
2323 case TYPE_GEQUAL: n1 = (i >= 0); break;
2324 case TYPE_SMALLER: n1 = (i < 0); break;
2325 case TYPE_SEQUAL: n1 = (i <= 0); break;
2326
2327 case TYPE_MATCH:
2328 case TYPE_NOMATCH:
2329 /* avoid 'l' flag in 'cpoptions' */
2330 save_cpo = p_cpo;
2331 p_cpo = (char_u *)"";
2332 regmatch.regprog = vim_regcomp(s2,
2333 RE_MAGIC + RE_STRING);
2334 regmatch.rm_ic = ic;
2335 if (regmatch.regprog != NULL)
2336 {
2337 n1 = vim_regexec_nl(&regmatch, s1, (colnr_T)0);
2338 vim_free(regmatch.regprog);
2339 if (type == TYPE_NOMATCH)
2340 n1 = !n1;
2341 }
2342 p_cpo = save_cpo;
2343 break;
2344
2345 case TYPE_UNKNOWN: break; /* avoid gcc warning */
2346 }
2347 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002348 clear_tv(rettv);
2349 clear_tv(&var2);
2350 rettv->v_type = VAR_NUMBER;
2351 rettv->vval.v_number = n1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002352 }
2353 }
2354
2355 return OK;
2356}
2357
2358/*
2359 * Handle fourth level expression:
2360 * + number addition
2361 * - number subtraction
2362 * . string concatenation
2363 *
2364 * "arg" must point to the first non-white of the expression.
2365 * "arg" is advanced to the next non-white after the recognized expression.
2366 *
2367 * Return OK or FAIL.
2368 */
2369 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002370eval5(arg, rettv, evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002371 char_u **arg;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002372 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002373 int evaluate;
2374{
Bram Moolenaar49cd9572005-01-03 21:06:01 +00002375 typeval var2;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002376 int op;
2377 long n1, n2;
2378 char_u *s1, *s2;
2379 char_u buf1[NUMBUFLEN], buf2[NUMBUFLEN];
2380 char_u *p;
2381
2382 /*
2383 * Get the first variable.
2384 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002385 if (eval6(arg, rettv, evaluate) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002386 return FAIL;
2387
2388 /*
2389 * Repeat computing, until no '+', '-' or '.' is following.
2390 */
2391 for (;;)
2392 {
2393 op = **arg;
2394 if (op != '+' && op != '-' && op != '.')
2395 break;
2396
2397 /*
2398 * Get the second variable.
2399 */
2400 *arg = skipwhite(*arg + 1);
2401 if (eval6(arg, &var2, evaluate) == FAIL)
2402 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002403 clear_tv(rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002404 return FAIL;
2405 }
2406
2407 if (evaluate)
2408 {
2409 /*
2410 * Compute the result.
2411 */
2412 if (op == '.')
2413 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002414 s1 = get_tv_string_buf(rettv, buf1);
2415 s2 = get_tv_string_buf(&var2, buf2);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002416 op = (int)STRLEN(s1);
2417 p = alloc((unsigned)(op + STRLEN(s2) + 1));
2418 if (p != NULL)
2419 {
2420 STRCPY(p, s1);
2421 STRCPY(p + op, s2);
2422 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002423 clear_tv(rettv);
2424 rettv->v_type = VAR_STRING;
2425 rettv->vval.v_string = p;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002426 }
2427 else
2428 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002429 n1 = get_tv_number(rettv);
2430 n2 = get_tv_number(&var2);
2431 clear_tv(rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002432 if (op == '+')
2433 n1 = n1 + n2;
2434 else
2435 n1 = n1 - n2;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002436 rettv->v_type = VAR_NUMBER;
2437 rettv->vval.v_number = n1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002438 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002439 clear_tv(&var2);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002440 }
2441 }
2442 return OK;
2443}
2444
2445/*
2446 * Handle fifth level expression:
2447 * * number multiplication
2448 * / number division
2449 * % number modulo
2450 *
2451 * "arg" must point to the first non-white of the expression.
2452 * "arg" is advanced to the next non-white after the recognized expression.
2453 *
2454 * Return OK or FAIL.
2455 */
2456 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002457eval6(arg, rettv, evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002458 char_u **arg;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002459 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002460 int evaluate;
2461{
Bram Moolenaar49cd9572005-01-03 21:06:01 +00002462 typeval var2;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002463 int op;
2464 long n1, n2;
2465
2466 /*
2467 * Get the first variable.
2468 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002469 if (eval7(arg, rettv, evaluate) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002470 return FAIL;
2471
2472 /*
2473 * Repeat computing, until no '*', '/' or '%' is following.
2474 */
2475 for (;;)
2476 {
2477 op = **arg;
2478 if (op != '*' && op != '/' && op != '%')
2479 break;
2480
2481 if (evaluate)
2482 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002483 n1 = get_tv_number(rettv);
2484 clear_tv(rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002485 }
2486 else
2487 n1 = 0;
2488
2489 /*
2490 * Get the second variable.
2491 */
2492 *arg = skipwhite(*arg + 1);
2493 if (eval7(arg, &var2, evaluate) == FAIL)
2494 return FAIL;
2495
2496 if (evaluate)
2497 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002498 n2 = get_tv_number(&var2);
2499 clear_tv(&var2);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002500
2501 /*
2502 * Compute the result.
2503 */
2504 if (op == '*')
2505 n1 = n1 * n2;
2506 else if (op == '/')
2507 {
2508 if (n2 == 0) /* give an error message? */
2509 n1 = 0x7fffffffL;
2510 else
2511 n1 = n1 / n2;
2512 }
2513 else
2514 {
2515 if (n2 == 0) /* give an error message? */
2516 n1 = 0;
2517 else
2518 n1 = n1 % n2;
2519 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002520 rettv->v_type = VAR_NUMBER;
2521 rettv->vval.v_number = n1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002522 }
2523 }
2524
2525 return OK;
2526}
2527
2528/*
2529 * Handle sixth level expression:
2530 * number number constant
2531 * "string" string contstant
2532 * 'string' literal string contstant
2533 * &option-name option value
2534 * @r register contents
2535 * identifier variable value
2536 * function() function call
2537 * $VAR environment variable
2538 * (expression) nested expression
2539 *
2540 * Also handle:
2541 * ! in front logical NOT
2542 * - in front unary minus
2543 * + in front unary plus (ignored)
2544 * trailing [] subscript in String
2545 *
2546 * "arg" must point to the first non-white of the expression.
2547 * "arg" is advanced to the next non-white after the recognized expression.
2548 *
2549 * Return OK or FAIL.
2550 */
2551 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002552eval7(arg, rettv, evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002553 char_u **arg;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002554 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002555 int evaluate;
2556{
Bram Moolenaar071d4272004-06-13 20:20:40 +00002557 long n;
2558 int len;
2559 char_u *s;
2560 int val;
2561 char_u *start_leader, *end_leader;
2562 int ret = OK;
2563 char_u *alias;
2564
2565 /*
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002566 * Initialise variable so that clear_tv() can't mistake this for a
Bram Moolenaar49cd9572005-01-03 21:06:01 +00002567 * string and free a string that isn't there.
Bram Moolenaar071d4272004-06-13 20:20:40 +00002568 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002569 rettv->v_type = VAR_UNKNOWN;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002570
2571 /*
2572 * Skip '!' and '-' characters. They are handled later.
2573 */
2574 start_leader = *arg;
2575 while (**arg == '!' || **arg == '-' || **arg == '+')
2576 *arg = skipwhite(*arg + 1);
2577 end_leader = *arg;
2578
2579 switch (**arg)
2580 {
2581 /*
2582 * Number constant.
2583 */
2584 case '0':
2585 case '1':
2586 case '2':
2587 case '3':
2588 case '4':
2589 case '5':
2590 case '6':
2591 case '7':
2592 case '8':
2593 case '9':
2594 vim_str2nr(*arg, NULL, &len, TRUE, TRUE, &n, NULL);
2595 *arg += len;
2596 if (evaluate)
2597 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002598 rettv->v_type = VAR_NUMBER;
2599 rettv->vval.v_number = n;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002600 }
2601 break;
2602
2603 /*
2604 * String constant: "string".
2605 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002606 case '"': ret = get_string_tv(arg, rettv, evaluate);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002607 break;
2608
2609 /*
2610 * Literal string constant: 'string'.
2611 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002612 case '\'': ret = get_lit_string_tv(arg, rettv, evaluate);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00002613 break;
2614
2615 /*
2616 * List: [expr, expr]
2617 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002618 case '[': ret = get_list_tv(arg, rettv, evaluate);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002619 break;
2620
2621 /*
2622 * Option value: &name
2623 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002624 case '&': ret = get_option_tv(arg, rettv, evaluate);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002625 break;
2626
2627 /*
2628 * Environment variable: $VAR.
2629 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002630 case '$': ret = get_env_tv(arg, rettv, evaluate);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002631 break;
2632
2633 /*
2634 * Register contents: @r.
2635 */
2636 case '@': ++*arg;
2637 if (evaluate)
2638 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002639 rettv->v_type = VAR_STRING;
2640 rettv->vval.v_string = get_reg_contents(**arg, FALSE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002641 }
2642 if (**arg != NUL)
2643 ++*arg;
2644 break;
2645
2646 /*
2647 * nested expression: (expression).
2648 */
2649 case '(': *arg = skipwhite(*arg + 1);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002650 ret = eval1(arg, rettv, evaluate); /* recursive! */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002651 if (**arg == ')')
2652 ++*arg;
2653 else if (ret == OK)
2654 {
2655 EMSG(_("E110: Missing ')'"));
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002656 clear_tv(rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002657 ret = FAIL;
2658 }
2659 break;
2660
2661 /*
2662 * Must be a variable or function name then.
2663 */
2664 default: s = *arg;
2665 len = get_func_len(arg, &alias, evaluate);
2666 if (alias != NULL)
2667 s = alias;
2668
2669 if (len == 0)
2670 ret = FAIL;
2671 else
2672 {
2673 if (**arg == '(') /* recursive! */
2674 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +00002675 /* If "s" is the name of a variable of type VAR_FUNC
2676 * use its contents. */
2677 s = deref_func_name(s, &len);
2678
2679 /* Invoke the function. */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002680 ret = get_func_tv(s, len, rettv, arg,
Bram Moolenaar071d4272004-06-13 20:20:40 +00002681 curwin->w_cursor.lnum, curwin->w_cursor.lnum,
2682 &len, evaluate);
2683 /* Stop the expression evaluation when immediately
2684 * aborting on error, or when an interrupt occurred or
2685 * an exception was thrown but not caught. */
2686 if (aborting())
2687 {
2688 if (ret == OK)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002689 clear_tv(rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002690 ret = FAIL;
2691 }
2692 }
2693 else if (evaluate)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002694 ret = get_var_tv(s, len, rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002695 }
2696
2697 if (alias != NULL)
2698 vim_free(alias);
2699
2700 break;
2701 }
2702 *arg = skipwhite(*arg);
2703
2704 /*
Bram Moolenaar49cd9572005-01-03 21:06:01 +00002705 * Handle expr[expr] and expr[expr:expr] subscript.
Bram Moolenaar071d4272004-06-13 20:20:40 +00002706 */
Bram Moolenaar49cd9572005-01-03 21:06:01 +00002707 while (**arg == '[' && ret == OK)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002708 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002709 if (eval_index(arg, rettv, evaluate) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002710 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002711 clear_tv(rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002712 return FAIL;
2713 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00002714 }
2715
2716 /*
2717 * Apply logical NOT and unary '-', from right to left, ignore '+'.
2718 */
2719 if (ret == OK && evaluate && end_leader > start_leader)
2720 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002721 val = get_tv_number(rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002722 while (end_leader > start_leader)
2723 {
2724 --end_leader;
2725 if (*end_leader == '!')
2726 val = !val;
2727 else if (*end_leader == '-')
2728 val = -val;
2729 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002730 clear_tv(rettv);
2731 rettv->v_type = VAR_NUMBER;
2732 rettv->vval.v_number = val;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002733 }
2734
2735 return ret;
2736}
2737
2738/*
Bram Moolenaar49cd9572005-01-03 21:06:01 +00002739 * Evaluate an "[expr]" or "[expr:expr]" index.
2740 * "*arg" points to the '['.
2741 * Returns FAIL or OK. "*arg" is advanced to after the ']'.
2742 */
2743 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002744eval_index(arg, rettv, evaluate)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00002745 char_u **arg;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002746 typeval *rettv;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00002747 int evaluate;
2748{
2749 int empty1 = FALSE, empty2 = FALSE;
2750 typeval var1, var2;
2751 long n1, n2 = 0;
2752 long len;
2753 int range;
2754 char_u *s;
2755
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002756 if (rettv->v_type == VAR_FUNC)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00002757 {
2758 EMSG(_("E999: Cannot index a Funcref"));
2759 return FAIL;
2760 }
2761
2762 /*
2763 * Get the (first) variable from inside the [].
2764 */
2765 *arg = skipwhite(*arg + 1);
2766 if (**arg == ':')
2767 empty1 = TRUE;
2768 else if (eval1(arg, &var1, evaluate) == FAIL) /* recursive! */
2769 return FAIL;
2770
2771 /*
2772 * Get the second variable from inside the [:].
2773 */
2774 if (**arg == ':')
2775 {
2776 range = TRUE;
2777 *arg = skipwhite(*arg + 1);
2778 if (**arg == ']')
2779 empty2 = TRUE;
2780 else if (eval1(arg, &var2, evaluate) == FAIL) /* recursive! */
2781 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002782 clear_tv(&var1);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00002783 return FAIL;
2784 }
2785 }
2786 else
2787 range = FALSE;
2788
2789 /* Check for the ']'. */
2790 if (**arg != ']')
2791 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002792 EMSG(_(e_missbrac));
2793 clear_tv(&var1);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00002794 if (range)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002795 clear_tv(&var2);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00002796 return FAIL;
2797 }
2798
2799 if (evaluate)
2800 {
2801 if (empty1)
2802 n1 = 0;
2803 else
2804 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002805 n1 = get_tv_number(&var1);
2806 clear_tv(&var1);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00002807 }
2808 if (range)
2809 {
2810 if (empty2)
2811 n2 = -1;
2812 else
2813 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002814 n2 = get_tv_number(&var2);
2815 clear_tv(&var2);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00002816 }
2817 }
2818
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002819 switch (rettv->v_type)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00002820 {
2821 case VAR_NUMBER:
2822 case VAR_STRING:
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002823 s = get_tv_string(rettv);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00002824 len = (long)STRLEN(s);
2825 if (range)
2826 {
2827 /* The resulting variable is a substring. If the indexes
2828 * are out of range the result is empty. */
2829 if (n1 < 0)
2830 {
2831 n1 = len + n1;
2832 if (n1 < 0)
2833 n1 = 0;
2834 }
2835 if (n2 < 0)
2836 n2 = len + n2;
2837 else if (n2 >= len)
2838 n2 = len;
2839 if (n1 >= len || n2 < 0 || n1 > n2)
2840 s = NULL;
2841 else
2842 s = vim_strnsave(s + n1, (int)(n2 - n1 + 1));
2843 }
2844 else
2845 {
2846 /* The resulting variable is a string of a single
2847 * character. If the index is too big or negative the
2848 * result is empty. */
2849 if (n1 >= len || n1 < 0)
2850 s = NULL;
2851 else
2852 s = vim_strnsave(s + n1, 1);
2853 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002854 clear_tv(rettv);
2855 rettv->v_type = VAR_STRING;
2856 rettv->vval.v_string = s;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00002857 break;
2858
2859 case VAR_LIST:
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002860 len = list_len(rettv->vval.v_list);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00002861 if (n1 < 0)
2862 n1 = len + n1;
2863 if (!empty1 && (n1 < 0 || n1 >= len))
2864 {
2865 EMSGN(_(e_listidx), n1);
2866 return FAIL;
2867 }
2868 if (range)
2869 {
2870 listvar *l;
2871 listitem *item;
2872
2873 if (n2 < 0)
2874 n2 = len + n2;
2875 if (!empty2 && (n2 < 0 || n2 >= len || n2 < n1))
2876 {
2877 EMSGN(_(e_listidx), n2);
2878 return FAIL;
2879 }
2880 l = list_alloc();
2881 if (l == NULL)
2882 return FAIL;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002883 for (item = list_find(rettv->vval.v_list, n1);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00002884 n1 <= n2; ++n1)
2885 {
2886 if (list_append_tv(l, &item->li_tv) == FAIL)
2887 {
2888 list_free(l);
2889 return FAIL;
2890 }
2891 item = item->li_next;
2892 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002893 clear_tv(rettv);
2894 rettv->v_type = VAR_LIST;
2895 rettv->vval.v_list = l;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00002896 }
2897 else
2898 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002899 copy_tv(&list_find(rettv->vval.v_list, n1)->li_tv,
Bram Moolenaar49cd9572005-01-03 21:06:01 +00002900 &var1);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002901 clear_tv(rettv);
2902 *rettv = var1;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00002903 }
2904 break;
2905 }
2906 }
2907
2908 *arg = skipwhite(*arg + 1); /* skip the ']' */
2909 return OK;
2910}
2911
2912/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00002913 * Get an option value.
2914 * "arg" points to the '&' or '+' before the option name.
2915 * "arg" is advanced to character after the option name.
2916 * Return OK or FAIL.
2917 */
2918 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002919get_option_tv(arg, rettv, evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002920 char_u **arg;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002921 typeval *rettv; /* when NULL, only check if option exists */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002922 int evaluate;
2923{
2924 char_u *option_end;
2925 long numval;
2926 char_u *stringval;
2927 int opt_type;
2928 int c;
2929 int working = (**arg == '+'); /* has("+option") */
2930 int ret = OK;
2931 int opt_flags;
2932
2933 /*
2934 * Isolate the option name and find its value.
2935 */
2936 option_end = find_option_end(arg, &opt_flags);
2937 if (option_end == NULL)
2938 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002939 if (rettv != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002940 EMSG2(_("E112: Option name missing: %s"), *arg);
2941 return FAIL;
2942 }
2943
2944 if (!evaluate)
2945 {
2946 *arg = option_end;
2947 return OK;
2948 }
2949
2950 c = *option_end;
2951 *option_end = NUL;
2952 opt_type = get_option_value(*arg, &numval,
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002953 rettv == NULL ? NULL : &stringval, opt_flags);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002954
2955 if (opt_type == -3) /* invalid name */
2956 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002957 if (rettv != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002958 EMSG2(_("E113: Unknown option: %s"), *arg);
2959 ret = FAIL;
2960 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002961 else if (rettv != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002962 {
2963 if (opt_type == -2) /* hidden string option */
2964 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002965 rettv->v_type = VAR_STRING;
2966 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002967 }
2968 else if (opt_type == -1) /* hidden number option */
2969 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002970 rettv->v_type = VAR_NUMBER;
2971 rettv->vval.v_number = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002972 }
2973 else if (opt_type == 1) /* number option */
2974 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002975 rettv->v_type = VAR_NUMBER;
2976 rettv->vval.v_number = numval;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002977 }
2978 else /* string option */
2979 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002980 rettv->v_type = VAR_STRING;
2981 rettv->vval.v_string = stringval;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002982 }
2983 }
2984 else if (working && (opt_type == -2 || opt_type == -1))
2985 ret = FAIL;
2986
2987 *option_end = c; /* put back for error messages */
2988 *arg = option_end;
2989
2990 return ret;
2991}
2992
2993/*
2994 * Allocate a variable for a string constant.
2995 * Return OK or FAIL.
2996 */
2997 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002998get_string_tv(arg, rettv, evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002999 char_u **arg;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003000 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003001 int evaluate;
3002{
3003 char_u *p;
3004 char_u *name;
3005 int i;
3006 int extra = 0;
3007
3008 /*
3009 * Find the end of the string, skipping backslashed characters.
3010 */
Bram Moolenaar1cd871b2004-12-19 22:46:22 +00003011 for (p = *arg + 1; *p && *p != '"'; mb_ptr_adv(p))
Bram Moolenaar071d4272004-06-13 20:20:40 +00003012 {
3013 if (*p == '\\' && p[1] != NUL)
3014 {
3015 ++p;
3016 /* A "\<x>" form occupies at least 4 characters, and produces up
3017 * to 6 characters: reserve space for 2 extra */
3018 if (*p == '<')
3019 extra += 2;
3020 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00003021 }
3022
3023 if (*p != '"')
3024 {
3025 EMSG2(_("E114: Missing quote: %s"), *arg);
3026 return FAIL;
3027 }
3028
3029 /* If only parsing, set *arg and return here */
3030 if (!evaluate)
3031 {
3032 *arg = p + 1;
3033 return OK;
3034 }
3035
3036 /*
3037 * Copy the string into allocated memory, handling backslashed
3038 * characters.
3039 */
3040 name = alloc((unsigned)(p - *arg + extra));
3041 if (name == NULL)
3042 return FAIL;
3043
3044 i = 0;
3045 for (p = *arg + 1; *p && *p != '"'; ++p)
3046 {
3047 if (*p == '\\')
3048 {
3049 switch (*++p)
3050 {
3051 case 'b': name[i++] = BS; break;
3052 case 'e': name[i++] = ESC; break;
3053 case 'f': name[i++] = FF; break;
3054 case 'n': name[i++] = NL; break;
3055 case 'r': name[i++] = CAR; break;
3056 case 't': name[i++] = TAB; break;
3057
3058 case 'X': /* hex: "\x1", "\x12" */
3059 case 'x':
3060 case 'u': /* Unicode: "\u0023" */
3061 case 'U':
3062 if (vim_isxdigit(p[1]))
3063 {
3064 int n, nr;
3065 int c = toupper(*p);
3066
3067 if (c == 'X')
3068 n = 2;
3069 else
3070 n = 4;
3071 nr = 0;
3072 while (--n >= 0 && vim_isxdigit(p[1]))
3073 {
3074 ++p;
3075 nr = (nr << 4) + hex2nr(*p);
3076 }
3077#ifdef FEAT_MBYTE
3078 /* For "\u" store the number according to
3079 * 'encoding'. */
3080 if (c != 'X')
3081 i += (*mb_char2bytes)(nr, name + i);
3082 else
3083#endif
3084 name[i++] = nr;
3085 }
3086 else
3087 name[i++] = *p;
3088 break;
3089
3090 /* octal: "\1", "\12", "\123" */
3091 case '0':
3092 case '1':
3093 case '2':
3094 case '3':
3095 case '4':
3096 case '5':
3097 case '6':
3098 case '7': name[i] = *p - '0';
3099 if (p[1] >= '0' && p[1] <= '7')
3100 {
3101 ++p;
3102 name[i] = (name[i] << 3) + *p - '0';
3103 if (p[1] >= '0' && p[1] <= '7')
3104 {
3105 ++p;
3106 name[i] = (name[i] << 3) + *p - '0';
3107 }
3108 }
3109 ++i;
3110 break;
3111
3112 /* Special key, e.g.: "\<C-W>" */
3113 case '<': extra = trans_special(&p, name + i, TRUE);
3114 if (extra != 0)
3115 {
3116 i += extra;
3117 --p;
3118 break;
3119 }
3120 /* FALLTHROUGH */
3121
3122 default: name[i++] = *p;
3123 break;
3124 }
3125 }
3126 else
3127 name[i++] = *p;
3128
3129#ifdef FEAT_MBYTE
3130 /* For a multi-byte character copy the bytes after the first one. */
3131 if (has_mbyte)
3132 {
3133 int l = (*mb_ptr2len_check)(p);
3134
3135 while (--l > 0)
3136 name[i++] = *++p;
3137 }
3138#endif
3139 }
3140 name[i] = NUL;
3141 *arg = p + 1;
3142
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003143 rettv->v_type = VAR_STRING;
3144 rettv->vval.v_string = name;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003145
3146 return OK;
3147}
3148
3149/*
3150 * Allocate a variable for an backtick-string constant.
3151 * Return OK or FAIL.
3152 */
3153 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003154get_lit_string_tv(arg, rettv, evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003155 char_u **arg;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003156 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003157 int evaluate;
3158{
3159 char_u *p;
3160 char_u *name;
3161
3162 /*
3163 * Find the end of the string.
3164 */
3165 p = vim_strchr(*arg + 1, '\'');
3166 if (p == NULL)
3167 {
3168 EMSG2(_("E115: Missing quote: %s"), *arg);
3169 return FAIL;
3170 }
3171
3172 if (evaluate)
3173 {
3174 /*
3175 * Copy the string into allocated memory.
3176 */
3177 name = vim_strnsave(*arg + 1, (int)(p - (*arg + 1)));
3178 if (name == NULL)
3179 return FAIL;
3180
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003181 rettv->v_type = VAR_STRING;
3182 rettv->vval.v_string = name;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003183 }
3184
3185 *arg = p + 1;
3186
3187 return OK;
3188}
3189
3190/*
Bram Moolenaar49cd9572005-01-03 21:06:01 +00003191 * Allocate a variable for a List and fill it from "*arg".
3192 * Return OK or FAIL.
3193 */
3194 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003195get_list_tv(arg, rettv, evaluate)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00003196 char_u **arg;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003197 typeval *rettv;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00003198 int evaluate;
3199{
3200 listvar *l = NULL;
3201 typeval tv;
3202 listitem *item;
3203
3204 if (evaluate)
3205 {
3206 l = list_alloc();
3207 if (l == NULL)
3208 return FAIL;
3209 }
3210
3211 *arg = skipwhite(*arg + 1);
3212 while (**arg != ']' && **arg != NUL)
3213 {
3214 if (eval1(arg, &tv, evaluate) == FAIL) /* recursive! */
3215 goto failret;
3216 if (evaluate)
3217 {
3218 item = listitem_alloc();
3219 if (item != NULL)
3220 {
3221 item->li_tv = tv;
3222 list_append(l, item);
3223 }
3224 }
3225
3226 if (**arg == ']')
3227 break;
3228 if (**arg != ',')
3229 {
3230 EMSG2(_("E999: Missing comma in list: %s"), *arg);
3231 goto failret;
3232 }
3233 *arg = skipwhite(*arg + 1);
3234 }
3235
3236 if (**arg != ']')
3237 {
3238 EMSG2(_("E999: Missing end of list ']': %s"), *arg);
3239failret:
3240 if (evaluate)
3241 list_free(l);
3242 return FAIL;
3243 }
3244
3245 *arg = skipwhite(*arg + 1);
3246 if (evaluate)
3247 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003248 rettv->v_type = VAR_LIST;
3249 rettv->vval.v_list = l;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00003250 ++l->lv_refcount;
3251 }
3252
3253 return OK;
3254}
3255
3256/*
3257 * Allocate an empty header for a list.
3258 */
3259 static listvar *
3260list_alloc()
3261{
3262 return (listvar *)alloc_clear(sizeof(listvar));
3263}
3264
3265/*
3266 * Unreference a list: decrement the reference count and free it when it
3267 * becomes zero.
3268 */
3269 static void
3270list_unref(l)
3271 listvar *l;
3272{
3273 if (l != NULL && --l->lv_refcount <= 0)
3274 list_free(l);
3275}
3276
3277/*
3278 * Free a list, including all items it points to.
3279 * Ignores the reference count.
3280 */
3281 static void
3282list_free(l)
3283 listvar *l;
3284{
3285 listitem *item;
3286 listitem *next;
3287
3288 for (item = l->lv_first; item != NULL; item = next)
3289 {
3290 next = item->li_next;
3291 listitem_free(item);
3292 }
3293 vim_free(l);
3294}
3295
3296/*
3297 * Allocate a list item.
3298 */
3299 static listitem *
3300listitem_alloc()
3301{
3302 return (listitem *)alloc(sizeof(listitem));
3303}
3304
3305/*
3306 * Free a list item. Also clears the value;
3307 */
3308 static void
3309listitem_free(item)
3310 listitem *item;
3311{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003312 clear_tv(&item->li_tv);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00003313 vim_free(item);
3314}
3315
3316/*
3317 * Get the number of items in a list.
3318 */
3319 static long
3320list_len(l)
3321 listvar *l;
3322{
3323 listitem *item;
3324 long len = 0;
3325
3326 if (l == NULL)
3327 return 0L;
3328 for (item = l->lv_first; item != NULL; item = item->li_next)
3329 ++len;
3330 return len;
3331}
3332
3333/*
3334 * Locate item with index "n" in list "l" and return it.
3335 * A negative index is counted from the end; -1 is the last item.
3336 * Returns NULL when "n" is out of range.
3337 */
3338 static listitem *
3339list_find(l, n)
3340 listvar *l;
3341 long n;
3342{
3343 listitem *item;
3344 long idx;
3345
3346 if (l == NULL)
3347 return NULL;
3348 if (n < 0)
3349 {
3350 idx = -1; /* search from the end */
3351 for (item = l->lv_last; item != NULL && idx > n; item = item->li_prev)
3352 --idx;
3353 }
3354 else
3355 {
3356 idx = 0; /* search from the start */
3357 for (item = l->lv_first; item != NULL && idx < n; item = item->li_next)
3358 ++idx;
3359 }
3360 if (idx != n)
3361 return NULL;
3362 return item;
3363}
3364
3365/*
3366 * Append item "item" to the end of list "l".
3367 */
3368 static void
3369list_append(l, item)
3370 listvar *l;
3371 listitem *item;
3372{
3373 if (l->lv_last == NULL)
3374 {
3375 /* empty list */
3376 l->lv_first = item;
3377 l->lv_last = item;
3378 item->li_prev = NULL;
3379 }
3380 else
3381 {
3382 l->lv_last->li_next = item;
3383 item->li_prev = l->lv_last;
3384 l->lv_last = item;
3385 }
3386 item->li_next = NULL;
3387}
3388
3389/*
3390 * Append typeval "tv" to the end of list "l".
3391 */
3392 static int
3393list_append_tv(l, tv)
3394 listvar *l;
3395 typeval *tv;
3396{
3397 listitem *ni = listitem_alloc();
3398
3399 if (ni == NULL)
3400 return FAIL;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003401 copy_tv(tv, &ni->li_tv);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00003402 list_append(l, ni);
3403 return OK;
3404}
3405
3406/*
3407 * Make a copy of list "l". Shallow if "deep" is FALSE.
3408 * The refcount of the new list is set to 1.
3409 * Returns NULL when out of memory.
3410 */
3411 static listvar *
3412list_copy(orig, deep)
3413 listvar *orig;
3414 int deep;
3415{
3416 listvar *copy;
3417 listitem *item;
3418 listitem *ni;
3419 static int recurse = 0;
3420
3421 if (orig == NULL)
3422 return NULL;
3423 if (recurse >= VAR_LIST_MAXNEST)
3424 {
3425 EMSG(_("E999: List nested too deep for making a copy"));
3426 return NULL;
3427 }
3428 ++recurse;
3429
3430 copy = list_alloc();
3431 if (copy != NULL)
3432 {
3433 for (item = orig->lv_first; item != NULL; item = item->li_next)
3434 {
3435 ni = listitem_alloc();
3436 if (ni == NULL)
3437 break;
3438 if (deep && item->li_tv.v_type == VAR_LIST)
3439 {
3440 ni->li_tv.v_type = VAR_LIST;
3441 ni->li_tv.vval.v_list = list_copy(item->li_tv.vval.v_list,
3442 TRUE);
3443 if (ni->li_tv.vval.v_list == NULL)
3444 {
3445 vim_free(ni);
3446 break;
3447 }
3448 }
3449 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003450 copy_tv(&item->li_tv, &ni->li_tv);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00003451 list_append(copy, ni);
3452 }
3453 ++copy->lv_refcount;
3454 }
3455
3456 --recurse;
3457 return copy;
3458}
3459
3460/*
3461 * Remove item with index "n" from list "l" and return it.
3462 * Returns NULL when "n" is out of range.
3463 */
3464 static listitem *
3465list_getrem(l, n)
3466 listvar *l;
3467 long n;
3468{
3469 listitem *item;
3470
3471 item = list_find(l, n);
3472 if (item != NULL)
3473 {
3474 if (item->li_next == NULL)
3475 l->lv_last = item->li_prev;
3476 else
3477 item->li_next->li_prev = item->li_prev;
3478 if (item->li_prev == NULL)
3479 l->lv_first = item->li_next;
3480 else
3481 item->li_prev->li_next = item->li_next;
3482 }
3483 return item;
3484}
3485
3486/*
3487 * Return an allocated string with the string representation of a list.
3488 * May return NULL.
3489 */
3490 static char_u *
3491list2string(tv)
3492 typeval *tv;
3493{
3494 garray_T ga;
3495 listitem *item;
3496 int first = TRUE;
3497 char_u *tofree;
3498 char_u *s;
3499
3500 if (tv->vval.v_list == NULL)
3501 return NULL;
3502 ga_init2(&ga, (int)sizeof(char), 80);
3503 ga_append(&ga, '[');
3504
3505 for (item = tv->vval.v_list->lv_first; item != NULL; item = item->li_next)
3506 {
3507 if (first)
3508 first = FALSE;
3509 else
3510 ga_concat(&ga, (char_u *)", ");
3511
3512 s = tv2string(&item->li_tv, &tofree);
3513 if (s != NULL)
3514 ga_concat(&ga, s);
3515 vim_free(tofree);
3516 }
3517
3518 ga_append(&ga, ']');
3519 ga_append(&ga, NUL);
3520 return (char_u *)ga.ga_data;
3521}
3522
3523/*
3524 * Return a string with the string representation of a variable.
3525 * If the memory is allocated "tofree" is set to it, otherwise NULL.
3526 * Can only be used once before the value is used, it may call
3527 * get_var_string().
3528 * May return NULL;
3529 */
3530 static char_u *
3531tv2string(tv, tofree)
3532 typeval *tv;
3533 char_u **tofree;
3534{
3535 switch (tv->v_type)
3536 {
3537 case VAR_FUNC:
3538 *tofree = NULL;
3539 return tv->vval.v_string;
3540 case VAR_LIST:
3541 *tofree = list2string(tv);
3542 return *tofree;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003543 case VAR_STRING:
3544 case VAR_NUMBER:
Bram Moolenaar49cd9572005-01-03 21:06:01 +00003545 break;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003546 default:
3547 EMSG2(_(e_intern2), "tv2string()");
Bram Moolenaar49cd9572005-01-03 21:06:01 +00003548 }
3549 *tofree = NULL;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003550 return get_tv_string(tv);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00003551}
3552
3553/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00003554 * Get the value of an environment variable.
3555 * "arg" is pointing to the '$'. It is advanced to after the name.
3556 * If the environment variable was not set, silently assume it is empty.
3557 * Always return OK.
3558 */
3559 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003560get_env_tv(arg, rettv, evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003561 char_u **arg;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003562 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003563 int evaluate;
3564{
3565 char_u *string = NULL;
3566 int len;
3567 int cc;
3568 char_u *name;
3569
3570 ++*arg;
3571 name = *arg;
3572 len = get_env_len(arg);
3573 if (evaluate)
3574 {
3575 if (len != 0)
3576 {
3577 cc = name[len];
3578 name[len] = NUL;
3579 /* first try mch_getenv(), fast for normal environment vars */
3580 string = mch_getenv(name);
3581 if (string != NULL && *string != NUL)
3582 string = vim_strsave(string);
3583 else
3584 {
3585 /* next try expanding things like $VIM and ${HOME} */
3586 string = expand_env_save(name - 1);
3587 if (string != NULL && *string == '$')
3588 {
3589 vim_free(string);
3590 string = NULL;
3591 }
3592 }
3593 name[len] = cc;
3594 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003595 rettv->v_type = VAR_STRING;
3596 rettv->vval.v_string = string;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003597 }
3598
3599 return OK;
3600}
3601
3602/*
3603 * Array with names and number of arguments of all internal functions
3604 * MUST BE KEPT SORTED IN strcmp() ORDER FOR BINARY SEARCH!
3605 */
3606static struct fst
3607{
3608 char *f_name; /* function name */
3609 char f_min_argc; /* minimal number of arguments */
3610 char f_max_argc; /* maximal number of arguments */
Bram Moolenaar49cd9572005-01-03 21:06:01 +00003611 void (*f_func) __ARGS((typeval *args, typeval *rvar));
3612 /* implemenation of function */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003613} functions[] =
3614{
3615 {"append", 2, 2, f_append},
3616 {"argc", 0, 0, f_argc},
3617 {"argidx", 0, 0, f_argidx},
3618 {"argv", 1, 1, f_argv},
3619 {"browse", 4, 4, f_browse},
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00003620 {"browsedir", 2, 2, f_browsedir},
Bram Moolenaar071d4272004-06-13 20:20:40 +00003621 {"bufexists", 1, 1, f_bufexists},
3622 {"buffer_exists", 1, 1, f_bufexists}, /* obsolete */
3623 {"buffer_name", 1, 1, f_bufname}, /* obsolete */
3624 {"buffer_number", 1, 1, f_bufnr}, /* obsolete */
3625 {"buflisted", 1, 1, f_buflisted},
3626 {"bufloaded", 1, 1, f_bufloaded},
3627 {"bufname", 1, 1, f_bufname},
3628 {"bufnr", 1, 1, f_bufnr},
3629 {"bufwinnr", 1, 1, f_bufwinnr},
3630 {"byte2line", 1, 1, f_byte2line},
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00003631 {"byteidx", 2, 2, f_byteidx},
Bram Moolenaar071d4272004-06-13 20:20:40 +00003632 {"char2nr", 1, 1, f_char2nr},
3633 {"cindent", 1, 1, f_cindent},
3634 {"col", 1, 1, f_col},
3635 {"confirm", 1, 4, f_confirm},
Bram Moolenaar49cd9572005-01-03 21:06:01 +00003636 {"copy", 1, 1, f_copy},
Bram Moolenaar071d4272004-06-13 20:20:40 +00003637 {"cscope_connection",0,3, f_cscope_connection},
3638 {"cursor", 2, 2, f_cursor},
Bram Moolenaar49cd9572005-01-03 21:06:01 +00003639 {"deepcopy", 1, 1, f_deepcopy},
Bram Moolenaar071d4272004-06-13 20:20:40 +00003640 {"delete", 1, 1, f_delete},
3641 {"did_filetype", 0, 0, f_did_filetype},
Bram Moolenaar47136d72004-10-12 20:02:24 +00003642 {"diff_filler", 1, 1, f_diff_filler},
3643 {"diff_hlID", 2, 2, f_diff_hlID},
Bram Moolenaar071d4272004-06-13 20:20:40 +00003644 {"escape", 2, 2, f_escape},
3645 {"eventhandler", 0, 0, f_eventhandler},
3646 {"executable", 1, 1, f_executable},
3647 {"exists", 1, 1, f_exists},
3648 {"expand", 1, 2, f_expand},
3649 {"file_readable", 1, 1, f_filereadable}, /* obsolete */
3650 {"filereadable", 1, 1, f_filereadable},
3651 {"filewritable", 1, 1, f_filewritable},
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00003652 {"finddir", 1, 3, f_finddir},
3653 {"findfile", 1, 3, f_findfile},
Bram Moolenaar071d4272004-06-13 20:20:40 +00003654 {"fnamemodify", 2, 2, f_fnamemodify},
3655 {"foldclosed", 1, 1, f_foldclosed},
3656 {"foldclosedend", 1, 1, f_foldclosedend},
3657 {"foldlevel", 1, 1, f_foldlevel},
3658 {"foldtext", 0, 0, f_foldtext},
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00003659 {"foldtextresult", 1, 1, f_foldtextresult},
Bram Moolenaar071d4272004-06-13 20:20:40 +00003660 {"foreground", 0, 0, f_foreground},
Bram Moolenaar49cd9572005-01-03 21:06:01 +00003661 {"function", 1, 1, f_function},
Bram Moolenaar071d4272004-06-13 20:20:40 +00003662 {"getbufvar", 2, 2, f_getbufvar},
3663 {"getchar", 0, 1, f_getchar},
3664 {"getcharmod", 0, 0, f_getcharmod},
3665 {"getcmdline", 0, 0, f_getcmdline},
3666 {"getcmdpos", 0, 0, f_getcmdpos},
3667 {"getcwd", 0, 0, f_getcwd},
Bram Moolenaar46c9c732004-12-12 11:37:09 +00003668 {"getfontname", 0, 1, f_getfontname},
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00003669 {"getfperm", 1, 1, f_getfperm},
Bram Moolenaar071d4272004-06-13 20:20:40 +00003670 {"getfsize", 1, 1, f_getfsize},
3671 {"getftime", 1, 1, f_getftime},
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00003672 {"getftype", 1, 1, f_getftype},
Bram Moolenaar071d4272004-06-13 20:20:40 +00003673 {"getline", 1, 1, f_getline},
3674 {"getreg", 0, 1, f_getreg},
3675 {"getregtype", 0, 1, f_getregtype},
3676 {"getwinposx", 0, 0, f_getwinposx},
3677 {"getwinposy", 0, 0, f_getwinposy},
3678 {"getwinvar", 2, 2, f_getwinvar},
3679 {"glob", 1, 1, f_glob},
3680 {"globpath", 2, 2, f_globpath},
3681 {"has", 1, 1, f_has},
3682 {"hasmapto", 1, 2, f_hasmapto},
3683 {"highlightID", 1, 1, f_hlID}, /* obsolete */
3684 {"highlight_exists",1, 1, f_hlexists}, /* obsolete */
3685 {"histadd", 2, 2, f_histadd},
3686 {"histdel", 1, 2, f_histdel},
3687 {"histget", 1, 2, f_histget},
3688 {"histnr", 1, 1, f_histnr},
3689 {"hlID", 1, 1, f_hlID},
3690 {"hlexists", 1, 1, f_hlexists},
3691 {"hostname", 0, 0, f_hostname},
3692 {"iconv", 3, 3, f_iconv},
3693 {"indent", 1, 1, f_indent},
3694 {"input", 1, 2, f_input},
3695 {"inputdialog", 1, 3, f_inputdialog},
3696 {"inputrestore", 0, 0, f_inputrestore},
3697 {"inputsave", 0, 0, f_inputsave},
3698 {"inputsecret", 1, 2, f_inputsecret},
Bram Moolenaar49cd9572005-01-03 21:06:01 +00003699 {"insert", 2, 3, f_insert},
Bram Moolenaar071d4272004-06-13 20:20:40 +00003700 {"isdirectory", 1, 1, f_isdirectory},
3701 {"last_buffer_nr", 0, 0, f_last_buffer_nr},/* obsolete */
Bram Moolenaar49cd9572005-01-03 21:06:01 +00003702 {"len", 1, 1, f_len},
Bram Moolenaar071d4272004-06-13 20:20:40 +00003703 {"libcall", 3, 3, f_libcall},
3704 {"libcallnr", 3, 3, f_libcallnr},
3705 {"line", 1, 1, f_line},
3706 {"line2byte", 1, 1, f_line2byte},
3707 {"lispindent", 1, 1, f_lispindent},
3708 {"localtime", 0, 0, f_localtime},
3709 {"maparg", 1, 2, f_maparg},
3710 {"mapcheck", 1, 2, f_mapcheck},
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00003711 {"match", 2, 4, f_match},
3712 {"matchend", 2, 4, f_matchend},
3713 {"matchstr", 2, 4, f_matchstr},
Bram Moolenaar071d4272004-06-13 20:20:40 +00003714 {"mode", 0, 0, f_mode},
3715 {"nextnonblank", 1, 1, f_nextnonblank},
3716 {"nr2char", 1, 1, f_nr2char},
3717 {"prevnonblank", 1, 1, f_prevnonblank},
3718 {"remote_expr", 2, 3, f_remote_expr},
3719 {"remote_foreground", 1, 1, f_remote_foreground},
3720 {"remote_peek", 1, 2, f_remote_peek},
3721 {"remote_read", 1, 1, f_remote_read},
3722 {"remote_send", 2, 3, f_remote_send},
Bram Moolenaar49cd9572005-01-03 21:06:01 +00003723 {"remove", 2, 2, f_remove},
Bram Moolenaar071d4272004-06-13 20:20:40 +00003724 {"rename", 2, 2, f_rename},
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00003725 {"repeat", 2, 2, f_repeat},
Bram Moolenaar071d4272004-06-13 20:20:40 +00003726 {"resolve", 1, 1, f_resolve},
3727 {"search", 1, 2, f_search},
3728 {"searchpair", 3, 5, f_searchpair},
3729 {"server2client", 2, 2, f_server2client},
3730 {"serverlist", 0, 0, f_serverlist},
3731 {"setbufvar", 3, 3, f_setbufvar},
3732 {"setcmdpos", 1, 1, f_setcmdpos},
3733 {"setline", 2, 2, f_setline},
3734 {"setreg", 2, 3, f_setreg},
3735 {"setwinvar", 3, 3, f_setwinvar},
3736 {"simplify", 1, 1, f_simplify},
3737#ifdef HAVE_STRFTIME
3738 {"strftime", 1, 2, f_strftime},
3739#endif
3740 {"stridx", 2, 2, f_stridx},
Bram Moolenaar49cd9572005-01-03 21:06:01 +00003741 {"string", 1, 1, f_string},
Bram Moolenaar071d4272004-06-13 20:20:40 +00003742 {"strlen", 1, 1, f_strlen},
3743 {"strpart", 2, 3, f_strpart},
3744 {"strridx", 2, 2, f_strridx},
3745 {"strtrans", 1, 1, f_strtrans},
3746 {"submatch", 1, 1, f_submatch},
3747 {"substitute", 4, 4, f_substitute},
3748 {"synID", 3, 3, f_synID},
3749 {"synIDattr", 2, 3, f_synIDattr},
3750 {"synIDtrans", 1, 1, f_synIDtrans},
Bram Moolenaarc0197e22004-09-13 20:26:32 +00003751 {"system", 1, 2, f_system},
Bram Moolenaar071d4272004-06-13 20:20:40 +00003752 {"tempname", 0, 0, f_tempname},
3753 {"tolower", 1, 1, f_tolower},
3754 {"toupper", 1, 1, f_toupper},
Bram Moolenaar8299df92004-07-10 09:47:34 +00003755 {"tr", 3, 3, f_tr},
Bram Moolenaar071d4272004-06-13 20:20:40 +00003756 {"type", 1, 1, f_type},
3757 {"virtcol", 1, 1, f_virtcol},
3758 {"visualmode", 0, 1, f_visualmode},
3759 {"winbufnr", 1, 1, f_winbufnr},
3760 {"wincol", 0, 0, f_wincol},
3761 {"winheight", 1, 1, f_winheight},
3762 {"winline", 0, 0, f_winline},
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00003763 {"winnr", 0, 1, f_winnr},
Bram Moolenaar071d4272004-06-13 20:20:40 +00003764 {"winrestcmd", 0, 0, f_winrestcmd},
3765 {"winwidth", 1, 1, f_winwidth},
3766};
3767
3768#if defined(FEAT_CMDL_COMPL) || defined(PROTO)
3769
3770/*
3771 * Function given to ExpandGeneric() to obtain the list of internal
3772 * or user defined function names.
3773 */
3774 char_u *
3775get_function_name(xp, idx)
3776 expand_T *xp;
3777 int idx;
3778{
3779 static int intidx = -1;
3780 char_u *name;
3781
3782 if (idx == 0)
3783 intidx = -1;
3784 if (intidx < 0)
3785 {
3786 name = get_user_func_name(xp, idx);
3787 if (name != NULL)
3788 return name;
3789 }
3790 if (++intidx < (int)(sizeof(functions) / sizeof(struct fst)))
3791 {
3792 STRCPY(IObuff, functions[intidx].f_name);
3793 STRCAT(IObuff, "(");
3794 if (functions[intidx].f_max_argc == 0)
3795 STRCAT(IObuff, ")");
3796 return IObuff;
3797 }
3798
3799 return NULL;
3800}
3801
3802/*
3803 * Function given to ExpandGeneric() to obtain the list of internal or
3804 * user defined variable or function names.
3805 */
3806/*ARGSUSED*/
3807 char_u *
3808get_expr_name(xp, idx)
3809 expand_T *xp;
3810 int idx;
3811{
3812 static int intidx = -1;
3813 char_u *name;
3814
3815 if (idx == 0)
3816 intidx = -1;
3817 if (intidx < 0)
3818 {
3819 name = get_function_name(xp, idx);
3820 if (name != NULL)
3821 return name;
3822 }
3823 return get_user_var_name(xp, ++intidx);
3824}
3825
3826#endif /* FEAT_CMDL_COMPL */
3827
3828/*
3829 * Find internal function in table above.
3830 * Return index, or -1 if not found
3831 */
3832 static int
3833find_internal_func(name)
3834 char_u *name; /* name of the function */
3835{
3836 int first = 0;
3837 int last = (int)(sizeof(functions) / sizeof(struct fst)) - 1;
3838 int cmp;
3839 int x;
3840
3841 /*
3842 * Find the function name in the table. Binary search.
3843 */
3844 while (first <= last)
3845 {
3846 x = first + ((unsigned)(last - first) >> 1);
3847 cmp = STRCMP(name, functions[x].f_name);
3848 if (cmp < 0)
3849 last = x - 1;
3850 else if (cmp > 0)
3851 first = x + 1;
3852 else
3853 return x;
3854 }
3855 return -1;
3856}
3857
3858/*
Bram Moolenaar49cd9572005-01-03 21:06:01 +00003859 * Check if "name" is a variable of type VAR_FUNC. If so, return the function
3860 * name it contains, otherwise return "name".
3861 */
3862 static char_u *
3863deref_func_name(name, lenp)
3864 char_u *name;
3865 int *lenp;
3866{
3867 VAR v;
3868 int cc;
3869
3870 cc = name[*lenp];
3871 name[*lenp] = NUL;
3872 v = find_var(name, FALSE);
3873 name[*lenp] = cc;
3874 if (v != NULL && v->tv.v_type == VAR_FUNC)
3875 {
3876 if (v->tv.vval.v_string == NULL)
3877 {
3878 *lenp = 0;
3879 return (char_u *)""; /* just in case */
3880 }
3881 *lenp = STRLEN(v->tv.vval.v_string);
3882 return v->tv.vval.v_string;
3883 }
3884
3885 return name;
3886}
3887
3888/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00003889 * Allocate a variable for the result of a function.
3890 * Return OK or FAIL.
3891 */
3892 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003893get_func_tv(name, len, rettv, arg, firstline, lastline, doesrange, evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003894 char_u *name; /* name of the function */
3895 int len; /* length of "name" */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003896 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003897 char_u **arg; /* argument, pointing to the '(' */
3898 linenr_T firstline; /* first line of range */
3899 linenr_T lastline; /* last line of range */
3900 int *doesrange; /* return: function handled range */
3901 int evaluate;
3902{
3903 char_u *argp;
3904 int ret = OK;
3905#define MAX_FUNC_ARGS 20
Bram Moolenaar49cd9572005-01-03 21:06:01 +00003906 typeval argvars[MAX_FUNC_ARGS]; /* vars for arguments */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003907 int argcount = 0; /* number of arguments found */
3908
3909 /*
3910 * Get the arguments.
3911 */
3912 argp = *arg;
3913 while (argcount < MAX_FUNC_ARGS)
3914 {
3915 argp = skipwhite(argp + 1); /* skip the '(' or ',' */
3916 if (*argp == ')' || *argp == ',' || *argp == NUL)
3917 break;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003918 if (eval1(&argp, &argvars[argcount], evaluate) == FAIL)
3919 {
3920 ret = FAIL;
3921 break;
3922 }
3923 ++argcount;
3924 if (*argp != ',')
3925 break;
3926 }
3927 if (*argp == ')')
3928 ++argp;
3929 else
3930 ret = FAIL;
3931
3932 if (ret == OK)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003933 ret = call_func(name, len, rettv, argcount, argvars,
Bram Moolenaar071d4272004-06-13 20:20:40 +00003934 firstline, lastline, doesrange, evaluate);
3935 else if (!aborting())
3936 EMSG2(_("E116: Invalid arguments for function %s"), name);
3937
3938 while (--argcount >= 0)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003939 clear_tv(&argvars[argcount]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003940
3941 *arg = skipwhite(argp);
3942 return ret;
3943}
3944
3945
3946/*
3947 * Call a function with its resolved parameters
3948 * Return OK or FAIL.
3949 */
3950 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003951call_func(name, len, rettv, argcount, argvars, firstline, lastline,
Bram Moolenaar071d4272004-06-13 20:20:40 +00003952 doesrange, evaluate)
3953 char_u *name; /* name of the function */
3954 int len; /* length of "name" */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003955 typeval *rettv; /* return value goes here */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003956 int argcount; /* number of "argvars" */
Bram Moolenaar49cd9572005-01-03 21:06:01 +00003957 typeval *argvars; /* vars for arguments */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003958 linenr_T firstline; /* first line of range */
3959 linenr_T lastline; /* last line of range */
3960 int *doesrange; /* return: function handled range */
3961 int evaluate;
3962{
3963 int ret = FAIL;
3964 static char *errors[] =
3965 {N_("E117: Unknown function: %s"),
3966 N_("E118: Too many arguments for function: %s"),
3967 N_("E119: Not enough arguments for function: %s"),
3968 N_("E120: Using <SID> not in a script context: %s"),
3969 };
3970#define ERROR_UNKNOWN 0
3971#define ERROR_TOOMANY 1
3972#define ERROR_TOOFEW 2
3973#define ERROR_SCRIPT 3
3974#define ERROR_NONE 4
3975#define ERROR_OTHER 5
3976 int error = ERROR_NONE;
3977 int i;
3978 int llen;
3979 ufunc_T *fp;
3980 int cc;
3981#define FLEN_FIXED 40
3982 char_u fname_buf[FLEN_FIXED + 1];
3983 char_u *fname;
3984
3985 /*
3986 * In a script change <SID>name() and s:name() to K_SNR 123_name().
3987 * Change <SNR>123_name() to K_SNR 123_name().
3988 * Use fname_buf[] when it fits, otherwise allocate memory (slow).
3989 */
3990 cc = name[len];
3991 name[len] = NUL;
3992 llen = eval_fname_script(name);
3993 if (llen > 0)
3994 {
3995 fname_buf[0] = K_SPECIAL;
3996 fname_buf[1] = KS_EXTRA;
3997 fname_buf[2] = (int)KE_SNR;
3998 i = 3;
3999 if (eval_fname_sid(name)) /* "<SID>" or "s:" */
4000 {
4001 if (current_SID <= 0)
4002 error = ERROR_SCRIPT;
4003 else
4004 {
4005 sprintf((char *)fname_buf + 3, "%ld_", (long)current_SID);
4006 i = (int)STRLEN(fname_buf);
4007 }
4008 }
4009 if (i + STRLEN(name + llen) < FLEN_FIXED)
4010 {
4011 STRCPY(fname_buf + i, name + llen);
4012 fname = fname_buf;
4013 }
4014 else
4015 {
4016 fname = alloc((unsigned)(i + STRLEN(name + llen) + 1));
4017 if (fname == NULL)
4018 error = ERROR_OTHER;
4019 else
4020 {
4021 mch_memmove(fname, fname_buf, (size_t)i);
4022 STRCPY(fname + i, name + llen);
4023 }
4024 }
4025 }
4026 else
4027 fname = name;
4028
4029 *doesrange = FALSE;
4030
4031
4032 /* execute the function if no errors detected and executing */
4033 if (evaluate && error == ERROR_NONE)
4034 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004035 rettv->v_type = VAR_NUMBER; /* default is number rettv */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004036 error = ERROR_UNKNOWN;
4037
4038 if (!ASCII_ISLOWER(fname[0]))
4039 {
4040 /*
4041 * User defined function.
4042 */
4043 fp = find_func(fname);
4044#ifdef FEAT_AUTOCMD
4045 if (fp == NULL && apply_autocmds(EVENT_FUNCUNDEFINED,
4046 fname, fname, TRUE, NULL)
4047#ifdef FEAT_EVAL
4048 && !aborting()
4049#endif
4050 )
4051 {
4052 /* executed an autocommand, search for function again */
4053 fp = find_func(fname);
4054 }
4055#endif
4056 if (fp != NULL)
4057 {
4058 if (fp->flags & FC_RANGE)
4059 *doesrange = TRUE;
4060 if (argcount < fp->args.ga_len)
4061 error = ERROR_TOOFEW;
4062 else if (!fp->varargs && argcount > fp->args.ga_len)
4063 error = ERROR_TOOMANY;
4064 else
4065 {
4066 /*
4067 * Call the user function.
4068 * Save and restore search patterns, script variables and
4069 * redo buffer.
4070 */
4071 save_search_patterns();
4072 saveRedobuff();
4073 ++fp->calls;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004074 call_user_func(fp, argcount, argvars, rettv,
Bram Moolenaar071d4272004-06-13 20:20:40 +00004075 firstline, lastline);
4076 --fp->calls;
4077 restoreRedobuff();
4078 restore_search_patterns();
4079 error = ERROR_NONE;
4080 }
4081 }
4082 }
4083 else
4084 {
4085 /*
4086 * Find the function name in the table, call its implementation.
4087 */
4088 i = find_internal_func(fname);
4089 if (i >= 0)
4090 {
4091 if (argcount < functions[i].f_min_argc)
4092 error = ERROR_TOOFEW;
4093 else if (argcount > functions[i].f_max_argc)
4094 error = ERROR_TOOMANY;
4095 else
4096 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004097 argvars[argcount].v_type = VAR_UNKNOWN;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004098 functions[i].f_func(argvars, rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004099 error = ERROR_NONE;
4100 }
4101 }
4102 }
4103 /*
4104 * The function call (or "FuncUndefined" autocommand sequence) might
4105 * have been aborted by an error, an interrupt, or an explicitly thrown
4106 * exception that has not been caught so far. This situation can be
4107 * tested for by calling aborting(). For an error in an internal
4108 * function or for the "E132" error in call_user_func(), however, the
4109 * throw point at which the "force_abort" flag (temporarily reset by
4110 * emsg()) is normally updated has not been reached yet. We need to
4111 * update that flag first to make aborting() reliable.
4112 */
4113 update_force_abort();
4114 }
4115 if (error == ERROR_NONE)
4116 ret = OK;
4117
4118 /*
4119 * Report an error unless the argument evaluation or function call has been
4120 * cancelled due to an aborting error, an interrupt, or an exception.
4121 */
4122 if (error < ERROR_NONE && !aborting())
4123 EMSG2((char_u *)_(errors[error]), name);
4124
4125 name[len] = cc;
4126 if (fname != name && fname != fname_buf)
4127 vim_free(fname);
4128
4129 return ret;
4130}
4131
4132/*********************************************
4133 * Implementation of the built-in functions
4134 */
4135
4136/*
4137 * "append(lnum, string)" function
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004138 * or "append(list, item)" function
Bram Moolenaar071d4272004-06-13 20:20:40 +00004139 */
4140 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004141f_append(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004142 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004143 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004144{
4145 long lnum;
4146
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004147 rettv->vval.v_number = 1; /* Default: Failed */
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004148 if (argvars[0].v_type == VAR_LIST)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004149 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004150 if (argvars[0].vval.v_list != NULL
4151 && list_append_tv(argvars[0].vval.v_list, &argvars[1]) == OK)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004152 copy_tv(&argvars[0], rettv);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004153 }
4154 else
4155 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004156 lnum = get_tv_lnum(argvars);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004157 if (lnum >= 0
4158 && lnum <= curbuf->b_ml.ml_line_count
4159 && u_save(lnum, lnum + 1) == OK)
4160 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004161 ml_append(lnum, get_tv_string(&argvars[1]), (colnr_T)0, FALSE);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004162 if (curwin->w_cursor.lnum > lnum)
4163 ++curwin->w_cursor.lnum;
4164 appended_lines_mark(lnum, 1L);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004165 rettv->vval.v_number = 0;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004166 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004167 }
4168}
4169
4170/*
4171 * "argc()" function
4172 */
4173/* ARGSUSED */
4174 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004175f_argc(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004176 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004177 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004178{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004179 rettv->vval.v_number = ARGCOUNT;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004180}
4181
4182/*
4183 * "argidx()" function
4184 */
4185/* ARGSUSED */
4186 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004187f_argidx(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004188 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004189 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004190{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004191 rettv->vval.v_number = curwin->w_arg_idx;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004192}
4193
4194/*
4195 * "argv(nr)" function
4196 */
4197 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004198f_argv(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004199 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004200 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004201{
4202 int idx;
4203
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004204 idx = get_tv_number(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004205 if (idx >= 0 && idx < ARGCOUNT)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004206 rettv->vval.v_string = vim_strsave(alist_name(&ARGLIST[idx]));
Bram Moolenaar071d4272004-06-13 20:20:40 +00004207 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004208 rettv->vval.v_string = NULL;
4209 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004210}
4211
4212/*
4213 * "browse(save, title, initdir, default)" function
4214 */
4215/* ARGSUSED */
4216 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004217f_browse(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004218 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004219 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004220{
4221#ifdef FEAT_BROWSE
4222 int save;
4223 char_u *title;
4224 char_u *initdir;
4225 char_u *defname;
4226 char_u buf[NUMBUFLEN];
4227 char_u buf2[NUMBUFLEN];
4228
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004229 save = get_tv_number(&argvars[0]);
4230 title = get_tv_string(&argvars[1]);
4231 initdir = get_tv_string_buf(&argvars[2], buf);
4232 defname = get_tv_string_buf(&argvars[3], buf2);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004233
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004234 rettv->vval.v_string =
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00004235 do_browse(save ? BROWSE_SAVE : 0,
4236 title, defname, NULL, initdir, NULL, curbuf);
4237#else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004238 rettv->vval.v_string = NULL;
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00004239#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004240 rettv->v_type = VAR_STRING;
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00004241}
4242
4243/*
4244 * "browsedir(title, initdir)" function
4245 */
4246/* ARGSUSED */
4247 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004248f_browsedir(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004249 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004250 typeval *rettv;
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00004251{
4252#ifdef FEAT_BROWSE
4253 char_u *title;
4254 char_u *initdir;
4255 char_u buf[NUMBUFLEN];
4256
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004257 title = get_tv_string(&argvars[0]);
4258 initdir = get_tv_string_buf(&argvars[1], buf);
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00004259
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004260 rettv->vval.v_string = do_browse(BROWSE_DIR,
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00004261 title, NULL, NULL, initdir, NULL, curbuf);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004262#else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004263 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004264#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004265 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004266}
4267
4268/*
4269 * Find a buffer by number or exact name.
4270 */
4271 static buf_T *
4272find_buffer(avar)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004273 typeval *avar;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004274{
4275 buf_T *buf = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004276
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004277 if (avar->v_type == VAR_NUMBER)
4278 buf = buflist_findnr((int)avar->vval.v_number);
4279 else if (avar->vval.v_string != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004280 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004281 buf = buflist_findname_exp(avar->vval.v_string);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004282 if (buf == NULL)
4283 {
4284 /* No full path name match, try a match with a URL or a "nofile"
4285 * buffer, these don't use the full path. */
4286 for (buf = firstbuf; buf != NULL; buf = buf->b_next)
4287 if (buf->b_fname != NULL
4288 && (path_with_url(buf->b_fname)
4289#ifdef FEAT_QUICKFIX
4290 || bt_nofile(buf)
4291#endif
4292 )
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004293 && STRCMP(buf->b_fname, avar->vval.v_string) == 0)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004294 break;
4295 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004296 }
4297 return buf;
4298}
4299
4300/*
4301 * "bufexists(expr)" function
4302 */
4303 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004304f_bufexists(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004305 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004306 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004307{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004308 rettv->vval.v_number = (find_buffer(&argvars[0]) != NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004309}
4310
4311/*
4312 * "buflisted(expr)" function
4313 */
4314 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004315f_buflisted(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004316 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004317 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004318{
4319 buf_T *buf;
4320
4321 buf = find_buffer(&argvars[0]);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004322 rettv->vval.v_number = (buf != NULL && buf->b_p_bl);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004323}
4324
4325/*
4326 * "bufloaded(expr)" function
4327 */
4328 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004329f_bufloaded(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004330 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004331 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004332{
4333 buf_T *buf;
4334
4335 buf = find_buffer(&argvars[0]);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004336 rettv->vval.v_number = (buf != NULL && buf->b_ml.ml_mfp != NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004337}
4338
4339/*
4340 * Get buffer by number or pattern.
4341 */
4342 static buf_T *
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004343get_buf_tv(tv)
4344 typeval *tv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004345{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004346 char_u *name = tv->vval.v_string;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004347 int save_magic;
4348 char_u *save_cpo;
4349 buf_T *buf;
4350
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004351 if (tv->v_type == VAR_NUMBER)
4352 return buflist_findnr((int)tv->vval.v_number);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004353 if (name == NULL || *name == NUL)
4354 return curbuf;
4355 if (name[0] == '$' && name[1] == NUL)
4356 return lastbuf;
4357
4358 /* Ignore 'magic' and 'cpoptions' here to make scripts portable */
4359 save_magic = p_magic;
4360 p_magic = TRUE;
4361 save_cpo = p_cpo;
4362 p_cpo = (char_u *)"";
4363
4364 buf = buflist_findnr(buflist_findpat(name, name + STRLEN(name),
4365 TRUE, FALSE));
4366
4367 p_magic = save_magic;
4368 p_cpo = save_cpo;
4369
4370 /* If not found, try expanding the name, like done for bufexists(). */
4371 if (buf == NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004372 buf = find_buffer(tv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004373
4374 return buf;
4375}
4376
4377/*
4378 * "bufname(expr)" function
4379 */
4380 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004381f_bufname(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004382 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004383 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004384{
4385 buf_T *buf;
4386
4387 ++emsg_off;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004388 buf = get_buf_tv(&argvars[0]);
4389 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004390 if (buf != NULL && buf->b_fname != NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004391 rettv->vval.v_string = vim_strsave(buf->b_fname);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004392 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004393 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004394 --emsg_off;
4395}
4396
4397/*
4398 * "bufnr(expr)" function
4399 */
4400 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004401f_bufnr(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004402 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004403 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004404{
4405 buf_T *buf;
4406
4407 ++emsg_off;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004408 buf = get_buf_tv(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004409 if (buf != NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004410 rettv->vval.v_number = buf->b_fnum;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004411 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004412 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004413 --emsg_off;
4414}
4415
4416/*
4417 * "bufwinnr(nr)" function
4418 */
4419 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004420f_bufwinnr(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004421 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004422 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004423{
4424#ifdef FEAT_WINDOWS
4425 win_T *wp;
4426 int winnr = 0;
4427#endif
4428 buf_T *buf;
4429
4430 ++emsg_off;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004431 buf = get_buf_tv(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004432#ifdef FEAT_WINDOWS
4433 for (wp = firstwin; wp; wp = wp->w_next)
4434 {
4435 ++winnr;
4436 if (wp->w_buffer == buf)
4437 break;
4438 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004439 rettv->vval.v_number = (wp != NULL ? winnr : -1);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004440#else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004441 rettv->vval.v_number = (curwin->w_buffer == buf ? 1 : -1);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004442#endif
4443 --emsg_off;
4444}
4445
4446/*
4447 * "byte2line(byte)" function
4448 */
4449/*ARGSUSED*/
4450 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004451f_byte2line(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004452 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004453 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004454{
4455#ifndef FEAT_BYTEOFF
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004456 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004457#else
4458 long boff = 0;
4459
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004460 boff = get_tv_number(&argvars[0]) - 1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004461 if (boff < 0)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004462 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004463 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004464 rettv->vval.v_number = ml_find_line_or_offset(curbuf,
Bram Moolenaar071d4272004-06-13 20:20:40 +00004465 (linenr_T)0, &boff);
4466#endif
4467}
4468
4469/*
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00004470 * "byteidx()" function
4471 */
4472/*ARGSUSED*/
4473 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004474f_byteidx(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004475 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004476 typeval *rettv;
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00004477{
4478#ifdef FEAT_MBYTE
4479 char_u *t;
4480#endif
4481 char_u *str;
4482 long idx;
4483
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004484 str = get_tv_string(&argvars[0]);
4485 idx = get_tv_number(&argvars[1]);
4486 rettv->vval.v_number = -1;
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00004487 if (idx < 0)
4488 return;
4489
4490#ifdef FEAT_MBYTE
4491 t = str;
4492 for ( ; idx > 0; idx--)
4493 {
4494 if (*t == NUL) /* EOL reached */
4495 return;
4496 t += mb_ptr2len_check(t);
4497 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004498 rettv->vval.v_number = t - str;
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00004499#else
4500 if (idx <= STRLEN(str))
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004501 rettv->vval.v_number = idx;
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00004502#endif
4503}
4504
4505/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00004506 * "char2nr(string)" function
4507 */
4508 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004509f_char2nr(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004510 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004511 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004512{
4513#ifdef FEAT_MBYTE
4514 if (has_mbyte)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004515 rettv->vval.v_number =
4516 (*mb_ptr2char)(get_tv_string(&argvars[0]));
Bram Moolenaar071d4272004-06-13 20:20:40 +00004517 else
4518#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004519 rettv->vval.v_number = get_tv_string(&argvars[0])[0];
Bram Moolenaar071d4272004-06-13 20:20:40 +00004520}
4521
4522/*
4523 * "cindent(lnum)" function
4524 */
4525 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004526f_cindent(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004527 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004528 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004529{
4530#ifdef FEAT_CINDENT
4531 pos_T pos;
4532 linenr_T lnum;
4533
4534 pos = curwin->w_cursor;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004535 lnum = get_tv_lnum(argvars);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004536 if (lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count)
4537 {
4538 curwin->w_cursor.lnum = lnum;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004539 rettv->vval.v_number = get_c_indent();
Bram Moolenaar071d4272004-06-13 20:20:40 +00004540 curwin->w_cursor = pos;
4541 }
4542 else
4543#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004544 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004545}
4546
4547/*
4548 * "col(string)" function
4549 */
4550 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004551f_col(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004552 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004553 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004554{
4555 colnr_T col = 0;
4556 pos_T *fp;
4557
4558 fp = var2fpos(&argvars[0], FALSE);
4559 if (fp != NULL)
4560 {
4561 if (fp->col == MAXCOL)
4562 {
4563 /* '> can be MAXCOL, get the length of the line then */
4564 if (fp->lnum <= curbuf->b_ml.ml_line_count)
4565 col = STRLEN(ml_get(fp->lnum)) + 1;
4566 else
4567 col = MAXCOL;
4568 }
4569 else
4570 {
4571 col = fp->col + 1;
4572#ifdef FEAT_VIRTUALEDIT
4573 /* col(".") when the cursor is on the NUL at the end of the line
4574 * because of "coladd" can be seen as an extra column. */
4575 if (virtual_active() && fp == &curwin->w_cursor)
4576 {
4577 char_u *p = ml_get_cursor();
4578
4579 if (curwin->w_cursor.coladd >= (colnr_T)chartabsize(p,
4580 curwin->w_virtcol - curwin->w_cursor.coladd))
4581 {
4582# ifdef FEAT_MBYTE
4583 int l;
4584
4585 if (*p != NUL && p[(l = (*mb_ptr2len_check)(p))] == NUL)
4586 col += l;
4587# else
4588 if (*p != NUL && p[1] == NUL)
4589 ++col;
4590# endif
4591 }
4592 }
4593#endif
4594 }
4595 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004596 rettv->vval.v_number = col;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004597}
4598
4599/*
4600 * "confirm(message, buttons[, default [, type]])" function
4601 */
4602/*ARGSUSED*/
4603 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004604f_confirm(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004605 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004606 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004607{
4608#if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
4609 char_u *message;
4610 char_u *buttons = NULL;
4611 char_u buf[NUMBUFLEN];
4612 char_u buf2[NUMBUFLEN];
4613 int def = 1;
4614 int type = VIM_GENERIC;
4615 int c;
4616
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004617 message = get_tv_string(&argvars[0]);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004618 if (argvars[1].v_type != VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004619 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004620 buttons = get_tv_string_buf(&argvars[1], buf);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004621 if (argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004622 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004623 def = get_tv_number(&argvars[2]);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004624 if (argvars[3].v_type != VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004625 {
4626 /* avoid that TOUPPER_ASC calls get_var_string_buf() twice */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004627 c = *get_tv_string_buf(&argvars[3], buf2);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004628 switch (TOUPPER_ASC(c))
4629 {
4630 case 'E': type = VIM_ERROR; break;
4631 case 'Q': type = VIM_QUESTION; break;
4632 case 'I': type = VIM_INFO; break;
4633 case 'W': type = VIM_WARNING; break;
4634 case 'G': type = VIM_GENERIC; break;
4635 }
4636 }
4637 }
4638 }
4639
4640 if (buttons == NULL || *buttons == NUL)
4641 buttons = (char_u *)_("&Ok");
4642
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004643 rettv->vval.v_number = do_dialog(type, NULL, message, buttons,
Bram Moolenaar071d4272004-06-13 20:20:40 +00004644 def, NULL);
4645#else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004646 rettv->vval.v_number = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004647#endif
4648}
4649
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004650/*
4651 * "copy()" function
4652 */
4653 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004654f_copy(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004655 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004656 typeval *rettv;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004657{
4658 if (argvars[0].v_type == VAR_LIST)
4659 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004660 rettv->v_type = VAR_LIST;
4661 rettv->vval.v_list = list_copy(argvars[0].vval.v_list, FALSE);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004662 }
4663 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004664 copy_tv(&argvars[0], rettv);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004665}
Bram Moolenaar071d4272004-06-13 20:20:40 +00004666
4667/*
4668 * "cscope_connection([{num} , {dbpath} [, {prepend}]])" function
4669 *
4670 * Checks the existence of a cscope connection.
4671 */
4672/*ARGSUSED*/
4673 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004674f_cscope_connection(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004675 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004676 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004677{
4678#ifdef FEAT_CSCOPE
4679 int num = 0;
4680 char_u *dbpath = NULL;
4681 char_u *prepend = NULL;
4682 char_u buf[NUMBUFLEN];
4683
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004684 if (argvars[0].v_type != VAR_UNKNOWN
4685 && argvars[1].v_type != VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004686 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004687 num = (int)get_tv_number(&argvars[0]);
4688 dbpath = get_tv_string(&argvars[1]);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004689 if (argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004690 prepend = get_tv_string_buf(&argvars[2], buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004691 }
4692
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004693 rettv->vval.v_number = cs_connection(num, dbpath, prepend);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004694#else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004695 rettv->vval.v_number = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004696#endif
4697}
4698
4699/*
4700 * "cursor(lnum, col)" function
4701 *
4702 * Moves the cursor to the specified line and column
4703 */
4704/*ARGSUSED*/
4705 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004706f_cursor(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004707 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004708 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004709{
4710 long line, col;
4711
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004712 line = get_tv_lnum(argvars);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004713 if (line > 0)
4714 curwin->w_cursor.lnum = line;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004715 col = get_tv_number(&argvars[1]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004716 if (col > 0)
4717 curwin->w_cursor.col = col - 1;
4718#ifdef FEAT_VIRTUALEDIT
4719 curwin->w_cursor.coladd = 0;
4720#endif
4721
4722 /* Make sure the cursor is in a valid position. */
4723 check_cursor();
4724#ifdef FEAT_MBYTE
4725 /* Correct cursor for multi-byte character. */
4726 if (has_mbyte)
4727 mb_adjust_cursor();
4728#endif
Bram Moolenaarf4b8e572004-06-24 15:53:16 +00004729
4730 curwin->w_set_curswant = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004731}
4732
4733/*
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004734 * "deepcopy()" function
Bram Moolenaar071d4272004-06-13 20:20:40 +00004735 */
4736 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004737f_deepcopy(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{
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004741 if (argvars[0].v_type == VAR_LIST)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004742 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004743 rettv->v_type = VAR_LIST;
4744 rettv->vval.v_list = list_copy(argvars[0].vval.v_list, TRUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004745 }
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004746 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004747 copy_tv(&argvars[0], rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004748}
4749
4750/*
4751 * "delete()" function
4752 */
4753 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004754f_delete(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004755 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004756 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004757{
4758 if (check_restricted() || check_secure())
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004759 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004760 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004761 rettv->vval.v_number = mch_remove(get_tv_string(&argvars[0]));
Bram Moolenaar071d4272004-06-13 20:20:40 +00004762}
4763
4764/*
4765 * "did_filetype()" function
4766 */
4767/*ARGSUSED*/
4768 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004769f_did_filetype(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004770 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004771 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004772{
4773#ifdef FEAT_AUTOCMD
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004774 rettv->vval.v_number = did_filetype;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004775#else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004776 rettv->vval.v_number = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004777#endif
4778}
4779
4780/*
Bram Moolenaar47136d72004-10-12 20:02:24 +00004781 * "diff_filler()" function
4782 */
4783/*ARGSUSED*/
4784 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004785f_diff_filler(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004786 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004787 typeval *rettv;
Bram Moolenaar47136d72004-10-12 20:02:24 +00004788{
4789#ifdef FEAT_DIFF
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004790 rettv->vval.v_number = diff_check_fill(curwin, get_tv_lnum(argvars));
Bram Moolenaar47136d72004-10-12 20:02:24 +00004791#endif
4792}
4793
4794/*
4795 * "diff_hlID()" function
4796 */
4797/*ARGSUSED*/
4798 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004799f_diff_hlID(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004800 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004801 typeval *rettv;
Bram Moolenaar47136d72004-10-12 20:02:24 +00004802{
4803#ifdef FEAT_DIFF
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004804 linenr_T lnum = get_tv_lnum(argvars);
Bram Moolenaar47136d72004-10-12 20:02:24 +00004805 static linenr_T prev_lnum = 0;
4806 static int changedtick = 0;
4807 static int fnum = 0;
4808 static int change_start = 0;
4809 static int change_end = 0;
4810 static enum hlf_value hlID = 0;
4811 int filler_lines;
4812 int col;
4813
4814 if (lnum != prev_lnum
4815 || changedtick != curbuf->b_changedtick
4816 || fnum != curbuf->b_fnum)
4817 {
4818 /* New line, buffer, change: need to get the values. */
4819 filler_lines = diff_check(curwin, lnum);
4820 if (filler_lines < 0)
4821 {
4822 if (filler_lines == -1)
4823 {
4824 change_start = MAXCOL;
4825 change_end = -1;
4826 if (diff_find_change(curwin, lnum, &change_start, &change_end))
4827 hlID = HLF_ADD; /* added line */
4828 else
4829 hlID = HLF_CHD; /* changed line */
4830 }
4831 else
4832 hlID = HLF_ADD; /* added line */
4833 }
4834 else
4835 hlID = (enum hlf_value)0;
4836 prev_lnum = lnum;
4837 changedtick = curbuf->b_changedtick;
4838 fnum = curbuf->b_fnum;
4839 }
4840
4841 if (hlID == HLF_CHD || hlID == HLF_TXD)
4842 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004843 col = get_tv_number(&argvars[1]) - 1;
Bram Moolenaar47136d72004-10-12 20:02:24 +00004844 if (col >= change_start && col <= change_end)
4845 hlID = HLF_TXD; /* changed text */
4846 else
4847 hlID = HLF_CHD; /* changed line */
4848 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004849 rettv->vval.v_number = hlID == (enum hlf_value)0 ? 0 : (int)hlID;
Bram Moolenaar47136d72004-10-12 20:02:24 +00004850#endif
4851}
4852
4853/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00004854 * "escape({string}, {chars})" function
4855 */
4856 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004857f_escape(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004858 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004859 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004860{
4861 char_u buf[NUMBUFLEN];
4862
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004863 rettv->vval.v_string =
4864 vim_strsave_escaped(get_tv_string(&argvars[0]),
4865 get_tv_string_buf(&argvars[1], buf));
4866 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004867}
4868
4869/*
4870 * "eventhandler()" function
4871 */
4872/*ARGSUSED*/
4873 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004874f_eventhandler(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004875 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004876 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004877{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004878 rettv->vval.v_number = vgetc_busy;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004879}
4880
4881/*
4882 * "executable()" function
4883 */
4884 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004885f_executable(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004886 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004887 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004888{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004889 rettv->vval.v_number = mch_can_exe(get_tv_string(&argvars[0]));
Bram Moolenaar071d4272004-06-13 20:20:40 +00004890}
4891
4892/*
4893 * "exists()" function
4894 */
4895 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004896f_exists(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004897 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004898 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004899{
4900 char_u *p;
4901 char_u *name;
4902 int n = FALSE;
4903 int len = 0;
4904
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004905 p = get_tv_string(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004906 if (*p == '$') /* environment variable */
4907 {
4908 /* first try "normal" environment variables (fast) */
4909 if (mch_getenv(p + 1) != NULL)
4910 n = TRUE;
4911 else
4912 {
4913 /* try expanding things like $VIM and ${HOME} */
4914 p = expand_env_save(p);
4915 if (p != NULL && *p != '$')
4916 n = TRUE;
4917 vim_free(p);
4918 }
4919 }
4920 else if (*p == '&' || *p == '+') /* option */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004921 n = (get_option_tv(&p, NULL, TRUE) == OK);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004922 else if (*p == '*') /* internal or user defined function */
4923 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004924 n = function_exists(p + 1);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004925 }
4926 else if (*p == ':')
4927 {
4928 n = cmd_exists(p + 1);
4929 }
4930 else if (*p == '#')
4931 {
4932#ifdef FEAT_AUTOCMD
4933 name = p + 1;
4934 p = vim_strchr(name, '#');
4935 if (p != NULL)
4936 n = au_exists(name, p, p + 1);
4937 else
4938 n = au_exists(name, name + STRLEN(name), NULL);
4939#endif
4940 }
4941 else /* internal variable */
4942 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00004943 char_u *expr_start;
4944 char_u *expr_end;
4945 char_u *temp_string = NULL;
4946 char_u *s;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004947 name = p;
4948
Bram Moolenaar071d4272004-06-13 20:20:40 +00004949 /* Find the end of the name. */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004950 s = find_name_end(name, &expr_start, &expr_end, FALSE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004951 if (expr_start != NULL)
4952 {
4953 temp_string = make_expanded_name(name, expr_start, expr_end, s);
4954 if (temp_string != NULL)
4955 {
4956 len = STRLEN(temp_string);
4957 name = temp_string;
4958 }
4959 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004960 if (len == 0)
4961 len = get_id_len(&p);
4962 if (len != 0)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004963 n = (get_var_tv(name, len, NULL) == OK);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004964
Bram Moolenaar071d4272004-06-13 20:20:40 +00004965 vim_free(temp_string);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004966 }
4967
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004968 rettv->vval.v_number = n;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004969}
4970
4971/*
4972 * "expand()" function
4973 */
4974 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004975f_expand(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004976 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004977 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004978{
4979 char_u *s;
4980 int len;
4981 char_u *errormsg;
4982 int flags = WILD_SILENT|WILD_USE_NL|WILD_LIST_NOTFOUND;
4983 expand_T xpc;
4984
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004985 rettv->v_type = VAR_STRING;
4986 s = get_tv_string(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004987 if (*s == '%' || *s == '#' || *s == '<')
4988 {
4989 ++emsg_off;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004990 rettv->vval.v_string = eval_vars(s, &len, NULL, &errormsg, s);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004991 --emsg_off;
4992 }
4993 else
4994 {
4995 /* When the optional second argument is non-zero, don't remove matches
4996 * for 'suffixes' and 'wildignore' */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004997 if (argvars[1].v_type != VAR_UNKNOWN && get_tv_number(&argvars[1]))
Bram Moolenaar071d4272004-06-13 20:20:40 +00004998 flags |= WILD_KEEP_ALL;
4999 ExpandInit(&xpc);
5000 xpc.xp_context = EXPAND_FILES;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005001 rettv->vval.v_string = ExpandOne(&xpc, s, NULL, flags, WILD_ALL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005002 ExpandCleanup(&xpc);
5003 }
5004}
5005
5006/*
5007 * "filereadable()" function
5008 */
5009 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005010f_filereadable(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005011 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005012 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005013{
5014 FILE *fd;
5015 char_u *p;
5016 int n;
5017
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005018 p = get_tv_string(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005019 if (*p && !mch_isdir(p) && (fd = mch_fopen((char *)p, "r")) != NULL)
5020 {
5021 n = TRUE;
5022 fclose(fd);
5023 }
5024 else
5025 n = FALSE;
5026
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005027 rettv->vval.v_number = n;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005028}
5029
5030/*
5031 * return 0 for not writable, 1 for writable file, 2 for a dir which we have
5032 * rights to write into.
5033 */
5034 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005035f_filewritable(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005036 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005037 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005038{
5039 char_u *p;
5040 int retval = 0;
5041#if defined(UNIX) || defined(VMS)
5042 int perm = 0;
5043#endif
5044
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005045 p = get_tv_string(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005046#if defined(UNIX) || defined(VMS)
5047 perm = mch_getperm(p);
5048#endif
5049#ifndef MACOS_CLASSIC /* TODO: get either mch_writable or mch_access */
5050 if (
5051# ifdef WIN3264
5052 mch_writable(p) &&
5053# else
5054# if defined(UNIX) || defined(VMS)
5055 (perm & 0222) &&
5056# endif
5057# endif
5058 mch_access((char *)p, W_OK) == 0
5059 )
5060#endif
5061 {
5062 ++retval;
5063 if (mch_isdir(p))
5064 ++retval;
5065 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005066 rettv->vval.v_number = retval;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005067}
5068
5069/*
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00005070 * "finddir({fname}[, {path}[, {count}]])" function
5071 */
5072 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005073f_finddir(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005074 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005075 typeval *rettv;
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00005076{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005077 f_findfilendir(argvars, rettv, TRUE);
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00005078}
5079
5080/*
5081 * "findfile({fname}[, {path}[, {count}]])" function
5082 */
5083 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005084f_findfile(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005085 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005086 typeval *rettv;
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00005087{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005088 f_findfilendir(argvars, rettv, FALSE);
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00005089}
5090
5091 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005092f_findfilendir(argvars, rettv, dir)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005093 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005094 typeval *rettv;
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00005095 int dir;
5096{
5097#ifdef FEAT_SEARCHPATH
5098 char_u *fname;
5099 char_u *fresult = NULL;
5100 char_u *path = *curbuf->b_p_path == NUL ? p_path : curbuf->b_p_path;
5101 char_u *p;
5102 char_u pathbuf[NUMBUFLEN];
5103 int count = 1;
5104 int first = TRUE;
5105
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005106 fname = get_tv_string(&argvars[0]);
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00005107
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005108 if (argvars[1].v_type != VAR_UNKNOWN)
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00005109 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005110 p = get_tv_string_buf(&argvars[1], pathbuf);
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00005111 if (*p != NUL)
5112 path = p;
5113
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005114 if (argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005115 count = get_tv_number(&argvars[2]);
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00005116 }
5117
5118 do
5119 {
5120 vim_free(fresult);
5121 fresult = find_file_in_path_option(first ? fname : NULL,
5122 first ? (int)STRLEN(fname) : 0,
5123 0, first, path, dir, NULL);
5124 first = FALSE;
5125 } while (--count > 0 && fresult != NULL);
5126
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005127 rettv->vval.v_string = fresult;
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00005128#else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005129 rettv->vval.v_string = NULL;
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00005130#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005131 rettv->v_type = VAR_STRING;
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00005132}
5133
5134/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00005135 * "fnamemodify({fname}, {mods})" function
5136 */
5137 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005138f_fnamemodify(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005139 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005140 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005141{
5142 char_u *fname;
5143 char_u *mods;
5144 int usedlen = 0;
5145 int len;
5146 char_u *fbuf = NULL;
5147 char_u buf[NUMBUFLEN];
5148
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005149 fname = get_tv_string(&argvars[0]);
5150 mods = get_tv_string_buf(&argvars[1], buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005151 len = (int)STRLEN(fname);
5152
5153 (void)modify_fname(mods, &usedlen, &fname, &fbuf, &len);
5154
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005155 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005156 if (fname == NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005157 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005158 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005159 rettv->vval.v_string = vim_strnsave(fname, len);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005160 vim_free(fbuf);
5161}
5162
5163/*
5164 * "foldclosed()" function
5165 */
5166 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005167f_foldclosed(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005168 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005169 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005170{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005171 foldclosed_both(argvars, rettv, FALSE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005172}
5173
5174/*
5175 * "foldclosedend()" function
5176 */
5177 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005178f_foldclosedend(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005179 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005180 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005181{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005182 foldclosed_both(argvars, rettv, TRUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005183}
5184
5185/*
5186 * "foldclosed()" function
5187 */
5188 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005189foldclosed_both(argvars, rettv, end)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005190 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005191 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005192 int end;
5193{
5194#ifdef FEAT_FOLDING
5195 linenr_T lnum;
5196 linenr_T first, last;
5197
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005198 lnum = get_tv_lnum(argvars);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005199 if (lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count)
5200 {
5201 if (hasFoldingWin(curwin, lnum, &first, &last, FALSE, NULL))
5202 {
5203 if (end)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005204 rettv->vval.v_number = (varnumber_T)last;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005205 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005206 rettv->vval.v_number = (varnumber_T)first;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005207 return;
5208 }
5209 }
5210#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005211 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005212}
5213
5214/*
5215 * "foldlevel()" function
5216 */
5217 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005218f_foldlevel(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005219 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005220 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005221{
5222#ifdef FEAT_FOLDING
5223 linenr_T lnum;
5224
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005225 lnum = get_tv_lnum(argvars);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005226 if (lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005227 rettv->vval.v_number = foldLevel(lnum);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005228 else
5229#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005230 rettv->vval.v_number = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005231}
5232
5233/*
5234 * "foldtext()" function
5235 */
5236/*ARGSUSED*/
5237 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005238f_foldtext(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005239 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005240 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005241{
5242#ifdef FEAT_FOLDING
5243 linenr_T lnum;
5244 char_u *s;
5245 char_u *r;
5246 int len;
5247 char *txt;
5248#endif
5249
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005250 rettv->v_type = VAR_STRING;
5251 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005252#ifdef FEAT_FOLDING
5253 if ((linenr_T)vimvars[VV_FOLDSTART].val > 0
5254 && (linenr_T)vimvars[VV_FOLDEND].val <= curbuf->b_ml.ml_line_count
5255 && vimvars[VV_FOLDDASHES].val != NULL)
5256 {
5257 /* Find first non-empty line in the fold. */
5258 lnum = (linenr_T)vimvars[VV_FOLDSTART].val;
5259 while (lnum < (linenr_T)vimvars[VV_FOLDEND].val)
5260 {
5261 if (!linewhite(lnum))
5262 break;
5263 ++lnum;
5264 }
5265
5266 /* Find interesting text in this line. */
5267 s = skipwhite(ml_get(lnum));
5268 /* skip C comment-start */
5269 if (s[0] == '/' && (s[1] == '*' || s[1] == '/'))
Bram Moolenaar293ee4d2004-12-09 21:34:53 +00005270 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00005271 s = skipwhite(s + 2);
Bram Moolenaar293ee4d2004-12-09 21:34:53 +00005272 if (*skipwhite(s) == NUL
5273 && lnum + 1 < (linenr_T)vimvars[VV_FOLDEND].val)
5274 {
5275 s = skipwhite(ml_get(lnum + 1));
5276 if (*s == '*')
5277 s = skipwhite(s + 1);
5278 }
5279 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00005280 txt = _("+-%s%3ld lines: ");
5281 r = alloc((unsigned)(STRLEN(txt)
5282 + STRLEN(vimvars[VV_FOLDDASHES].val) /* for %s */
5283 + 20 /* for %3ld */
5284 + STRLEN(s))); /* concatenated */
5285 if (r != NULL)
5286 {
5287 sprintf((char *)r, txt, vimvars[VV_FOLDDASHES].val,
5288 (long)((linenr_T)vimvars[VV_FOLDEND].val
5289 - (linenr_T)vimvars[VV_FOLDSTART].val + 1));
5290 len = (int)STRLEN(r);
5291 STRCAT(r, s);
5292 /* remove 'foldmarker' and 'commentstring' */
5293 foldtext_cleanup(r + len);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005294 rettv->vval.v_string = r;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005295 }
5296 }
5297#endif
5298}
5299
5300/*
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00005301 * "foldtextresult(lnum)" function
5302 */
5303/*ARGSUSED*/
5304 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005305f_foldtextresult(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005306 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005307 typeval *rettv;
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00005308{
5309#ifdef FEAT_FOLDING
5310 linenr_T lnum;
5311 char_u *text;
5312 char_u buf[51];
5313 foldinfo_T foldinfo;
5314 int fold_count;
5315#endif
5316
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005317 rettv->v_type = VAR_STRING;
5318 rettv->vval.v_string = NULL;
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00005319#ifdef FEAT_FOLDING
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005320 lnum = get_tv_lnum(argvars);
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00005321 fold_count = foldedCount(curwin, lnum, &foldinfo);
5322 if (fold_count > 0)
5323 {
5324 text = get_foldtext(curwin, lnum, lnum + fold_count - 1,
5325 &foldinfo, buf);
5326 if (text == buf)
5327 text = vim_strsave(text);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005328 rettv->vval.v_string = text;
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00005329 }
5330#endif
5331}
5332
5333/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00005334 * "foreground()" function
5335 */
5336/*ARGSUSED*/
5337 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005338f_foreground(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005339 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005340 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005341{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005342 rettv->vval.v_number = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005343#ifdef FEAT_GUI
5344 if (gui.in_use)
5345 gui_mch_set_foreground();
5346#else
5347# ifdef WIN32
5348 win32_set_foreground();
5349# endif
5350#endif
5351}
5352
5353/*
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005354 * "function()" function
5355 */
5356/*ARGSUSED*/
5357 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005358f_function(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005359 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005360 typeval *rettv;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005361{
5362 char_u *s;
5363
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005364 s = get_tv_string(&argvars[0]);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005365 if (s == NULL || *s == NUL || isdigit(*s))
5366 EMSG2(_(e_invarg2), s);
5367 else if (!function_exists(s))
5368 EMSG2(_("E999: Unknown function: %s"), s);
5369 else
5370 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005371 rettv->vval.v_string = vim_strsave(s);
5372 rettv->v_type = VAR_FUNC;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005373 }
5374}
5375
5376/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00005377 * "getchar()" function
5378 */
5379 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005380f_getchar(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005381 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005382 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005383{
5384 varnumber_T n;
5385
5386 ++no_mapping;
5387 ++allow_keys;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005388 if (argvars[0].v_type == VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005389 /* getchar(): blocking wait. */
5390 n = safe_vgetc();
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005391 else if (get_tv_number(&argvars[0]) == 1)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005392 /* getchar(1): only check if char avail */
5393 n = vpeekc();
5394 else if (vpeekc() == NUL)
5395 /* getchar(0) and no char avail: return zero */
5396 n = 0;
5397 else
5398 /* getchar(0) and char avail: return char */
5399 n = safe_vgetc();
5400 --no_mapping;
5401 --allow_keys;
5402
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005403 rettv->vval.v_number = n;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005404 if (IS_SPECIAL(n) || mod_mask != 0)
5405 {
5406 char_u temp[10]; /* modifier: 3, mbyte-char: 6, NUL: 1 */
5407 int i = 0;
5408
5409 /* Turn a special key into three bytes, plus modifier. */
5410 if (mod_mask != 0)
5411 {
5412 temp[i++] = K_SPECIAL;
5413 temp[i++] = KS_MODIFIER;
5414 temp[i++] = mod_mask;
5415 }
5416 if (IS_SPECIAL(n))
5417 {
5418 temp[i++] = K_SPECIAL;
5419 temp[i++] = K_SECOND(n);
5420 temp[i++] = K_THIRD(n);
5421 }
5422#ifdef FEAT_MBYTE
5423 else if (has_mbyte)
5424 i += (*mb_char2bytes)(n, temp + i);
5425#endif
5426 else
5427 temp[i++] = n;
5428 temp[i++] = NUL;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005429 rettv->v_type = VAR_STRING;
5430 rettv->vval.v_string = vim_strsave(temp);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005431 }
5432}
5433
5434/*
5435 * "getcharmod()" function
5436 */
5437/*ARGSUSED*/
5438 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005439f_getcharmod(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005440 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005441 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005442{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005443 rettv->vval.v_number = mod_mask;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005444}
5445
5446/*
5447 * "getcmdline()" function
5448 */
5449/*ARGSUSED*/
5450 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005451f_getcmdline(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005452 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005453 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005454{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005455 rettv->v_type = VAR_STRING;
5456 rettv->vval.v_string = get_cmdline_str();
Bram Moolenaar071d4272004-06-13 20:20:40 +00005457}
5458
5459/*
5460 * "getcmdpos()" function
5461 */
5462/*ARGSUSED*/
5463 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005464f_getcmdpos(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005465 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005466 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005467{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005468 rettv->vval.v_number = get_cmdline_pos() + 1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005469}
5470
5471/*
5472 * "getbufvar()" function
5473 */
5474 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005475f_getbufvar(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005476 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005477 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005478{
5479 buf_T *buf;
5480 buf_T *save_curbuf;
5481 char_u *varname;
5482 VAR v;
5483
5484 ++emsg_off;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005485 buf = get_buf_tv(&argvars[0]);
5486 varname = get_tv_string(&argvars[1]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005487
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005488 rettv->v_type = VAR_STRING;
5489 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005490
5491 if (buf != NULL && varname != NULL)
5492 {
5493 if (*varname == '&') /* buffer-local-option */
5494 {
5495 /* set curbuf to be our buf, temporarily */
5496 save_curbuf = curbuf;
5497 curbuf = buf;
5498
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005499 get_option_tv(&varname, rettv, TRUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005500
5501 /* restore previous notion of curbuf */
5502 curbuf = save_curbuf;
5503 }
5504 else
5505 {
5506 /* look up the variable */
5507 v = find_var_in_ga(&buf->b_vars, varname);
5508 if (v != NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005509 copy_tv(&v->tv, rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005510 }
5511 }
5512
5513 --emsg_off;
5514}
5515
5516/*
5517 * "getcwd()" function
5518 */
5519/*ARGSUSED*/
5520 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005521f_getcwd(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005522 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005523 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005524{
5525 char_u cwd[MAXPATHL];
5526
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005527 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005528 if (mch_dirname(cwd, MAXPATHL) == FAIL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005529 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005530 else
5531 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005532 rettv->vval.v_string = vim_strsave(cwd);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005533#ifdef BACKSLASH_IN_FILENAME
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005534 slash_adjust(rettv->vval.v_string);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005535#endif
5536 }
5537}
5538
5539/*
Bram Moolenaar46c9c732004-12-12 11:37:09 +00005540 * "getfontname()" function
5541 */
Bram Moolenaar1cd871b2004-12-19 22:46:22 +00005542/*ARGSUSED*/
Bram Moolenaar46c9c732004-12-12 11:37:09 +00005543 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005544f_getfontname(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005545 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005546 typeval *rettv;
Bram Moolenaar46c9c732004-12-12 11:37:09 +00005547{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005548 rettv->v_type = VAR_STRING;
5549 rettv->vval.v_string = NULL;
Bram Moolenaar46c9c732004-12-12 11:37:09 +00005550#ifdef FEAT_GUI
5551 if (gui.in_use)
5552 {
5553 GuiFont font;
5554 char_u *name = NULL;
5555
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005556 if (argvars[0].v_type == VAR_UNKNOWN)
Bram Moolenaar46c9c732004-12-12 11:37:09 +00005557 {
5558 /* Get the "Normal" font. Either the name saved by
5559 * hl_set_font_name() or from the font ID. */
5560 font = gui.norm_font;
5561 name = hl_get_font_name();
5562 }
5563 else
5564 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005565 name = get_tv_string(&argvars[0]);
Bram Moolenaar46c9c732004-12-12 11:37:09 +00005566 if (STRCMP(name, "*") == 0) /* don't use font dialog */
5567 return;
5568 font = gui_mch_get_font(name, FALSE);
5569 if (font == NOFONT)
5570 return; /* Invalid font name, return empty string. */
5571 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005572 rettv->vval.v_string = gui_mch_get_fontname(font, name);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005573 if (argvars[0].v_type != VAR_UNKNOWN)
Bram Moolenaar46c9c732004-12-12 11:37:09 +00005574 gui_mch_free_font(font);
5575 }
5576#endif
5577}
5578
5579/*
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00005580 * "getfperm({fname})" function
5581 */
5582 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005583f_getfperm(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005584 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005585 typeval *rettv;
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00005586{
5587 char_u *fname;
5588 struct stat st;
5589 char_u *perm = NULL;
5590 char_u flags[] = "rwx";
5591 int i;
5592
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005593 fname = get_tv_string(&argvars[0]);
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00005594
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005595 rettv->v_type = VAR_STRING;
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00005596 if (mch_stat((char *)fname, &st) >= 0)
5597 {
5598 perm = vim_strsave((char_u *)"---------");
5599 if (perm != NULL)
5600 {
5601 for (i = 0; i < 9; i++)
5602 {
5603 if (st.st_mode & (1 << (8 - i)))
5604 perm[i] = flags[i % 3];
5605 }
5606 }
5607 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005608 rettv->vval.v_string = perm;
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00005609}
5610
5611/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00005612 * "getfsize({fname})" function
5613 */
5614 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005615f_getfsize(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005616 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005617 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005618{
5619 char_u *fname;
5620 struct stat st;
5621
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005622 fname = get_tv_string(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005623
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005624 rettv->v_type = VAR_NUMBER;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005625
5626 if (mch_stat((char *)fname, &st) >= 0)
5627 {
5628 if (mch_isdir(fname))
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005629 rettv->vval.v_number = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005630 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005631 rettv->vval.v_number = (varnumber_T)st.st_size;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005632 }
5633 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005634 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005635}
5636
5637/*
5638 * "getftime({fname})" function
5639 */
5640 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005641f_getftime(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005642 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005643 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005644{
5645 char_u *fname;
5646 struct stat st;
5647
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005648 fname = get_tv_string(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005649
5650 if (mch_stat((char *)fname, &st) >= 0)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005651 rettv->vval.v_number = (varnumber_T)st.st_mtime;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005652 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005653 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005654}
5655
5656/*
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00005657 * "getftype({fname})" function
5658 */
5659 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005660f_getftype(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005661 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005662 typeval *rettv;
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00005663{
5664 char_u *fname;
5665 struct stat st;
5666 char_u *type = NULL;
5667 char *t;
5668
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005669 fname = get_tv_string(&argvars[0]);
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00005670
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005671 rettv->v_type = VAR_STRING;
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00005672 if (mch_lstat((char *)fname, &st) >= 0)
5673 {
5674#ifdef S_ISREG
5675 if (S_ISREG(st.st_mode))
5676 t = "file";
5677 else if (S_ISDIR(st.st_mode))
5678 t = "dir";
5679# ifdef S_ISLNK
5680 else if (S_ISLNK(st.st_mode))
5681 t = "link";
5682# endif
5683# ifdef S_ISBLK
5684 else if (S_ISBLK(st.st_mode))
5685 t = "bdev";
5686# endif
5687# ifdef S_ISCHR
5688 else if (S_ISCHR(st.st_mode))
5689 t = "cdev";
5690# endif
5691# ifdef S_ISFIFO
5692 else if (S_ISFIFO(st.st_mode))
5693 t = "fifo";
5694# endif
5695# ifdef S_ISSOCK
5696 else if (S_ISSOCK(st.st_mode))
5697 t = "fifo";
5698# endif
5699 else
5700 t = "other";
5701#else
5702# ifdef S_IFMT
5703 switch (st.st_mode & S_IFMT)
5704 {
5705 case S_IFREG: t = "file"; break;
5706 case S_IFDIR: t = "dir"; break;
5707# ifdef S_IFLNK
5708 case S_IFLNK: t = "link"; break;
5709# endif
5710# ifdef S_IFBLK
5711 case S_IFBLK: t = "bdev"; break;
5712# endif
5713# ifdef S_IFCHR
5714 case S_IFCHR: t = "cdev"; break;
5715# endif
5716# ifdef S_IFIFO
5717 case S_IFIFO: t = "fifo"; break;
5718# endif
5719# ifdef S_IFSOCK
5720 case S_IFSOCK: t = "socket"; break;
5721# endif
5722 default: t = "other";
5723 }
5724# else
5725 if (mch_isdir(fname))
5726 t = "dir";
5727 else
5728 t = "file";
5729# endif
5730#endif
5731 type = vim_strsave((char_u *)t);
5732 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005733 rettv->vval.v_string = type;
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00005734}
5735
5736/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00005737 * "getreg()" function
5738 */
5739 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005740f_getreg(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005741 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005742 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005743{
5744 char_u *strregname;
5745 int regname;
5746
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005747 if (argvars[0].v_type != VAR_UNKNOWN)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005748 strregname = get_tv_string(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005749 else
5750 strregname = vimvars[VV_REG].val;
5751 regname = (strregname == NULL ? '"' : *strregname);
5752 if (regname == 0)
5753 regname = '"';
5754
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005755 rettv->v_type = VAR_STRING;
5756 rettv->vval.v_string = get_reg_contents(regname, TRUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005757}
5758
5759/*
5760 * "getregtype()" function
5761 */
5762 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005763f_getregtype(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005764 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005765 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005766{
5767 char_u *strregname;
5768 int regname;
5769 char_u buf[NUMBUFLEN + 2];
5770 long reglen = 0;
5771
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005772 if (argvars[0].v_type != VAR_UNKNOWN)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005773 strregname = get_tv_string(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005774 else
5775 /* Default to v:register */
5776 strregname = vimvars[VV_REG].val;
5777
5778 regname = (strregname == NULL ? '"' : *strregname);
5779 if (regname == 0)
5780 regname = '"';
5781
5782 buf[0] = NUL;
5783 buf[1] = NUL;
5784 switch (get_reg_type(regname, &reglen))
5785 {
5786 case MLINE: buf[0] = 'V'; break;
5787 case MCHAR: buf[0] = 'v'; break;
5788#ifdef FEAT_VISUAL
5789 case MBLOCK:
5790 buf[0] = Ctrl_V;
5791 sprintf((char *)buf + 1, "%ld", reglen + 1);
5792 break;
5793#endif
5794 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005795 rettv->v_type = VAR_STRING;
5796 rettv->vval.v_string = vim_strsave(buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005797}
5798
5799/*
5800 * "getline(lnum)" function
5801 */
5802 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005803f_getline(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005804 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005805 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005806{
5807 linenr_T lnum;
5808 char_u *p;
5809
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005810 lnum = get_tv_lnum(argvars);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005811
5812 if (lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count)
5813 p = ml_get(lnum);
5814 else
5815 p = (char_u *)"";
5816
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005817 rettv->v_type = VAR_STRING;
5818 rettv->vval.v_string = vim_strsave(p);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005819}
5820
5821/*
5822 * "getwinposx()" function
5823 */
5824/*ARGSUSED*/
5825 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005826f_getwinposx(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005827 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005828 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005829{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005830 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005831#ifdef FEAT_GUI
5832 if (gui.in_use)
5833 {
5834 int x, y;
5835
5836 if (gui_mch_get_winpos(&x, &y) == OK)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005837 rettv->vval.v_number = x;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005838 }
5839#endif
5840}
5841
5842/*
5843 * "getwinposy()" function
5844 */
5845/*ARGSUSED*/
5846 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005847f_getwinposy(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005848 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005849 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005850{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005851 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005852#ifdef FEAT_GUI
5853 if (gui.in_use)
5854 {
5855 int x, y;
5856
5857 if (gui_mch_get_winpos(&x, &y) == OK)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005858 rettv->vval.v_number = y;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005859 }
5860#endif
5861}
5862
5863/*
5864 * "getwinvar()" function
5865 */
5866 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005867f_getwinvar(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005868 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005869 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005870{
5871 win_T *win, *oldcurwin;
5872 char_u *varname;
5873 VAR v;
5874
5875 ++emsg_off;
5876 win = find_win_by_nr(&argvars[0]);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005877 varname = get_tv_string(&argvars[1]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005878
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005879 rettv->v_type = VAR_STRING;
5880 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005881
5882 if (win != NULL && varname != NULL)
5883 {
5884 if (*varname == '&') /* window-local-option */
5885 {
5886 /* set curwin to be our win, temporarily */
5887 oldcurwin = curwin;
5888 curwin = win;
5889
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005890 get_option_tv(&varname, rettv, 1);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005891
5892 /* restore previous notion of curwin */
5893 curwin = oldcurwin;
5894 }
5895 else
5896 {
5897 /* look up the variable */
5898 v = find_var_in_ga(&win->w_vars, varname);
5899 if (v != NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005900 copy_tv(&v->tv, rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005901 }
5902 }
5903
5904 --emsg_off;
5905}
5906
5907/*
5908 * "glob()" function
5909 */
5910 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005911f_glob(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005912 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005913 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005914{
5915 expand_T xpc;
5916
5917 ExpandInit(&xpc);
5918 xpc.xp_context = EXPAND_FILES;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005919 rettv->v_type = VAR_STRING;
5920 rettv->vval.v_string = ExpandOne(&xpc, get_tv_string(&argvars[0]),
Bram Moolenaar071d4272004-06-13 20:20:40 +00005921 NULL, WILD_USE_NL|WILD_SILENT, WILD_ALL);
5922 ExpandCleanup(&xpc);
5923}
5924
5925/*
5926 * "globpath()" function
5927 */
5928 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005929f_globpath(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005930 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005931 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005932{
5933 char_u buf1[NUMBUFLEN];
5934
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005935 rettv->v_type = VAR_STRING;
5936 rettv->vval.v_string = globpath(get_tv_string(&argvars[0]),
5937 get_tv_string_buf(&argvars[1], buf1));
Bram Moolenaar071d4272004-06-13 20:20:40 +00005938}
5939
5940/*
5941 * "has()" function
5942 */
5943 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005944f_has(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005945 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005946 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005947{
5948 int i;
5949 char_u *name;
5950 int n = FALSE;
5951 static char *(has_list[]) =
5952 {
5953#ifdef AMIGA
5954 "amiga",
5955# ifdef FEAT_ARP
5956 "arp",
5957# endif
5958#endif
5959#ifdef __BEOS__
5960 "beos",
5961#endif
5962#ifdef MSDOS
5963# ifdef DJGPP
5964 "dos32",
5965# else
5966 "dos16",
5967# endif
5968#endif
5969#ifdef MACOS /* TODO: Should we add MACOS_CLASSIC, MACOS_X? (Dany) */
5970 "mac",
5971#endif
5972#if defined(MACOS_X_UNIX)
5973 "macunix",
5974#endif
5975#ifdef OS2
5976 "os2",
5977#endif
5978#ifdef __QNX__
5979 "qnx",
5980#endif
5981#ifdef RISCOS
5982 "riscos",
5983#endif
5984#ifdef UNIX
5985 "unix",
5986#endif
5987#ifdef VMS
5988 "vms",
5989#endif
5990#ifdef WIN16
5991 "win16",
5992#endif
5993#ifdef WIN32
5994 "win32",
5995#endif
5996#if defined(UNIX) && (defined(__CYGWIN32__) || defined(__CYGWIN__))
5997 "win32unix",
5998#endif
5999#ifdef WIN64
6000 "win64",
6001#endif
6002#ifdef EBCDIC
6003 "ebcdic",
6004#endif
6005#ifndef CASE_INSENSITIVE_FILENAME
6006 "fname_case",
6007#endif
6008#ifdef FEAT_ARABIC
6009 "arabic",
6010#endif
6011#ifdef FEAT_AUTOCMD
6012 "autocmd",
6013#endif
6014#ifdef FEAT_BEVAL
6015 "balloon_eval",
6016#endif
6017#if defined(SOME_BUILTIN_TCAPS) || defined(ALL_BUILTIN_TCAPS)
6018 "builtin_terms",
6019# ifdef ALL_BUILTIN_TCAPS
6020 "all_builtin_terms",
6021# endif
6022#endif
6023#ifdef FEAT_BYTEOFF
6024 "byte_offset",
6025#endif
6026#ifdef FEAT_CINDENT
6027 "cindent",
6028#endif
6029#ifdef FEAT_CLIENTSERVER
6030 "clientserver",
6031#endif
6032#ifdef FEAT_CLIPBOARD
6033 "clipboard",
6034#endif
6035#ifdef FEAT_CMDL_COMPL
6036 "cmdline_compl",
6037#endif
6038#ifdef FEAT_CMDHIST
6039 "cmdline_hist",
6040#endif
6041#ifdef FEAT_COMMENTS
6042 "comments",
6043#endif
6044#ifdef FEAT_CRYPT
6045 "cryptv",
6046#endif
6047#ifdef FEAT_CSCOPE
6048 "cscope",
6049#endif
6050#ifdef DEBUG
6051 "debug",
6052#endif
6053#ifdef FEAT_CON_DIALOG
6054 "dialog_con",
6055#endif
6056#ifdef FEAT_GUI_DIALOG
6057 "dialog_gui",
6058#endif
6059#ifdef FEAT_DIFF
6060 "diff",
6061#endif
6062#ifdef FEAT_DIGRAPHS
6063 "digraphs",
6064#endif
6065#ifdef FEAT_DND
6066 "dnd",
6067#endif
6068#ifdef FEAT_EMACS_TAGS
6069 "emacs_tags",
6070#endif
6071 "eval", /* always present, of course! */
6072#ifdef FEAT_EX_EXTRA
6073 "ex_extra",
6074#endif
6075#ifdef FEAT_SEARCH_EXTRA
6076 "extra_search",
6077#endif
6078#ifdef FEAT_FKMAP
6079 "farsi",
6080#endif
6081#ifdef FEAT_SEARCHPATH
6082 "file_in_path",
6083#endif
6084#ifdef FEAT_FIND_ID
6085 "find_in_path",
6086#endif
6087#ifdef FEAT_FOLDING
6088 "folding",
6089#endif
6090#ifdef FEAT_FOOTER
6091 "footer",
6092#endif
6093#if !defined(USE_SYSTEM) && defined(UNIX)
6094 "fork",
6095#endif
6096#ifdef FEAT_GETTEXT
6097 "gettext",
6098#endif
6099#ifdef FEAT_GUI
6100 "gui",
6101#endif
6102#ifdef FEAT_GUI_ATHENA
6103# ifdef FEAT_GUI_NEXTAW
6104 "gui_neXtaw",
6105# else
6106 "gui_athena",
6107# endif
6108#endif
Bram Moolenaar843ee412004-06-30 16:16:41 +00006109#ifdef FEAT_GUI_KDE
6110 "gui_kde",
6111#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00006112#ifdef FEAT_GUI_GTK
6113 "gui_gtk",
6114# ifdef HAVE_GTK2
6115 "gui_gtk2",
6116# endif
6117#endif
6118#ifdef FEAT_GUI_MAC
6119 "gui_mac",
6120#endif
6121#ifdef FEAT_GUI_MOTIF
6122 "gui_motif",
6123#endif
6124#ifdef FEAT_GUI_PHOTON
6125 "gui_photon",
6126#endif
6127#ifdef FEAT_GUI_W16
6128 "gui_win16",
6129#endif
6130#ifdef FEAT_GUI_W32
6131 "gui_win32",
6132#endif
6133#ifdef FEAT_HANGULIN
6134 "hangul_input",
6135#endif
6136#if defined(HAVE_ICONV_H) && defined(USE_ICONV)
6137 "iconv",
6138#endif
6139#ifdef FEAT_INS_EXPAND
6140 "insert_expand",
6141#endif
6142#ifdef FEAT_JUMPLIST
6143 "jumplist",
6144#endif
6145#ifdef FEAT_KEYMAP
6146 "keymap",
6147#endif
6148#ifdef FEAT_LANGMAP
6149 "langmap",
6150#endif
6151#ifdef FEAT_LIBCALL
6152 "libcall",
6153#endif
6154#ifdef FEAT_LINEBREAK
6155 "linebreak",
6156#endif
6157#ifdef FEAT_LISP
6158 "lispindent",
6159#endif
6160#ifdef FEAT_LISTCMDS
6161 "listcmds",
6162#endif
6163#ifdef FEAT_LOCALMAP
6164 "localmap",
6165#endif
6166#ifdef FEAT_MENU
6167 "menu",
6168#endif
6169#ifdef FEAT_SESSION
6170 "mksession",
6171#endif
6172#ifdef FEAT_MODIFY_FNAME
6173 "modify_fname",
6174#endif
6175#ifdef FEAT_MOUSE
6176 "mouse",
6177#endif
6178#ifdef FEAT_MOUSESHAPE
6179 "mouseshape",
6180#endif
6181#if defined(UNIX) || defined(VMS)
6182# ifdef FEAT_MOUSE_DEC
6183 "mouse_dec",
6184# endif
6185# ifdef FEAT_MOUSE_GPM
6186 "mouse_gpm",
6187# endif
6188# ifdef FEAT_MOUSE_JSB
6189 "mouse_jsbterm",
6190# endif
6191# ifdef FEAT_MOUSE_NET
6192 "mouse_netterm",
6193# endif
6194# ifdef FEAT_MOUSE_PTERM
6195 "mouse_pterm",
6196# endif
6197# ifdef FEAT_MOUSE_XTERM
6198 "mouse_xterm",
6199# endif
6200#endif
6201#ifdef FEAT_MBYTE
6202 "multi_byte",
6203#endif
6204#ifdef FEAT_MBYTE_IME
6205 "multi_byte_ime",
6206#endif
6207#ifdef FEAT_MULTI_LANG
6208 "multi_lang",
6209#endif
Bram Moolenaar325b7a22004-07-05 15:58:32 +00006210#ifdef FEAT_MZSCHEME
6211 "mzscheme",
6212#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00006213#ifdef FEAT_OLE
6214 "ole",
6215#endif
6216#ifdef FEAT_OSFILETYPE
6217 "osfiletype",
6218#endif
6219#ifdef FEAT_PATH_EXTRA
6220 "path_extra",
6221#endif
6222#ifdef FEAT_PERL
6223#ifndef DYNAMIC_PERL
6224 "perl",
6225#endif
6226#endif
6227#ifdef FEAT_PYTHON
6228#ifndef DYNAMIC_PYTHON
6229 "python",
6230#endif
6231#endif
6232#ifdef FEAT_POSTSCRIPT
6233 "postscript",
6234#endif
6235#ifdef FEAT_PRINTER
6236 "printer",
6237#endif
6238#ifdef FEAT_QUICKFIX
6239 "quickfix",
6240#endif
6241#ifdef FEAT_RIGHTLEFT
6242 "rightleft",
6243#endif
6244#if defined(FEAT_RUBY) && !defined(DYNAMIC_RUBY)
6245 "ruby",
6246#endif
6247#ifdef FEAT_SCROLLBIND
6248 "scrollbind",
6249#endif
6250#ifdef FEAT_CMDL_INFO
6251 "showcmd",
6252 "cmdline_info",
6253#endif
6254#ifdef FEAT_SIGNS
6255 "signs",
6256#endif
6257#ifdef FEAT_SMARTINDENT
6258 "smartindent",
6259#endif
6260#ifdef FEAT_SNIFF
6261 "sniff",
6262#endif
6263#ifdef FEAT_STL_OPT
6264 "statusline",
6265#endif
6266#ifdef FEAT_SUN_WORKSHOP
6267 "sun_workshop",
6268#endif
6269#ifdef FEAT_NETBEANS_INTG
6270 "netbeans_intg",
6271#endif
6272#ifdef FEAT_SYN_HL
6273 "syntax",
6274#endif
6275#if defined(USE_SYSTEM) || !defined(UNIX)
6276 "system",
6277#endif
6278#ifdef FEAT_TAG_BINS
6279 "tag_binary",
6280#endif
6281#ifdef FEAT_TAG_OLDSTATIC
6282 "tag_old_static",
6283#endif
6284#ifdef FEAT_TAG_ANYWHITE
6285 "tag_any_white",
6286#endif
6287#ifdef FEAT_TCL
6288# ifndef DYNAMIC_TCL
6289 "tcl",
6290# endif
6291#endif
6292#ifdef TERMINFO
6293 "terminfo",
6294#endif
6295#ifdef FEAT_TERMRESPONSE
6296 "termresponse",
6297#endif
6298#ifdef FEAT_TEXTOBJ
6299 "textobjects",
6300#endif
6301#ifdef HAVE_TGETENT
6302 "tgetent",
6303#endif
6304#ifdef FEAT_TITLE
6305 "title",
6306#endif
6307#ifdef FEAT_TOOLBAR
6308 "toolbar",
6309#endif
6310#ifdef FEAT_USR_CMDS
6311 "user-commands", /* was accidentally included in 5.4 */
6312 "user_commands",
6313#endif
6314#ifdef FEAT_VIMINFO
6315 "viminfo",
6316#endif
6317#ifdef FEAT_VERTSPLIT
6318 "vertsplit",
6319#endif
6320#ifdef FEAT_VIRTUALEDIT
6321 "virtualedit",
6322#endif
6323#ifdef FEAT_VISUAL
6324 "visual",
6325#endif
6326#ifdef FEAT_VISUALEXTRA
6327 "visualextra",
6328#endif
6329#ifdef FEAT_VREPLACE
6330 "vreplace",
6331#endif
6332#ifdef FEAT_WILDIGN
6333 "wildignore",
6334#endif
6335#ifdef FEAT_WILDMENU
6336 "wildmenu",
6337#endif
6338#ifdef FEAT_WINDOWS
6339 "windows",
6340#endif
6341#ifdef FEAT_WAK
6342 "winaltkeys",
6343#endif
6344#ifdef FEAT_WRITEBACKUP
6345 "writebackup",
6346#endif
6347#ifdef FEAT_XIM
6348 "xim",
6349#endif
6350#ifdef FEAT_XFONTSET
6351 "xfontset",
6352#endif
6353#ifdef USE_XSMP
6354 "xsmp",
6355#endif
6356#ifdef USE_XSMP_INTERACT
6357 "xsmp_interact",
6358#endif
6359#ifdef FEAT_XCLIPBOARD
6360 "xterm_clipboard",
6361#endif
6362#ifdef FEAT_XTERM_SAVE
6363 "xterm_save",
6364#endif
6365#if defined(UNIX) && defined(FEAT_X11)
6366 "X11",
6367#endif
6368 NULL
6369 };
6370
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006371 name = get_tv_string(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006372 for (i = 0; has_list[i] != NULL; ++i)
6373 if (STRICMP(name, has_list[i]) == 0)
6374 {
6375 n = TRUE;
6376 break;
6377 }
6378
6379 if (n == FALSE)
6380 {
6381 if (STRNICMP(name, "patch", 5) == 0)
6382 n = has_patch(atoi((char *)name + 5));
6383 else if (STRICMP(name, "vim_starting") == 0)
6384 n = (starting != 0);
6385#ifdef DYNAMIC_TCL
6386 else if (STRICMP(name, "tcl") == 0)
6387 n = tcl_enabled(FALSE);
6388#endif
6389#if defined(USE_ICONV) && defined(DYNAMIC_ICONV)
6390 else if (STRICMP(name, "iconv") == 0)
6391 n = iconv_enabled(FALSE);
6392#endif
6393#ifdef DYNAMIC_RUBY
6394 else if (STRICMP(name, "ruby") == 0)
6395 n = ruby_enabled(FALSE);
6396#endif
6397#ifdef DYNAMIC_PYTHON
6398 else if (STRICMP(name, "python") == 0)
6399 n = python_enabled(FALSE);
6400#endif
6401#ifdef DYNAMIC_PERL
6402 else if (STRICMP(name, "perl") == 0)
6403 n = perl_enabled(FALSE);
6404#endif
6405#ifdef FEAT_GUI
6406 else if (STRICMP(name, "gui_running") == 0)
6407 n = (gui.in_use || gui.starting);
6408# ifdef FEAT_GUI_W32
6409 else if (STRICMP(name, "gui_win32s") == 0)
6410 n = gui_is_win32s();
6411# endif
6412# ifdef FEAT_BROWSE
6413 else if (STRICMP(name, "browse") == 0)
6414 n = gui.in_use; /* gui_mch_browse() works when GUI is running */
6415# endif
6416#endif
6417#ifdef FEAT_SYN_HL
6418 else if (STRICMP(name, "syntax_items") == 0)
6419 n = syntax_present(curbuf);
6420#endif
6421#if defined(WIN3264)
6422 else if (STRICMP(name, "win95") == 0)
6423 n = mch_windows95();
6424#endif
Bram Moolenaar35a9aaa2004-10-24 19:23:07 +00006425#ifdef FEAT_NETBEANS_INTG
6426 else if (STRICMP(name, "netbeans_enabled") == 0)
6427 n = usingNetbeans;
6428#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00006429 }
6430
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006431 rettv->vval.v_number = n;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006432}
6433
6434/*
6435 * "hasmapto()" function
6436 */
6437 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006438f_hasmapto(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006439 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006440 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006441{
6442 char_u *name;
6443 char_u *mode;
6444 char_u buf[NUMBUFLEN];
6445
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006446 name = get_tv_string(&argvars[0]);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006447 if (argvars[1].v_type == VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006448 mode = (char_u *)"nvo";
6449 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006450 mode = get_tv_string_buf(&argvars[1], buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006451
6452 if (map_to_exists(name, mode))
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006453 rettv->vval.v_number = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006454 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006455 rettv->vval.v_number = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006456}
6457
6458/*
6459 * "histadd()" function
6460 */
6461/*ARGSUSED*/
6462 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006463f_histadd(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006464 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006465 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006466{
6467#ifdef FEAT_CMDHIST
6468 int histype;
6469 char_u *str;
6470 char_u buf[NUMBUFLEN];
6471#endif
6472
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006473 rettv->vval.v_number = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006474 if (check_restricted() || check_secure())
6475 return;
6476#ifdef FEAT_CMDHIST
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006477 histype = get_histtype(get_tv_string(&argvars[0]));
Bram Moolenaar071d4272004-06-13 20:20:40 +00006478 if (histype >= 0)
6479 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006480 str = get_tv_string_buf(&argvars[1], buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006481 if (*str != NUL)
6482 {
6483 add_to_history(histype, str, FALSE, NUL);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006484 rettv->vval.v_number = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006485 return;
6486 }
6487 }
6488#endif
6489}
6490
6491/*
6492 * "histdel()" function
6493 */
6494/*ARGSUSED*/
6495 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006496f_histdel(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006497 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006498 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006499{
6500#ifdef FEAT_CMDHIST
6501 int n;
6502 char_u buf[NUMBUFLEN];
6503
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006504 if (argvars[1].v_type == VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006505 /* only one argument: clear entire history */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006506 n = clr_history(get_histtype(get_tv_string(&argvars[0])));
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006507 else if (argvars[1].v_type == VAR_NUMBER)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006508 /* index given: remove that entry */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006509 n = del_history_idx(get_histtype(get_tv_string(&argvars[0])),
6510 (int)get_tv_number(&argvars[1]));
Bram Moolenaar071d4272004-06-13 20:20:40 +00006511 else
6512 /* string given: remove all matching entries */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006513 n = del_history_entry(get_histtype(get_tv_string(&argvars[0])),
6514 get_tv_string_buf(&argvars[1], buf));
6515 rettv->vval.v_number = n;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006516#else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006517 rettv->vval.v_number = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006518#endif
6519}
6520
6521/*
6522 * "histget()" function
6523 */
6524/*ARGSUSED*/
6525 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006526f_histget(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006527 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006528 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006529{
6530#ifdef FEAT_CMDHIST
6531 int type;
6532 int idx;
6533
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006534 type = get_histtype(get_tv_string(&argvars[0]));
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006535 if (argvars[1].v_type == VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006536 idx = get_history_idx(type);
6537 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006538 idx = (int)get_tv_number(&argvars[1]);
6539 rettv->vval.v_string = vim_strsave(get_history_entry(type, idx));
Bram Moolenaar071d4272004-06-13 20:20:40 +00006540#else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006541 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006542#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006543 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006544}
6545
6546/*
6547 * "histnr()" function
6548 */
6549/*ARGSUSED*/
6550 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006551f_histnr(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006552 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006553 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006554{
6555 int i;
6556
6557#ifdef FEAT_CMDHIST
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006558 i = get_histtype(get_tv_string(&argvars[0]));
Bram Moolenaar071d4272004-06-13 20:20:40 +00006559 if (i >= HIST_CMD && i < HIST_COUNT)
6560 i = get_history_idx(i);
6561 else
6562#endif
6563 i = -1;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006564 rettv->vval.v_number = i;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006565}
6566
6567/*
6568 * "highlight_exists()" function
6569 */
6570 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006571f_hlexists(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006572 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006573 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006574{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006575 rettv->vval.v_number = highlight_exists(get_tv_string(&argvars[0]));
Bram Moolenaar071d4272004-06-13 20:20:40 +00006576}
6577
6578/*
6579 * "highlightID(name)" function
6580 */
6581 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006582f_hlID(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006583 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006584 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006585{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006586 rettv->vval.v_number = syn_name2id(get_tv_string(&argvars[0]));
Bram Moolenaar071d4272004-06-13 20:20:40 +00006587}
6588
6589/*
6590 * "hostname()" function
6591 */
6592/*ARGSUSED*/
6593 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006594f_hostname(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006595 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006596 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006597{
6598 char_u hostname[256];
6599
6600 mch_get_host_name(hostname, 256);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006601 rettv->v_type = VAR_STRING;
6602 rettv->vval.v_string = vim_strsave(hostname);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006603}
6604
6605/*
6606 * iconv() function
6607 */
6608/*ARGSUSED*/
6609 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006610f_iconv(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006611 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006612 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006613{
6614#ifdef FEAT_MBYTE
6615 char_u buf1[NUMBUFLEN];
6616 char_u buf2[NUMBUFLEN];
6617 char_u *from, *to, *str;
6618 vimconv_T vimconv;
6619#endif
6620
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006621 rettv->v_type = VAR_STRING;
6622 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006623
6624#ifdef FEAT_MBYTE
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006625 str = get_tv_string(&argvars[0]);
6626 from = enc_canonize(enc_skip(get_tv_string_buf(&argvars[1], buf1)));
6627 to = enc_canonize(enc_skip(get_tv_string_buf(&argvars[2], buf2)));
Bram Moolenaar071d4272004-06-13 20:20:40 +00006628 vimconv.vc_type = CONV_NONE;
6629 convert_setup(&vimconv, from, to);
6630
6631 /* If the encodings are equal, no conversion needed. */
6632 if (vimconv.vc_type == CONV_NONE)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006633 rettv->vval.v_string = vim_strsave(str);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006634 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006635 rettv->vval.v_string = string_convert(&vimconv, str, NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006636
6637 convert_setup(&vimconv, NULL, NULL);
6638 vim_free(from);
6639 vim_free(to);
6640#endif
6641}
6642
6643/*
6644 * "indent()" function
6645 */
6646 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006647f_indent(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006648 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006649 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006650{
6651 linenr_T lnum;
6652
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006653 lnum = get_tv_lnum(argvars);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006654 if (lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006655 rettv->vval.v_number = get_indent_lnum(lnum);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006656 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006657 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006658}
6659
6660static int inputsecret_flag = 0;
6661
6662/*
6663 * "input()" function
6664 * Also handles inputsecret() when inputsecret is set.
6665 */
6666 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006667f_input(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006668 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006669 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006670{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006671 char_u *prompt = get_tv_string(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006672 char_u *p = NULL;
6673 int c;
6674 char_u buf[NUMBUFLEN];
6675 int cmd_silent_save = cmd_silent;
6676
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006677 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006678
6679#ifdef NO_CONSOLE_INPUT
6680 /* While starting up, there is no place to enter text. */
6681 if (no_console_input())
6682 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006683 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006684 return;
6685 }
6686#endif
6687
6688 cmd_silent = FALSE; /* Want to see the prompt. */
6689 if (prompt != NULL)
6690 {
6691 /* Only the part of the message after the last NL is considered as
6692 * prompt for the command line */
6693 p = vim_strrchr(prompt, '\n');
6694 if (p == NULL)
6695 p = prompt;
6696 else
6697 {
6698 ++p;
6699 c = *p;
6700 *p = NUL;
6701 msg_start();
6702 msg_clr_eos();
6703 msg_puts_attr(prompt, echo_attr);
6704 msg_didout = FALSE;
6705 msg_starthere();
6706 *p = c;
6707 }
6708 cmdline_row = msg_row;
6709 }
6710
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006711 if (argvars[1].v_type != VAR_UNKNOWN)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006712 stuffReadbuffSpec(get_tv_string_buf(&argvars[1], buf));
Bram Moolenaar071d4272004-06-13 20:20:40 +00006713
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006714 rettv->vval.v_string =
Bram Moolenaar071d4272004-06-13 20:20:40 +00006715 getcmdline_prompt(inputsecret_flag ? NUL : '@', p, echo_attr);
6716
6717 /* since the user typed this, no need to wait for return */
6718 need_wait_return = FALSE;
6719 msg_didout = FALSE;
6720 cmd_silent = cmd_silent_save;
6721}
6722
6723/*
6724 * "inputdialog()" function
6725 */
6726 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006727f_inputdialog(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006728 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006729 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006730{
6731#if defined(FEAT_GUI_TEXTDIALOG)
6732 /* Use a GUI dialog if the GUI is running and 'c' is not in 'guioptions' */
6733 if (gui.in_use && vim_strchr(p_go, GO_CONDIALOG) == NULL)
6734 {
6735 char_u *message;
6736 char_u buf[NUMBUFLEN];
6737
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006738 message = get_tv_string(&argvars[0]);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006739 if (argvars[1].v_type != VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006740 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006741 STRNCPY(IObuff, get_tv_string_buf(&argvars[1], buf), IOSIZE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006742 IObuff[IOSIZE - 1] = NUL;
6743 }
6744 else
6745 IObuff[0] = NUL;
6746 if (do_dialog(VIM_QUESTION, NULL, message, (char_u *)_("&OK\n&Cancel"),
6747 1, IObuff) == 1)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006748 rettv->vval.v_string = vim_strsave(IObuff);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006749 else
6750 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006751 if (argvars[1].v_type != VAR_UNKNOWN
6752 && argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006753 rettv->vval.v_string = vim_strsave(
6754 get_tv_string_buf(&argvars[2], buf));
Bram Moolenaar071d4272004-06-13 20:20:40 +00006755 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006756 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006757 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006758 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006759 }
6760 else
6761#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006762 f_input(argvars, rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006763}
6764
6765static garray_T ga_userinput = {0, 0, sizeof(tasave_T), 4, NULL};
6766
6767/*
6768 * "inputrestore()" function
6769 */
6770/*ARGSUSED*/
6771 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006772f_inputrestore(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006773 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006774 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006775{
6776 if (ga_userinput.ga_len > 0)
6777 {
6778 --ga_userinput.ga_len;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006779 restore_typeahead((tasave_T *)(ga_userinput.ga_data)
6780 + ga_userinput.ga_len);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006781 rettv->vval.v_number = 0; /* OK */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006782 }
6783 else if (p_verbose > 1)
6784 {
6785 msg((char_u *)_("called inputrestore() more often than inputsave()"));
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006786 rettv->vval.v_number = 1; /* Failed */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006787 }
6788}
6789
6790/*
6791 * "inputsave()" function
6792 */
6793/*ARGSUSED*/
6794 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006795f_inputsave(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006796 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006797 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006798{
6799 /* Add an entry to the stack of typehead storage. */
6800 if (ga_grow(&ga_userinput, 1) == OK)
6801 {
6802 save_typeahead((tasave_T *)(ga_userinput.ga_data)
6803 + ga_userinput.ga_len);
6804 ++ga_userinput.ga_len;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006805 rettv->vval.v_number = 0; /* OK */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006806 }
6807 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006808 rettv->vval.v_number = 1; /* Failed */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006809}
6810
6811/*
6812 * "inputsecret()" function
6813 */
6814 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006815f_inputsecret(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006816 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006817 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006818{
6819 ++cmdline_star;
6820 ++inputsecret_flag;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006821 f_input(argvars, rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006822 --cmdline_star;
6823 --inputsecret_flag;
6824}
6825
6826/*
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006827 * "insert()" function
6828 */
6829 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006830f_insert(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006831 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006832 typeval *rettv;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006833{
6834 long before = 0;
6835 long n;
6836 listitem *item;
6837 listitem *ni;
6838 listvar *l;
6839
6840 if (argvars[0].v_type != VAR_LIST)
6841 EMSG(_("E999: First argument of insert() must be a list"));
6842 else if ((l = argvars[0].vval.v_list) != NULL)
6843 {
6844 if (argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006845 before = get_tv_number(&argvars[2]);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006846
6847 if (before < 0)
6848 {
6849 /* Count from the end: -1 is before last item. */
6850 item = l->lv_last;
6851 for (n = before + 1; n < 0 && item != NULL; ++n)
6852 item = item->li_prev;
6853 if (item == NULL)
6854 n = 1; /* report an error, don't append */
6855 }
6856 else
6857 {
6858 /* Can't use list_find() here, we allow one past the end. */
6859 item = l->lv_first;
6860 for (n = before; n > 0 && item != NULL; --n)
6861 item = item->li_next;
6862 }
6863 if (n > 0)
6864 EMSGN(_(e_listidx), before);
6865 else
6866 {
6867 ni = listitem_alloc();
6868 if (ni != NULL)
6869 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006870 copy_tv(&argvars[1], &ni->li_tv);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006871 if (item == NULL)
6872 /* Append new item at end of list. */
6873 list_append(l, ni);
6874 else
6875 {
6876 /* Insert new item before existing item. */
6877 ni->li_prev = item->li_prev;
6878 ni->li_next = item;
6879 if (item->li_prev == NULL)
6880 l->lv_first = ni;
6881 else
6882 item->li_prev->li_next = ni;
6883 item->li_prev = ni;
6884 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006885 copy_tv(&argvars[0], rettv);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006886 }
6887 }
6888 }
6889}
6890
6891/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00006892 * "isdirectory()" function
6893 */
6894 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006895f_isdirectory(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006896 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006897 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006898{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006899 rettv->vval.v_number = mch_isdir(get_tv_string(&argvars[0]));
Bram Moolenaar071d4272004-06-13 20:20:40 +00006900}
6901
6902/*
6903 * "last_buffer_nr()" function.
6904 */
6905/*ARGSUSED*/
6906 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006907f_last_buffer_nr(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006908 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006909 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006910{
6911 int n = 0;
6912 buf_T *buf;
6913
6914 for (buf = firstbuf; buf != NULL; buf = buf->b_next)
6915 if (n < buf->b_fnum)
6916 n = buf->b_fnum;
6917
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006918 rettv->vval.v_number = n;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006919}
6920
6921/*
6922 * "len()" function
6923 */
6924 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006925f_len(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006926 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006927 typeval *rettv;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006928{
6929 switch (argvars[0].v_type)
6930 {
6931 case VAR_STRING:
6932 case VAR_NUMBER:
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006933 rettv->vval.v_number = (varnumber_T)STRLEN(
6934 get_tv_string(&argvars[0]));
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006935 break;
6936 case VAR_LIST:
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006937 rettv->vval.v_number = list_len(argvars[0].vval.v_list);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006938 break;
6939 default:
6940 EMSG(_("E999: Invalid type for len()"));
6941 break;
6942 }
6943}
6944
6945/*
6946 * "libcall()" function
6947 */
6948 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006949f_libcall(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006950 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006951 typeval *rettv;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006952{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006953 libcall_common(argvars, rettv, VAR_STRING);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006954}
6955
6956/*
6957 * "libcallnr()" function
6958 */
6959 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006960f_libcallnr(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006961 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006962 typeval *rettv;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006963{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006964 libcall_common(argvars, rettv, VAR_NUMBER);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006965}
6966
6967 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006968libcall_common(argvars, rettv, type)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006969 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006970 typeval *rettv;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006971 int type;
6972{
6973#ifdef FEAT_LIBCALL
6974 char_u *string_in;
6975 char_u **string_result;
6976 int nr_result;
6977#endif
6978
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006979 rettv->v_type = type;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006980 if (type == VAR_NUMBER)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006981 rettv->vval.v_number = 0;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006982 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006983 rettv->vval.v_string = NULL;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006984
6985 if (check_restricted() || check_secure())
6986 return;
6987
6988#ifdef FEAT_LIBCALL
6989 /* The first two args must be strings, otherwise its meaningless */
6990 if (argvars[0].v_type == VAR_STRING && argvars[1].v_type == VAR_STRING)
6991 {
6992 if (argvars[2].v_type == VAR_NUMBER)
6993 string_in = NULL;
6994 else
6995 string_in = argvars[2].vval.v_string;
6996 if (type == VAR_NUMBER)
6997 string_result = NULL;
6998 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006999 string_result = &rettv->vval.v_string;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007000 if (mch_libcall(argvars[0].vval.v_string,
7001 argvars[1].vval.v_string,
7002 string_in,
7003 argvars[2].vval.v_number,
7004 string_result,
7005 &nr_result) == OK
7006 && type == VAR_NUMBER)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007007 rettv->vval.v_number = nr_result;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007008 }
7009#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00007010}
7011
7012/*
7013 * "line(string)" function
7014 */
7015 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007016f_line(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007017 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007018 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007019{
7020 linenr_T lnum = 0;
7021 pos_T *fp;
7022
7023 fp = var2fpos(&argvars[0], TRUE);
7024 if (fp != NULL)
7025 lnum = fp->lnum;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007026 rettv->vval.v_number = lnum;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007027}
7028
7029/*
7030 * "line2byte(lnum)" function
7031 */
7032/*ARGSUSED*/
7033 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007034f_line2byte(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007035 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007036 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007037{
7038#ifndef FEAT_BYTEOFF
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007039 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007040#else
7041 linenr_T lnum;
7042
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007043 lnum = get_tv_lnum(argvars);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007044 if (lnum < 1 || lnum > curbuf->b_ml.ml_line_count + 1)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007045 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007046 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007047 rettv->vval.v_number = ml_find_line_or_offset(curbuf, lnum, NULL);
7048 if (rettv->vval.v_number >= 0)
7049 ++rettv->vval.v_number;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007050#endif
7051}
7052
7053/*
7054 * "lispindent(lnum)" function
7055 */
7056 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007057f_lispindent(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007058 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007059 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007060{
7061#ifdef FEAT_LISP
7062 pos_T pos;
7063 linenr_T lnum;
7064
7065 pos = curwin->w_cursor;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007066 lnum = get_tv_lnum(argvars);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007067 if (lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count)
7068 {
7069 curwin->w_cursor.lnum = lnum;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007070 rettv->vval.v_number = get_lisp_indent();
Bram Moolenaar071d4272004-06-13 20:20:40 +00007071 curwin->w_cursor = pos;
7072 }
7073 else
7074#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007075 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007076}
7077
7078/*
7079 * "localtime()" function
7080 */
7081/*ARGSUSED*/
7082 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007083f_localtime(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007084 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007085 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007086{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007087 rettv->vval.v_number = (varnumber_T)time(NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007088}
7089
7090/*
7091 * "maparg()" function
7092 */
7093 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007094f_maparg(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007095 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007096 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007097{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007098 get_maparg(argvars, rettv, TRUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007099}
7100
7101/*
7102 * "mapcheck()" function
7103 */
7104 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007105f_mapcheck(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007106 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007107 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007108{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007109 get_maparg(argvars, rettv, FALSE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007110}
7111
7112 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007113get_maparg(argvars, rettv, exact)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007114 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007115 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007116 int exact;
7117{
7118 char_u *keys;
7119 char_u *which;
7120 char_u buf[NUMBUFLEN];
7121 char_u *keys_buf = NULL;
7122 char_u *rhs;
7123 int mode;
7124 garray_T ga;
7125
7126 /* return empty string for failure */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007127 rettv->v_type = VAR_STRING;
7128 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007129
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007130 keys = get_tv_string(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007131 if (*keys == NUL)
7132 return;
7133
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007134 if (argvars[1].v_type != VAR_UNKNOWN)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007135 which = get_tv_string_buf(&argvars[1], buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007136 else
7137 which = (char_u *)"";
7138 mode = get_map_mode(&which, 0);
7139
7140 keys = replace_termcodes(keys, &keys_buf, TRUE, TRUE);
7141 rhs = check_map(keys, mode, exact);
7142 vim_free(keys_buf);
7143 if (rhs != NULL)
7144 {
7145 ga_init(&ga);
7146 ga.ga_itemsize = 1;
7147 ga.ga_growsize = 40;
7148
7149 while (*rhs != NUL)
7150 ga_concat(&ga, str2special(&rhs, FALSE));
7151
7152 ga_append(&ga, NUL);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007153 rettv->vval.v_string = (char_u *)ga.ga_data;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007154 }
7155}
7156
7157/*
7158 * "match()" function
7159 */
7160 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007161f_match(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007162 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007163 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007164{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007165 find_some_match(argvars, rettv, 1);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007166}
7167
7168/*
7169 * "matchend()" function
7170 */
7171 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007172f_matchend(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007173 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007174 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007175{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007176 find_some_match(argvars, rettv, 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007177}
7178
7179/*
7180 * "matchstr()" function
7181 */
7182 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007183f_matchstr(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{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007187 find_some_match(argvars, rettv, 2);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007188}
7189
7190 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007191find_some_match(argvars, rettv, type)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007192 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007193 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007194 int type;
7195{
7196 char_u *str;
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00007197 char_u *expr;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007198 char_u *pat;
7199 regmatch_T regmatch;
7200 char_u patbuf[NUMBUFLEN];
7201 char_u *save_cpo;
7202 long start = 0;
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00007203 long nth = 1;
7204 int match;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007205
7206 /* Make 'cpoptions' empty, the 'l' flag should not be used here. */
7207 save_cpo = p_cpo;
7208 p_cpo = (char_u *)"";
7209
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007210 expr = str = get_tv_string(&argvars[0]);
7211 pat = get_tv_string_buf(&argvars[1], patbuf);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007212
7213 if (type == 2)
7214 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007215 rettv->v_type = VAR_STRING;
7216 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007217 }
7218 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007219 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007220
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007221 if (argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007222 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007223 start = get_tv_number(&argvars[2]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007224 if (start < 0)
7225 start = 0;
7226 if (start > (long)STRLEN(str))
7227 goto theend;
7228 str += start;
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00007229
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007230 if (argvars[3].v_type != VAR_UNKNOWN)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007231 nth = get_tv_number(&argvars[3]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007232 }
7233
7234 regmatch.regprog = vim_regcomp(pat, RE_MAGIC + RE_STRING);
7235 if (regmatch.regprog != NULL)
7236 {
7237 regmatch.rm_ic = p_ic;
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00007238
7239 while (1)
7240 {
7241 match = vim_regexec_nl(&regmatch, str, (colnr_T)0);
7242 if (!match || --nth <= 0)
7243 break;
7244 /* Advance to just after the match. */
7245#ifdef FEAT_MBYTE
7246 str = regmatch.startp[0] + mb_ptr2len_check(regmatch.startp[0]);
7247#else
7248 str = regmatch.startp[0] + 1;
7249#endif
7250 }
7251
7252 if (match)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007253 {
7254 if (type == 2)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007255 rettv->vval.v_string = vim_strnsave(regmatch.startp[0],
Bram Moolenaar071d4272004-06-13 20:20:40 +00007256 (int)(regmatch.endp[0] - regmatch.startp[0]));
7257 else
7258 {
7259 if (type != 0)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007260 rettv->vval.v_number =
Bram Moolenaar071d4272004-06-13 20:20:40 +00007261 (varnumber_T)(regmatch.startp[0] - str);
7262 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007263 rettv->vval.v_number =
Bram Moolenaar071d4272004-06-13 20:20:40 +00007264 (varnumber_T)(regmatch.endp[0] - str);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007265 rettv->vval.v_number += str - expr;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007266 }
7267 }
7268 vim_free(regmatch.regprog);
7269 }
7270
7271theend:
7272 p_cpo = save_cpo;
7273}
7274
7275/*
7276 * "mode()" function
7277 */
7278/*ARGSUSED*/
7279 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007280f_mode(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007281 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007282 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007283{
7284 char_u buf[2];
7285
7286#ifdef FEAT_VISUAL
7287 if (VIsual_active)
7288 {
7289 if (VIsual_select)
7290 buf[0] = VIsual_mode + 's' - 'v';
7291 else
7292 buf[0] = VIsual_mode;
7293 }
7294 else
7295#endif
7296 if (State == HITRETURN || State == ASKMORE || State == SETWSIZE)
7297 buf[0] = 'r';
7298 else if (State & INSERT)
7299 {
7300 if (State & REPLACE_FLAG)
7301 buf[0] = 'R';
7302 else
7303 buf[0] = 'i';
7304 }
7305 else if (State & CMDLINE)
7306 buf[0] = 'c';
7307 else
7308 buf[0] = 'n';
7309
7310 buf[1] = NUL;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007311 rettv->vval.v_string = vim_strsave(buf);
7312 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007313}
7314
7315/*
7316 * "nr2char()" function
7317 */
7318 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007319f_nr2char(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007320 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007321 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007322{
7323 char_u buf[NUMBUFLEN];
7324
7325#ifdef FEAT_MBYTE
7326 if (has_mbyte)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007327 buf[(*mb_char2bytes)((int)get_tv_number(&argvars[0]), buf)] = NUL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007328 else
7329#endif
7330 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007331 buf[0] = (char_u)get_tv_number(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007332 buf[1] = NUL;
7333 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007334 rettv->v_type = VAR_STRING;
7335 rettv->vval.v_string = vim_strsave(buf);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007336}
7337
7338/*
7339 * "remove({list}, {idx})" function
7340 */
7341 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007342f_remove(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007343 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007344 typeval *rettv;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007345{
7346 listvar *l;
7347 listitem *item;
7348 long idx;
7349
7350 if (argvars[0].v_type != VAR_LIST)
7351 EMSG(_("E999: First argument of remove() must be a list"));
7352 else if ((l = argvars[0].vval.v_list) != NULL)
7353 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007354 idx = get_tv_number(&argvars[1]);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007355 item = list_getrem(l, idx);
7356 if (item == NULL)
7357 EMSGN(_(e_listidx), idx);
7358 else
7359 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007360 *rettv = item->li_tv;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007361 vim_free(item);
7362 }
7363 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00007364}
7365
7366/*
7367 * "rename({from}, {to})" function
7368 */
7369 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007370f_rename(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007371 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007372 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007373{
7374 char_u buf[NUMBUFLEN];
7375
7376 if (check_restricted() || check_secure())
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007377 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007378 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007379 rettv->vval.v_number = vim_rename(get_tv_string(&argvars[0]),
7380 get_tv_string_buf(&argvars[1], buf));
Bram Moolenaar071d4272004-06-13 20:20:40 +00007381}
7382
7383/*
7384 * "resolve()" function
7385 */
7386 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007387f_resolve(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007388 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007389 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007390{
7391 char_u *p;
7392
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007393 p = get_tv_string(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007394#ifdef FEAT_SHORTCUT
7395 {
7396 char_u *v = NULL;
7397
7398 v = mch_resolve_shortcut(p);
7399 if (v != NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007400 rettv->vval.v_string = v;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007401 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007402 rettv->vval.v_string = vim_strsave(p);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007403 }
7404#else
7405# ifdef HAVE_READLINK
7406 {
7407 char_u buf[MAXPATHL + 1];
7408 char_u *cpy;
7409 int len;
7410 char_u *remain = NULL;
7411 char_u *q;
7412 int is_relative_to_current = FALSE;
7413 int has_trailing_pathsep = FALSE;
7414 int limit = 100;
7415
7416 p = vim_strsave(p);
7417
7418 if (p[0] == '.' && (vim_ispathsep(p[1])
7419 || (p[1] == '.' && (vim_ispathsep(p[2])))))
7420 is_relative_to_current = TRUE;
7421
7422 len = STRLEN(p);
Bram Moolenaar1cd871b2004-12-19 22:46:22 +00007423 if (len > 0 && after_pathsep(p, p + len))
Bram Moolenaar071d4272004-06-13 20:20:40 +00007424 has_trailing_pathsep = TRUE;
7425
7426 q = getnextcomp(p);
7427 if (*q != NUL)
7428 {
7429 /* Separate the first path component in "p", and keep the
7430 * remainder (beginning with the path separator). */
7431 remain = vim_strsave(q - 1);
7432 q[-1] = NUL;
7433 }
7434
7435 for (;;)
7436 {
7437 for (;;)
7438 {
7439 len = readlink((char *)p, (char *)buf, MAXPATHL);
7440 if (len <= 0)
7441 break;
7442 buf[len] = NUL;
7443
7444 if (limit-- == 0)
7445 {
7446 vim_free(p);
7447 vim_free(remain);
7448 EMSG(_("E655: Too many symbolic links (cycle?)"));
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007449 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007450 goto fail;
7451 }
7452
7453 /* Ensure that the result will have a trailing path separator
7454 * if the argument has one. */
7455 if (remain == NULL && has_trailing_pathsep)
7456 add_pathsep(buf);
7457
7458 /* Separate the first path component in the link value and
7459 * concatenate the remainders. */
7460 q = getnextcomp(vim_ispathsep(*buf) ? buf + 1 : buf);
7461 if (*q != NUL)
7462 {
7463 if (remain == NULL)
7464 remain = vim_strsave(q - 1);
7465 else
7466 {
7467 cpy = vim_strnsave(q-1, STRLEN(q-1)+STRLEN(remain));
7468 if (cpy != NULL)
7469 {
7470 STRCAT(cpy, remain);
7471 vim_free(remain);
7472 remain = cpy;
7473 }
7474 }
7475 q[-1] = NUL;
7476 }
7477
7478 q = gettail(p);
7479 if (q > p && *q == NUL)
7480 {
7481 /* Ignore trailing path separator. */
7482 q[-1] = NUL;
7483 q = gettail(p);
7484 }
7485 if (q > p && !mch_isFullName(buf))
7486 {
7487 /* symlink is relative to directory of argument */
7488 cpy = alloc((unsigned)(STRLEN(p) + STRLEN(buf) + 1));
7489 if (cpy != NULL)
7490 {
7491 STRCPY(cpy, p);
7492 STRCPY(gettail(cpy), buf);
7493 vim_free(p);
7494 p = cpy;
7495 }
7496 }
7497 else
7498 {
7499 vim_free(p);
7500 p = vim_strsave(buf);
7501 }
7502 }
7503
7504 if (remain == NULL)
7505 break;
7506
7507 /* Append the first path component of "remain" to "p". */
7508 q = getnextcomp(remain + 1);
7509 len = q - remain - (*q != NUL);
7510 cpy = vim_strnsave(p, STRLEN(p) + len);
7511 if (cpy != NULL)
7512 {
7513 STRNCAT(cpy, remain, len);
7514 vim_free(p);
7515 p = cpy;
7516 }
7517 /* Shorten "remain". */
7518 if (*q != NUL)
7519 STRCPY(remain, q - 1);
7520 else
7521 {
7522 vim_free(remain);
7523 remain = NULL;
7524 }
7525 }
7526
7527 /* If the result is a relative path name, make it explicitly relative to
7528 * the current directory if and only if the argument had this form. */
7529 if (!vim_ispathsep(*p))
7530 {
7531 if (is_relative_to_current
7532 && *p != NUL
7533 && !(p[0] == '.'
7534 && (p[1] == NUL
7535 || vim_ispathsep(p[1])
7536 || (p[1] == '.'
7537 && (p[2] == NUL
7538 || vim_ispathsep(p[2]))))))
7539 {
7540 /* Prepend "./". */
7541 cpy = vim_strnsave((char_u *)"./", 2 + STRLEN(p));
7542 if (cpy != NULL)
7543 {
7544 STRCAT(cpy, p);
7545 vim_free(p);
7546 p = cpy;
7547 }
7548 }
7549 else if (!is_relative_to_current)
7550 {
7551 /* Strip leading "./". */
7552 q = p;
7553 while (q[0] == '.' && vim_ispathsep(q[1]))
7554 q += 2;
7555 if (q > p)
7556 mch_memmove(p, p + 2, STRLEN(p + 2) + (size_t)1);
7557 }
7558 }
7559
7560 /* Ensure that the result will have no trailing path separator
7561 * if the argument had none. But keep "/" or "//". */
7562 if (!has_trailing_pathsep)
7563 {
7564 q = p + STRLEN(p);
Bram Moolenaar1cd871b2004-12-19 22:46:22 +00007565 if (after_pathsep(p, q))
7566 *gettail_sep(p) = NUL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007567 }
7568
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007569 rettv->vval.v_string = p;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007570 }
7571# else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007572 rettv->vval.v_string = vim_strsave(p);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007573# endif
7574#endif
7575
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007576 simplify_filename(rettv->vval.v_string);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007577
7578#ifdef HAVE_READLINK
7579fail:
7580#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007581 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007582}
7583
7584/*
7585 * "simplify()" function
7586 */
7587 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007588f_simplify(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007589 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007590 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007591{
7592 char_u *p;
7593
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007594 p = get_tv_string(&argvars[0]);
7595 rettv->vval.v_string = vim_strsave(p);
7596 simplify_filename(rettv->vval.v_string); /* simplify in place */
7597 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007598}
7599
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00007600#define SP_NOMOVE 1 /* don't move cursor */
7601#define SP_REPEAT 2 /* repeat to find outer pair */
7602#define SP_RETCOUNT 4 /* return matchcount */
7603
Bram Moolenaar071d4272004-06-13 20:20:40 +00007604/*
7605 * "search()" function
7606 */
7607 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007608f_search(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007609 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007610 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007611{
7612 char_u *pat;
7613 pos_T pos;
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00007614 pos_T save_cursor;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007615 int save_p_ws = p_ws;
7616 int dir;
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00007617 int flags = 0;
7618
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007619 rettv->vval.v_number = 0; /* default: FAIL */
Bram Moolenaar071d4272004-06-13 20:20:40 +00007620
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007621 pat = get_tv_string(&argvars[0]);
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00007622 dir = get_search_arg(&argvars[1], &flags); /* may set p_ws */
7623 if (dir == 0)
7624 goto theend;
7625 if ((flags & ~SP_NOMOVE) != 0)
7626 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007627 EMSG2(_(e_invarg2), get_tv_string(&argvars[1]));
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00007628 goto theend;
7629 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00007630
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00007631 pos = save_cursor = curwin->w_cursor;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007632 if (searchit(curwin, curbuf, &pos, dir, pat, 1L,
7633 SEARCH_KEEP, RE_SEARCH) != FAIL)
7634 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007635 rettv->vval.v_number = pos.lnum;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007636 curwin->w_cursor = pos;
7637 /* "/$" will put the cursor after the end of the line, may need to
7638 * correct that here */
7639 check_cursor();
7640 }
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00007641
7642 /* If 'n' flag is used: restore cursor position. */
7643 if (flags & SP_NOMOVE)
7644 curwin->w_cursor = save_cursor;
7645theend:
Bram Moolenaar071d4272004-06-13 20:20:40 +00007646 p_ws = save_p_ws;
7647}
7648
Bram Moolenaar071d4272004-06-13 20:20:40 +00007649/*
7650 * "searchpair()" function
7651 */
7652 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007653f_searchpair(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007654 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007655 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007656{
7657 char_u *spat, *mpat, *epat;
7658 char_u *skip;
7659 char_u *pat, *pat2, *pat3;
7660 pos_T pos;
7661 pos_T firstpos;
7662 pos_T save_cursor;
7663 pos_T save_pos;
7664 int save_p_ws = p_ws;
7665 char_u *save_cpo;
7666 int dir;
7667 int flags = 0;
7668 char_u nbuf1[NUMBUFLEN];
7669 char_u nbuf2[NUMBUFLEN];
7670 char_u nbuf3[NUMBUFLEN];
7671 int n;
7672 int r;
7673 int nest = 1;
7674 int err;
7675
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007676 rettv->vval.v_number = 0; /* default: FAIL */
Bram Moolenaar071d4272004-06-13 20:20:40 +00007677
7678 /* Make 'cpoptions' empty, the 'l' flag should not be used here. */
7679 save_cpo = p_cpo;
7680 p_cpo = (char_u *)"";
7681
7682 /* Get the three pattern arguments: start, middle, end. */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007683 spat = get_tv_string(&argvars[0]);
7684 mpat = get_tv_string_buf(&argvars[1], nbuf1);
7685 epat = get_tv_string_buf(&argvars[2], nbuf2);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007686
7687 /* Make two search patterns: start/end (pat2, for in nested pairs) and
7688 * start/middle/end (pat3, for the top pair). */
7689 pat2 = alloc((unsigned)(STRLEN(spat) + STRLEN(epat) + 15));
7690 pat3 = alloc((unsigned)(STRLEN(spat) + STRLEN(mpat) + STRLEN(epat) + 23));
7691 if (pat2 == NULL || pat3 == NULL)
7692 goto theend;
7693 sprintf((char *)pat2, "\\(%s\\m\\)\\|\\(%s\\m\\)", spat, epat);
7694 if (*mpat == NUL)
7695 STRCPY(pat3, pat2);
7696 else
7697 sprintf((char *)pat3, "\\(%s\\m\\)\\|\\(%s\\m\\)\\|\\(%s\\m\\)",
7698 spat, epat, mpat);
7699
7700 /* Handle the optional fourth argument: flags */
7701 dir = get_search_arg(&argvars[3], &flags); /* may set p_ws */
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00007702 if (dir == 0)
7703 goto theend;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007704
7705 /* Optional fifth argument: skip expresion */
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007706 if (argvars[3].v_type == VAR_UNKNOWN
7707 || argvars[4].v_type == VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007708 skip = (char_u *)"";
7709 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007710 skip = get_tv_string_buf(&argvars[4], nbuf3);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007711
7712 save_cursor = curwin->w_cursor;
7713 pos = curwin->w_cursor;
7714 firstpos.lnum = 0;
7715 pat = pat3;
7716 for (;;)
7717 {
7718 n = searchit(curwin, curbuf, &pos, dir, pat, 1L,
7719 SEARCH_KEEP, RE_SEARCH);
7720 if (n == FAIL || (firstpos.lnum != 0 && equalpos(pos, firstpos)))
7721 /* didn't find it or found the first match again: FAIL */
7722 break;
7723
7724 if (firstpos.lnum == 0)
7725 firstpos = pos;
7726
7727 /* If the skip pattern matches, ignore this match. */
7728 if (*skip != NUL)
7729 {
7730 save_pos = curwin->w_cursor;
7731 curwin->w_cursor = pos;
7732 r = eval_to_bool(skip, &err, NULL, FALSE);
7733 curwin->w_cursor = save_pos;
7734 if (err)
7735 {
7736 /* Evaluating {skip} caused an error, break here. */
7737 curwin->w_cursor = save_cursor;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007738 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007739 break;
7740 }
7741 if (r)
7742 continue;
7743 }
7744
7745 if ((dir == BACKWARD && n == 3) || (dir == FORWARD && n == 2))
7746 {
7747 /* Found end when searching backwards or start when searching
7748 * forward: nested pair. */
7749 ++nest;
7750 pat = pat2; /* nested, don't search for middle */
7751 }
7752 else
7753 {
7754 /* Found end when searching forward or start when searching
7755 * backward: end of (nested) pair; or found middle in outer pair. */
7756 if (--nest == 1)
7757 pat = pat3; /* outer level, search for middle */
7758 }
7759
7760 if (nest == 0)
7761 {
7762 /* Found the match: return matchcount or line number. */
7763 if (flags & SP_RETCOUNT)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007764 ++rettv->vval.v_number;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007765 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007766 rettv->vval.v_number = pos.lnum;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007767 curwin->w_cursor = pos;
7768 if (!(flags & SP_REPEAT))
7769 break;
7770 nest = 1; /* search for next unmatched */
7771 }
7772 }
7773
7774 /* If 'n' flag is used or search failed: restore cursor position. */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007775 if ((flags & SP_NOMOVE) || rettv->vval.v_number == 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007776 curwin->w_cursor = save_cursor;
7777
7778theend:
7779 vim_free(pat2);
7780 vim_free(pat3);
7781 p_ws = save_p_ws;
7782 p_cpo = save_cpo;
7783}
7784
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00007785/*
7786 * Get flags for a search function.
7787 * Possibly sets "p_ws".
7788 * Returns BACKWARD, FORWARD or zero (for an error).
7789 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00007790 static int
7791get_search_arg(varp, flagsp)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007792 typeval *varp;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007793 int *flagsp;
7794{
7795 int dir = FORWARD;
7796 char_u *flags;
7797 char_u nbuf[NUMBUFLEN];
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00007798 int mask;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007799
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007800 if (varp->v_type != VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007801 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007802 flags = get_tv_string_buf(varp, nbuf);
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00007803 while (*flags != NUL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007804 {
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00007805 switch (*flags)
7806 {
7807 case 'b': dir = BACKWARD; break;
7808 case 'w': p_ws = TRUE; break;
7809 case 'W': p_ws = FALSE; break;
7810 default: mask = 0;
7811 if (flagsp != NULL)
7812 switch (*flags)
7813 {
7814 case 'n': mask = SP_NOMOVE; break;
7815 case 'r': mask = SP_REPEAT; break;
7816 case 'm': mask = SP_RETCOUNT; break;
7817 }
7818 if (mask == 0)
7819 {
7820 EMSG2(_(e_invarg2), flags);
7821 dir = 0;
7822 }
7823 else
7824 *flagsp |= mask;
7825 }
7826 if (dir == 0)
7827 break;
7828 ++flags;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007829 }
7830 }
7831 return dir;
7832}
7833
7834/*
7835 * "setbufvar()" function
7836 */
7837/*ARGSUSED*/
7838 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007839f_setbufvar(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007840 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007841 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007842{
7843 buf_T *buf;
7844#ifdef FEAT_AUTOCMD
7845 aco_save_T aco;
7846#else
7847 buf_T *save_curbuf;
7848#endif
7849 char_u *varname, *bufvarname;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007850 typeval *varp;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007851 char_u nbuf[NUMBUFLEN];
7852
7853 if (check_restricted() || check_secure())
7854 return;
7855 ++emsg_off;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007856 buf = get_buf_tv(&argvars[0]);
7857 varname = get_tv_string(&argvars[1]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007858 varp = &argvars[2];
7859
7860 if (buf != NULL && varname != NULL && varp != NULL)
7861 {
7862 /* set curbuf to be our buf, temporarily */
7863#ifdef FEAT_AUTOCMD
7864 aucmd_prepbuf(&aco, buf);
7865#else
7866 save_curbuf = curbuf;
7867 curbuf = buf;
7868#endif
7869
7870 if (*varname == '&')
7871 {
7872 ++varname;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007873 set_option_value(varname, get_tv_number(varp),
7874 get_tv_string_buf(varp, nbuf), OPT_LOCAL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007875 }
7876 else
7877 {
7878 bufvarname = alloc((unsigned)STRLEN(varname) + 3);
7879 if (bufvarname != NULL)
7880 {
7881 STRCPY(bufvarname, "b:");
7882 STRCPY(bufvarname + 2, varname);
Bram Moolenaar1c2fda22005-01-02 11:43:19 +00007883 set_var(bufvarname, varp, TRUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007884 vim_free(bufvarname);
7885 }
7886 }
7887
7888 /* reset notion of buffer */
7889#ifdef FEAT_AUTOCMD
7890 aucmd_restbuf(&aco);
7891#else
7892 curbuf = save_curbuf;
7893#endif
7894 }
7895 --emsg_off;
7896}
7897
7898/*
7899 * "setcmdpos()" function
7900 */
7901 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007902f_setcmdpos(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007903 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007904 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007905{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007906 rettv->vval.v_number = set_cmdline_pos(
7907 (int)get_tv_number(&argvars[0]) - 1);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007908}
7909
7910/*
7911 * "setline()" function
7912 */
7913 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007914f_setline(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007915 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007916 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007917{
7918 linenr_T lnum;
7919 char_u *line;
7920
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007921 lnum = get_tv_lnum(argvars);
7922 line = get_tv_string(&argvars[1]);
7923 rettv->vval.v_number = 1; /* FAIL is default */
Bram Moolenaar071d4272004-06-13 20:20:40 +00007924
7925 if (lnum >= 1
7926 && lnum <= curbuf->b_ml.ml_line_count
7927 && u_savesub(lnum) == OK
7928 && ml_replace(lnum, line, TRUE) == OK)
7929 {
7930 changed_bytes(lnum, 0);
7931 check_cursor_col();
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007932 rettv->vval.v_number = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007933 }
7934}
7935
7936/*
7937 * "setreg()" function
7938 */
7939 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007940f_setreg(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007941 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007942 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007943{
7944 int regname;
7945 char_u *strregname;
7946 char_u *stropt;
7947 int append;
7948 char_u yank_type;
7949 long block_len;
7950
7951 block_len = -1;
7952 yank_type = MAUTO;
7953 append = FALSE;
7954
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007955 strregname = get_tv_string(argvars);
7956 rettv->vval.v_number = 1; /* FAIL is default */
Bram Moolenaar071d4272004-06-13 20:20:40 +00007957
7958 regname = (strregname == NULL ? '"' : *strregname);
7959 if (regname == 0 || regname == '@')
7960 regname = '"';
7961 else if (regname == '=')
7962 return;
7963
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007964 if (argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007965 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007966 for (stropt = get_tv_string(&argvars[2]); *stropt != NUL; ++stropt)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007967 switch (*stropt)
7968 {
7969 case 'a': case 'A': /* append */
7970 append = TRUE;
7971 break;
7972 case 'v': case 'c': /* character-wise selection */
7973 yank_type = MCHAR;
7974 break;
7975 case 'V': case 'l': /* line-wise selection */
7976 yank_type = MLINE;
7977 break;
7978#ifdef FEAT_VISUAL
7979 case 'b': case Ctrl_V: /* block-wise selection */
7980 yank_type = MBLOCK;
7981 if (VIM_ISDIGIT(stropt[1]))
7982 {
7983 ++stropt;
7984 block_len = getdigits(&stropt) - 1;
7985 --stropt;
7986 }
7987 break;
7988#endif
7989 }
7990 }
7991
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007992 write_reg_contents_ex(regname, get_tv_string(&argvars[1]), -1,
Bram Moolenaar071d4272004-06-13 20:20:40 +00007993 append, yank_type, block_len);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007994 rettv->vval.v_number = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007995}
7996
7997
7998/*
7999 * "setwinvar(expr)" function
8000 */
8001/*ARGSUSED*/
8002 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008003f_setwinvar(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008004 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008005 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008006{
8007 win_T *win;
8008#ifdef FEAT_WINDOWS
8009 win_T *save_curwin;
8010#endif
8011 char_u *varname, *winvarname;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008012 typeval *varp;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008013 char_u nbuf[NUMBUFLEN];
8014
8015 if (check_restricted() || check_secure())
8016 return;
8017 ++emsg_off;
8018 win = find_win_by_nr(&argvars[0]);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008019 varname = get_tv_string(&argvars[1]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008020 varp = &argvars[2];
8021
8022 if (win != NULL && varname != NULL && varp != NULL)
8023 {
8024#ifdef FEAT_WINDOWS
8025 /* set curwin to be our win, temporarily */
8026 save_curwin = curwin;
8027 curwin = win;
8028 curbuf = curwin->w_buffer;
8029#endif
8030
8031 if (*varname == '&')
8032 {
8033 ++varname;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008034 set_option_value(varname, get_tv_number(varp),
8035 get_tv_string_buf(varp, nbuf), OPT_LOCAL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008036 }
8037 else
8038 {
8039 winvarname = alloc((unsigned)STRLEN(varname) + 3);
8040 if (winvarname != NULL)
8041 {
8042 STRCPY(winvarname, "w:");
8043 STRCPY(winvarname + 2, varname);
Bram Moolenaar1c2fda22005-01-02 11:43:19 +00008044 set_var(winvarname, varp, TRUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008045 vim_free(winvarname);
8046 }
8047 }
8048
8049#ifdef FEAT_WINDOWS
8050 /* Restore current window, if it's still valid (autocomands can make
8051 * it invalid). */
8052 if (win_valid(save_curwin))
8053 {
8054 curwin = save_curwin;
8055 curbuf = curwin->w_buffer;
8056 }
8057#endif
8058 }
8059 --emsg_off;
8060}
8061
8062/*
8063 * "nextnonblank()" function
8064 */
8065 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008066f_nextnonblank(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008067 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008068 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008069{
8070 linenr_T lnum;
8071
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008072 for (lnum = get_tv_lnum(argvars); ; ++lnum)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008073 {
8074 if (lnum > curbuf->b_ml.ml_line_count)
8075 {
8076 lnum = 0;
8077 break;
8078 }
8079 if (*skipwhite(ml_get(lnum)) != NUL)
8080 break;
8081 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008082 rettv->vval.v_number = lnum;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008083}
8084
8085/*
8086 * "prevnonblank()" function
8087 */
8088 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008089f_prevnonblank(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008090 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008091 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008092{
8093 linenr_T lnum;
8094
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008095 lnum = get_tv_lnum(argvars);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008096 if (lnum < 1 || lnum > curbuf->b_ml.ml_line_count)
8097 lnum = 0;
8098 else
8099 while (lnum >= 1 && *skipwhite(ml_get(lnum)) == NUL)
8100 --lnum;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008101 rettv->vval.v_number = lnum;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008102}
8103
8104#if defined(FEAT_CLIENTSERVER) && defined(FEAT_X11)
8105static void make_connection __ARGS((void));
8106static int check_connection __ARGS((void));
8107
8108 static void
8109make_connection()
8110{
8111 if (X_DISPLAY == NULL
8112# ifdef FEAT_GUI
8113 && !gui.in_use
8114# endif
8115 )
8116 {
8117 x_force_connect = TRUE;
8118 setup_term_clip();
8119 x_force_connect = FALSE;
8120 }
8121}
8122
8123 static int
8124check_connection()
8125{
8126 make_connection();
8127 if (X_DISPLAY == NULL)
8128 {
8129 EMSG(_("E240: No connection to Vim server"));
8130 return FAIL;
8131 }
8132 return OK;
8133}
8134#endif
8135
8136/*ARGSUSED*/
8137 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008138f_serverlist(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 *r = NULL;
8143
8144#ifdef FEAT_CLIENTSERVER
8145# ifdef WIN32
8146 r = serverGetVimNames();
8147# else
8148 make_connection();
8149 if (X_DISPLAY != NULL)
8150 r = serverGetVimNames(X_DISPLAY);
8151# endif
8152#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008153 rettv->v_type = VAR_STRING;
8154 rettv->vval.v_string = r;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008155}
8156
8157/*ARGSUSED*/
8158 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008159f_remote_peek(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008160 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008161 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008162{
8163#ifdef FEAT_CLIENTSERVER
8164 var v;
8165 char_u *s = NULL;
8166# ifdef WIN32
8167 int n = 0;
8168# endif
8169
8170 if (check_restricted() || check_secure())
8171 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008172 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008173 return;
8174 }
8175# ifdef WIN32
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008176 sscanf(get_tv_string(&argvars[0]), "%x", &n);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008177 if (n == 0)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008178 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008179 else
8180 {
8181 s = serverGetReply((HWND)n, FALSE, FALSE, FALSE);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008182 rettv->vval.v_number = (s != NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008183 }
8184# else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008185 rettv->vval.v_number = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008186 if (check_connection() == FAIL)
8187 return;
8188
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008189 rettv->vval.v_number = serverPeekReply(X_DISPLAY,
8190 serverStrToWin(get_tv_string(&argvars[0])), &s);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008191# endif
8192
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008193 if (argvars[1].v_type != VAR_UNKNOWN && rettv->vval.v_number > 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008194 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008195 v.tv.v_type = VAR_STRING;
8196 v.tv.vval.v_string = vim_strsave(s);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008197 set_var(get_tv_string(&argvars[1]), &v.tv, FALSE);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008198 vim_free(v.tv.vval.v_string);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008199 }
8200#else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008201 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008202#endif
8203}
8204
8205/*ARGSUSED*/
8206 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008207f_remote_read(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008208 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008209 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008210{
8211 char_u *r = NULL;
8212
8213#ifdef FEAT_CLIENTSERVER
8214 if (!check_restricted() && !check_secure())
8215 {
8216# ifdef WIN32
8217 /* The server's HWND is encoded in the 'id' parameter */
8218 int n = 0;
8219
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008220 sscanf(get_tv_string(&argvars[0]), "%x", &n);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008221 if (n != 0)
8222 r = serverGetReply((HWND)n, FALSE, TRUE, TRUE);
8223 if (r == NULL)
8224# else
8225 if (check_connection() == FAIL || serverReadReply(X_DISPLAY,
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008226 serverStrToWin(get_tv_string(&argvars[0])), &r, FALSE) < 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008227# endif
8228 EMSG(_("E277: Unable to read a server reply"));
8229 }
8230#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008231 rettv->v_type = VAR_STRING;
8232 rettv->vval.v_string = r;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008233}
8234
8235/*ARGSUSED*/
8236 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008237f_server2client(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008238 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008239 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008240{
8241#ifdef FEAT_CLIENTSERVER
8242 char_u buf[NUMBUFLEN];
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008243 char_u *server = get_tv_string(&argvars[0]);
8244 char_u *reply = get_tv_string_buf(&argvars[1], buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008245
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008246 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008247 if (check_restricted() || check_secure())
8248 return;
8249# ifdef FEAT_X11
8250 if (check_connection() == FAIL)
8251 return;
8252# endif
8253
8254 if (serverSendReply(server, reply) < 0)
8255 {
8256 EMSG(_("E258: Unable to send to client"));
8257 return;
8258 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008259 rettv->vval.v_number = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008260#else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008261 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008262#endif
8263}
8264
8265#ifdef FEAT_CLIENTSERVER
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008266static void remote_common __ARGS((typeval *argvars, typeval *rettv, int expr));
Bram Moolenaar071d4272004-06-13 20:20:40 +00008267
8268 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008269remote_common(argvars, rettv, expr)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008270 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008271 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008272 int expr;
8273{
8274 char_u *server_name;
8275 char_u *keys;
8276 char_u *r = NULL;
8277 char_u buf[NUMBUFLEN];
8278# ifdef WIN32
8279 HWND w;
8280# else
8281 Window w;
8282# endif
8283
8284 if (check_restricted() || check_secure())
8285 return;
8286
8287# ifdef FEAT_X11
8288 if (check_connection() == FAIL)
8289 return;
8290# endif
8291
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008292 server_name = get_tv_string(&argvars[0]);
8293 keys = get_tv_string_buf(&argvars[1], buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008294# ifdef WIN32
8295 if (serverSendToVim(server_name, keys, &r, &w, expr, TRUE) < 0)
8296# else
8297 if (serverSendToVim(X_DISPLAY, server_name, keys, &r, &w, expr, 0, TRUE)
8298 < 0)
8299# endif
8300 {
8301 if (r != NULL)
8302 EMSG(r); /* sending worked but evaluation failed */
8303 else
8304 EMSG2(_("E241: Unable to send to %s"), server_name);
8305 return;
8306 }
8307
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008308 rettv->vval.v_string = r;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008309
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008310 if (argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008311 {
8312 var v;
8313 char_u str[30];
8314
8315 sprintf((char *)str, "0x%x", (unsigned int)w);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008316 v.tv.v_type = VAR_STRING;
8317 v.tv.vval.v_string = vim_strsave(str);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008318 set_var(get_tv_string(&argvars[2]), &v.tv, FALSE);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008319 vim_free(v.tv.vval.v_string);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008320 }
8321}
8322#endif
8323
8324/*
8325 * "remote_expr()" function
8326 */
8327/*ARGSUSED*/
8328 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008329f_remote_expr(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008330 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008331 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008332{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008333 rettv->v_type = VAR_STRING;
8334 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008335#ifdef FEAT_CLIENTSERVER
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008336 remote_common(argvars, rettv, TRUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008337#endif
8338}
8339
8340/*
8341 * "remote_send()" function
8342 */
8343/*ARGSUSED*/
8344 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008345f_remote_send(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008346 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008347 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008348{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008349 rettv->v_type = VAR_STRING;
8350 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008351#ifdef FEAT_CLIENTSERVER
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008352 remote_common(argvars, rettv, FALSE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008353#endif
8354}
8355
8356/*
8357 * "remote_foreground()" function
8358 */
8359/*ARGSUSED*/
8360 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008361f_remote_foreground(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008362 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008363 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008364{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008365 rettv->vval.v_number = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008366#ifdef FEAT_CLIENTSERVER
8367# ifdef WIN32
8368 /* On Win32 it's done in this application. */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008369 serverForeground(get_tv_string(&argvars[0]));
Bram Moolenaar071d4272004-06-13 20:20:40 +00008370# else
8371 /* Send a foreground() expression to the server. */
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008372 argvars[1].v_type = VAR_STRING;
8373 argvars[1].vval.v_string = vim_strsave((char_u *)"foreground()");
8374 argvars[2].v_type = VAR_UNKNOWN;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008375 remote_common(argvars, rettv, TRUE);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008376 vim_free(argvars[1].vval.v_string);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008377# endif
8378#endif
8379}
8380
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00008381/*
8382 * "repeat()" function
8383 */
8384/*ARGSUSED*/
8385 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008386f_repeat(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008387 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008388 typeval *rettv;
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00008389{
8390 char_u *p;
8391 int n;
8392 int slen;
8393 int len;
8394 char_u *r;
8395 int i;
8396
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008397 p = get_tv_string(&argvars[0]);
8398 n = get_tv_number(&argvars[1]);
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00008399
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008400 rettv->v_type = VAR_STRING;
8401 rettv->vval.v_string = NULL;
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00008402
8403 slen = (int)STRLEN(p);
8404 len = slen * n;
8405
8406 if (len <= 0)
8407 return;
8408
8409 r = alloc(len + 1);
8410 if (r != NULL)
8411 {
8412 for (i = 0; i < n; i++)
8413 mch_memmove(r + i * slen, p, (size_t)slen);
8414 r[len] = NUL;
8415 }
8416
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008417 rettv->vval.v_string = r;
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00008418}
8419
Bram Moolenaar071d4272004-06-13 20:20:40 +00008420#ifdef HAVE_STRFTIME
8421/*
8422 * "strftime({format}[, {time}])" function
8423 */
8424 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008425f_strftime(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008426 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008427 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008428{
8429 char_u result_buf[256];
8430 struct tm *curtime;
8431 time_t seconds;
8432 char_u *p;
8433
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008434 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008435
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008436 p = get_tv_string(&argvars[0]);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008437 if (argvars[1].v_type == VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008438 seconds = time(NULL);
8439 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008440 seconds = (time_t)get_tv_number(&argvars[1]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008441 curtime = localtime(&seconds);
8442 /* MSVC returns NULL for an invalid value of seconds. */
8443 if (curtime == NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008444 rettv->vval.v_string = vim_strsave((char_u *)_("(Invalid)"));
Bram Moolenaar071d4272004-06-13 20:20:40 +00008445 else
8446 {
8447# ifdef FEAT_MBYTE
8448 vimconv_T conv;
8449 char_u *enc;
8450
8451 conv.vc_type = CONV_NONE;
8452 enc = enc_locale();
8453 convert_setup(&conv, p_enc, enc);
8454 if (conv.vc_type != CONV_NONE)
8455 p = string_convert(&conv, p, NULL);
8456# endif
8457 if (p != NULL)
8458 (void)strftime((char *)result_buf, sizeof(result_buf),
8459 (char *)p, curtime);
8460 else
8461 result_buf[0] = NUL;
8462
8463# ifdef FEAT_MBYTE
8464 if (conv.vc_type != CONV_NONE)
8465 vim_free(p);
8466 convert_setup(&conv, enc, p_enc);
8467 if (conv.vc_type != CONV_NONE)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008468 rettv->vval.v_string = string_convert(&conv, result_buf, NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008469 else
8470# endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008471 rettv->vval.v_string = vim_strsave(result_buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008472
8473# ifdef FEAT_MBYTE
8474 /* Release conversion descriptors */
8475 convert_setup(&conv, NULL, NULL);
8476 vim_free(enc);
8477# endif
8478 }
8479}
8480#endif
8481
8482/*
8483 * "stridx()" function
8484 */
8485 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008486f_stridx(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008487 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008488 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008489{
8490 char_u buf[NUMBUFLEN];
8491 char_u *needle;
8492 char_u *haystack;
8493 char_u *pos;
8494
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008495 needle = get_tv_string(&argvars[1]);
8496 haystack = get_tv_string_buf(&argvars[0], buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008497 pos = (char_u *)strstr((char *)haystack, (char *)needle);
8498
8499 if (pos == NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008500 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008501 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008502 rettv->vval.v_number = (varnumber_T) (pos - haystack);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008503}
8504
8505/*
8506 * "strridx()" function
8507 */
8508 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008509f_strridx(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008510 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008511 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008512{
8513 char_u buf[NUMBUFLEN];
8514 char_u *needle;
8515 char_u *haystack;
8516 char_u *rest;
8517 char_u *lastmatch = NULL;
8518
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008519 needle = get_tv_string(&argvars[1]);
8520 haystack = get_tv_string_buf(&argvars[0], buf);
Bram Moolenaard4755bb2004-09-02 19:12:26 +00008521 if (*needle == NUL)
8522 /* Empty string matches past the end. */
8523 lastmatch = haystack + STRLEN(haystack);
8524 else
8525 for (rest = haystack; *rest != '\0'; ++rest)
8526 {
8527 rest = (char_u *)strstr((char *)rest, (char *)needle);
8528 if (rest == NULL)
8529 break;
8530 lastmatch = rest;
8531 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00008532
8533 if (lastmatch == NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008534 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008535 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008536 rettv->vval.v_number = (varnumber_T)(lastmatch - haystack);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008537}
8538
8539/*
8540 * "string()" function
8541 */
8542 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008543f_string(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008544 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008545 typeval *rettv;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008546{
8547 char_u *tofree;
8548
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008549 rettv->v_type = VAR_STRING;
8550 rettv->vval.v_string = tv2string(&argvars[0], &tofree);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008551 if (tofree == NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008552 rettv->vval.v_string = vim_strsave(rettv->vval.v_string);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008553}
8554
8555/*
8556 * "strlen()" function
8557 */
8558 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008559f_strlen(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008560 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008561 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008562{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008563 rettv->vval.v_number = (varnumber_T)(STRLEN(
8564 get_tv_string(&argvars[0])));
Bram Moolenaar071d4272004-06-13 20:20:40 +00008565}
8566
8567/*
8568 * "strpart()" function
8569 */
8570 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008571f_strpart(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008572 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008573 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008574{
8575 char_u *p;
8576 int n;
8577 int len;
8578 int slen;
8579
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008580 p = get_tv_string(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008581 slen = (int)STRLEN(p);
8582
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008583 n = get_tv_number(&argvars[1]);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008584 if (argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008585 len = get_tv_number(&argvars[2]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008586 else
8587 len = slen - n; /* default len: all bytes that are available. */
8588
8589 /*
8590 * Only return the overlap between the specified part and the actual
8591 * string.
8592 */
8593 if (n < 0)
8594 {
8595 len += n;
8596 n = 0;
8597 }
8598 else if (n > slen)
8599 n = slen;
8600 if (len < 0)
8601 len = 0;
8602 else if (n + len > slen)
8603 len = slen - n;
8604
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008605 rettv->v_type = VAR_STRING;
8606 rettv->vval.v_string = vim_strnsave(p + n, len);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008607}
8608
8609/*
8610 * "strtrans()" function
8611 */
8612 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008613f_strtrans(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008614 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008615 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008616{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008617 rettv->v_type = VAR_STRING;
8618 rettv->vval.v_string = transstr(get_tv_string(&argvars[0]));
Bram Moolenaar071d4272004-06-13 20:20:40 +00008619}
8620
8621/*
8622 * "synID(line, col, trans)" function
8623 */
8624/*ARGSUSED*/
8625 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008626f_synID(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008627 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008628 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008629{
8630 int id = 0;
8631#ifdef FEAT_SYN_HL
8632 long line;
8633 long col;
8634 int trans;
8635
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008636 line = get_tv_lnum(argvars);
8637 col = get_tv_number(&argvars[1]) - 1;
8638 trans = get_tv_number(&argvars[2]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008639
8640 if (line >= 1 && line <= curbuf->b_ml.ml_line_count
8641 && col >= 0 && col < (long)STRLEN(ml_get(line)))
8642 id = syn_get_id(line, col, trans);
8643#endif
8644
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008645 rettv->vval.v_number = id;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008646}
8647
8648/*
8649 * "synIDattr(id, what [, mode])" function
8650 */
8651/*ARGSUSED*/
8652 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008653f_synIDattr(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{
8657 char_u *p = NULL;
8658#ifdef FEAT_SYN_HL
8659 int id;
8660 char_u *what;
8661 char_u *mode;
8662 char_u modebuf[NUMBUFLEN];
8663 int modec;
8664
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008665 id = get_tv_number(&argvars[0]);
8666 what = get_tv_string(&argvars[1]);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008667 if (argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008668 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008669 mode = get_tv_string_buf(&argvars[2], modebuf);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008670 modec = TOLOWER_ASC(mode[0]);
8671 if (modec != 't' && modec != 'c'
8672#ifdef FEAT_GUI
8673 && modec != 'g'
8674#endif
8675 )
8676 modec = 0; /* replace invalid with current */
8677 }
8678 else
8679 {
8680#ifdef FEAT_GUI
8681 if (gui.in_use)
8682 modec = 'g';
8683 else
8684#endif
8685 if (t_colors > 1)
8686 modec = 'c';
8687 else
8688 modec = 't';
8689 }
8690
8691
8692 switch (TOLOWER_ASC(what[0]))
8693 {
8694 case 'b':
8695 if (TOLOWER_ASC(what[1]) == 'g') /* bg[#] */
8696 p = highlight_color(id, what, modec);
8697 else /* bold */
8698 p = highlight_has_attr(id, HL_BOLD, modec);
8699 break;
8700
8701 case 'f': /* fg[#] */
8702 p = highlight_color(id, what, modec);
8703 break;
8704
8705 case 'i':
8706 if (TOLOWER_ASC(what[1]) == 'n') /* inverse */
8707 p = highlight_has_attr(id, HL_INVERSE, modec);
8708 else /* italic */
8709 p = highlight_has_attr(id, HL_ITALIC, modec);
8710 break;
8711
8712 case 'n': /* name */
8713 p = get_highlight_name(NULL, id - 1);
8714 break;
8715
8716 case 'r': /* reverse */
8717 p = highlight_has_attr(id, HL_INVERSE, modec);
8718 break;
8719
8720 case 's': /* standout */
8721 p = highlight_has_attr(id, HL_STANDOUT, modec);
8722 break;
8723
8724 case 'u': /* underline */
8725 p = highlight_has_attr(id, HL_UNDERLINE, modec);
8726 break;
8727 }
8728
8729 if (p != NULL)
8730 p = vim_strsave(p);
8731#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008732 rettv->v_type = VAR_STRING;
8733 rettv->vval.v_string = p;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008734}
8735
8736/*
8737 * "synIDtrans(id)" function
8738 */
8739/*ARGSUSED*/
8740 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008741f_synIDtrans(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008742 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008743 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008744{
8745 int id;
8746
8747#ifdef FEAT_SYN_HL
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008748 id = get_tv_number(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008749
8750 if (id > 0)
8751 id = syn_get_final_id(id);
8752 else
8753#endif
8754 id = 0;
8755
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008756 rettv->vval.v_number = id;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008757}
8758
8759/*
8760 * "system()" function
8761 */
8762 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008763f_system(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008764 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008765 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008766{
Bram Moolenaarc0197e22004-09-13 20:26:32 +00008767 char_u *res = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008768 char_u *p;
Bram Moolenaarc0197e22004-09-13 20:26:32 +00008769 char_u *infile = NULL;
8770 char_u buf[NUMBUFLEN];
8771 int err = FALSE;
8772 FILE *fd;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008773
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008774 if (argvars[1].v_type != VAR_UNKNOWN)
Bram Moolenaarc0197e22004-09-13 20:26:32 +00008775 {
8776 /*
8777 * Write the string to a temp file, to be used for input of the shell
8778 * command.
8779 */
8780 if ((infile = vim_tempname('i')) == NULL)
8781 {
8782 EMSG(_(e_notmp));
8783 return;
8784 }
8785
8786 fd = mch_fopen((char *)infile, WRITEBIN);
8787 if (fd == NULL)
8788 {
8789 EMSG2(_(e_notopen), infile);
8790 goto done;
8791 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008792 p = get_tv_string_buf(&argvars[1], buf);
Bram Moolenaarc0197e22004-09-13 20:26:32 +00008793 if (fwrite(p, STRLEN(p), 1, fd) != 1)
8794 err = TRUE;
8795 if (fclose(fd) != 0)
8796 err = TRUE;
8797 if (err)
8798 {
8799 EMSG(_("E677: Error writing temp file"));
8800 goto done;
8801 }
8802 }
8803
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008804 res = get_cmd_output(get_tv_string(&argvars[0]), infile, SHELL_SILENT);
Bram Moolenaarc0197e22004-09-13 20:26:32 +00008805
Bram Moolenaar071d4272004-06-13 20:20:40 +00008806#ifdef USE_CR
8807 /* translate <CR> into <NL> */
Bram Moolenaarc0197e22004-09-13 20:26:32 +00008808 if (res != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008809 {
8810 char_u *s;
8811
Bram Moolenaarc0197e22004-09-13 20:26:32 +00008812 for (s = res; *s; ++s)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008813 {
8814 if (*s == CAR)
8815 *s = NL;
8816 }
8817 }
8818#else
8819# ifdef USE_CRNL
8820 /* translate <CR><NL> into <NL> */
Bram Moolenaarc0197e22004-09-13 20:26:32 +00008821 if (res != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008822 {
8823 char_u *s, *d;
8824
Bram Moolenaarc0197e22004-09-13 20:26:32 +00008825 d = res;
8826 for (s = res; *s; ++s)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008827 {
8828 if (s[0] == CAR && s[1] == NL)
8829 ++s;
8830 *d++ = *s;
8831 }
8832 *d = NUL;
8833 }
8834# endif
8835#endif
Bram Moolenaarc0197e22004-09-13 20:26:32 +00008836
8837done:
8838 if (infile != NULL)
8839 {
8840 mch_remove(infile);
8841 vim_free(infile);
8842 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008843 rettv->v_type = VAR_STRING;
8844 rettv->vval.v_string = res;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008845}
8846
8847/*
8848 * "submatch()" function
8849 */
8850 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008851f_submatch(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008852 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008853 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008854{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008855 rettv->v_type = VAR_STRING;
8856 rettv->vval.v_string = reg_submatch((int)get_tv_number(&argvars[0]));
Bram Moolenaar071d4272004-06-13 20:20:40 +00008857}
8858
8859/*
8860 * "substitute()" function
8861 */
8862 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008863f_substitute(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008864 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008865 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008866{
8867 char_u patbuf[NUMBUFLEN];
8868 char_u subbuf[NUMBUFLEN];
8869 char_u flagsbuf[NUMBUFLEN];
8870
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008871 rettv->v_type = VAR_STRING;
8872 rettv->vval.v_string = do_string_sub(
8873 get_tv_string(&argvars[0]),
8874 get_tv_string_buf(&argvars[1], patbuf),
8875 get_tv_string_buf(&argvars[2], subbuf),
8876 get_tv_string_buf(&argvars[3], flagsbuf));
Bram Moolenaar071d4272004-06-13 20:20:40 +00008877}
8878
8879/*
8880 * "tempname()" function
8881 */
8882/*ARGSUSED*/
8883 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008884f_tempname(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008885 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008886 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008887{
8888 static int x = 'A';
8889
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008890 rettv->v_type = VAR_STRING;
8891 rettv->vval.v_string = vim_tempname(x);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008892
8893 /* Advance 'x' to use A-Z and 0-9, so that there are at least 34 different
8894 * names. Skip 'I' and 'O', they are used for shell redirection. */
8895 do
8896 {
8897 if (x == 'Z')
8898 x = '0';
8899 else if (x == '9')
8900 x = 'A';
8901 else
8902 {
8903#ifdef EBCDIC
8904 if (x == 'I')
8905 x = 'J';
8906 else if (x == 'R')
8907 x = 'S';
8908 else
8909#endif
8910 ++x;
8911 }
8912 } while (x == 'I' || x == 'O');
8913}
8914
8915/*
8916 * "tolower(string)" function
8917 */
8918 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008919f_tolower(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008920 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008921 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008922{
8923 char_u *p;
8924
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008925 p = vim_strsave(get_tv_string(&argvars[0]));
8926 rettv->v_type = VAR_STRING;
8927 rettv->vval.v_string = p;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008928
8929 if (p != NULL)
8930 while (*p != NUL)
8931 {
8932#ifdef FEAT_MBYTE
8933 int l;
8934
8935 if (enc_utf8)
8936 {
8937 int c, lc;
8938
8939 c = utf_ptr2char(p);
8940 lc = utf_tolower(c);
8941 l = utf_ptr2len_check(p);
8942 /* TODO: reallocate string when byte count changes. */
8943 if (utf_char2len(lc) == l)
8944 utf_char2bytes(lc, p);
8945 p += l;
8946 }
8947 else if (has_mbyte && (l = (*mb_ptr2len_check)(p)) > 1)
8948 p += l; /* skip multi-byte character */
8949 else
8950#endif
8951 {
8952 *p = TOLOWER_LOC(*p); /* note that tolower() can be a macro */
8953 ++p;
8954 }
8955 }
8956}
8957
8958/*
8959 * "toupper(string)" function
8960 */
8961 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008962f_toupper(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008963 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008964 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008965{
8966 char_u *p;
8967
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008968 p = vim_strsave(get_tv_string(&argvars[0]));
8969 rettv->v_type = VAR_STRING;
8970 rettv->vval.v_string = p;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008971
8972 if (p != NULL)
8973 while (*p != NUL)
8974 {
8975#ifdef FEAT_MBYTE
8976 int l;
8977
8978 if (enc_utf8)
8979 {
8980 int c, uc;
8981
8982 c = utf_ptr2char(p);
8983 uc = utf_toupper(c);
8984 l = utf_ptr2len_check(p);
8985 /* TODO: reallocate string when byte count changes. */
8986 if (utf_char2len(uc) == l)
8987 utf_char2bytes(uc, p);
8988 p += l;
8989 }
8990 else if (has_mbyte && (l = (*mb_ptr2len_check)(p)) > 1)
8991 p += l; /* skip multi-byte character */
8992 else
8993#endif
8994 {
8995 *p = TOUPPER_LOC(*p); /* note that toupper() can be a macro */
8996 p++;
8997 }
8998 }
8999}
9000
9001/*
Bram Moolenaar8299df92004-07-10 09:47:34 +00009002 * "tr(string, fromstr, tostr)" function
9003 */
9004 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009005f_tr(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009006 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009007 typeval *rettv;
Bram Moolenaar8299df92004-07-10 09:47:34 +00009008{
9009 char_u *instr;
9010 char_u *fromstr;
9011 char_u *tostr;
9012 char_u *p;
9013#ifdef FEAT_MBYTE
9014 int inlen;
9015 int fromlen;
9016 int tolen;
9017 int idx;
9018 char_u *cpstr;
9019 int cplen;
9020 int first = TRUE;
9021#endif
9022 char_u buf[NUMBUFLEN];
9023 char_u buf2[NUMBUFLEN];
9024 garray_T ga;
9025
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009026 instr = get_tv_string(&argvars[0]);
9027 fromstr = get_tv_string_buf(&argvars[1], buf);
9028 tostr = get_tv_string_buf(&argvars[2], buf2);
Bram Moolenaar8299df92004-07-10 09:47:34 +00009029
9030 /* Default return value: empty string. */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009031 rettv->v_type = VAR_STRING;
9032 rettv->vval.v_string = NULL;
Bram Moolenaar8299df92004-07-10 09:47:34 +00009033 ga_init2(&ga, (int)sizeof(char), 80);
9034
9035#ifdef FEAT_MBYTE
9036 if (!has_mbyte)
9037#endif
9038 /* not multi-byte: fromstr and tostr must be the same length */
9039 if (STRLEN(fromstr) != STRLEN(tostr))
9040 {
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00009041#ifdef FEAT_MBYTE
Bram Moolenaar8299df92004-07-10 09:47:34 +00009042error:
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00009043#endif
Bram Moolenaar8299df92004-07-10 09:47:34 +00009044 EMSG2(_(e_invarg2), fromstr);
9045 ga_clear(&ga);
9046 return;
9047 }
9048
9049 /* fromstr and tostr have to contain the same number of chars */
9050 while (*instr != NUL)
9051 {
9052#ifdef FEAT_MBYTE
9053 if (has_mbyte)
9054 {
9055 inlen = mb_ptr2len_check(instr);
9056 cpstr = instr;
9057 cplen = inlen;
9058 idx = 0;
9059 for (p = fromstr; *p != NUL; p += fromlen)
9060 {
9061 fromlen = mb_ptr2len_check(p);
9062 if (fromlen == inlen && STRNCMP(instr, p, inlen) == 0)
9063 {
9064 for (p = tostr; *p != NUL; p += tolen)
9065 {
9066 tolen = mb_ptr2len_check(p);
9067 if (idx-- == 0)
9068 {
9069 cplen = tolen;
9070 cpstr = p;
9071 break;
9072 }
9073 }
9074 if (*p == NUL) /* tostr is shorter than fromstr */
9075 goto error;
9076 break;
9077 }
9078 ++idx;
9079 }
9080
9081 if (first && cpstr == instr)
9082 {
9083 /* Check that fromstr and tostr have the same number of
9084 * (multi-byte) characters. Done only once when a character
9085 * of instr doesn't appear in fromstr. */
9086 first = FALSE;
9087 for (p = tostr; *p != NUL; p += tolen)
9088 {
9089 tolen = mb_ptr2len_check(p);
9090 --idx;
9091 }
9092 if (idx != 0)
9093 goto error;
9094 }
9095
9096 ga_grow(&ga, cplen);
Bram Moolenaar2df6dcc2004-07-12 15:53:54 +00009097 mch_memmove((char *)ga.ga_data + ga.ga_len, cpstr, (size_t)cplen);
Bram Moolenaar8299df92004-07-10 09:47:34 +00009098 ga.ga_len += cplen;
Bram Moolenaar8299df92004-07-10 09:47:34 +00009099
9100 instr += inlen;
9101 }
9102 else
9103#endif
9104 {
9105 /* When not using multi-byte chars we can do it faster. */
9106 p = vim_strchr(fromstr, *instr);
9107 if (p != NULL)
9108 ga_append(&ga, tostr[p - fromstr]);
9109 else
9110 ga_append(&ga, *instr);
9111 ++instr;
9112 }
9113 }
9114
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009115 rettv->vval.v_string = ga.ga_data;
Bram Moolenaar8299df92004-07-10 09:47:34 +00009116}
9117
9118/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00009119 * "type(expr)" function
9120 */
9121 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009122f_type(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009123 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009124 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009125{
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009126 if (argvars[0].v_type == VAR_NUMBER)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009127 rettv->vval.v_number = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009128 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009129 rettv->vval.v_number = 1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009130}
9131
9132/*
9133 * "virtcol(string)" function
9134 */
9135 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009136f_virtcol(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009137 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009138 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009139{
9140 colnr_T vcol = 0;
9141 pos_T *fp;
9142
9143 fp = var2fpos(&argvars[0], FALSE);
9144 if (fp != NULL && fp->lnum <= curbuf->b_ml.ml_line_count)
9145 {
9146 getvvcol(curwin, fp, NULL, NULL, &vcol);
9147 ++vcol;
9148 }
9149
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009150 rettv->vval.v_number = vcol;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009151}
9152
9153/*
9154 * "visualmode()" function
9155 */
9156/*ARGSUSED*/
9157 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009158f_visualmode(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009159 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009160 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009161{
9162#ifdef FEAT_VISUAL
9163 char_u str[2];
9164
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009165 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009166 str[0] = curbuf->b_visual_mode_eval;
9167 str[1] = NUL;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009168 rettv->vval.v_string = vim_strsave(str);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009169
9170 /* A non-zero number or non-empty string argument: reset mode. */
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009171 if ((argvars[0].v_type == VAR_NUMBER
9172 && argvars[0].vval.v_number != 0)
9173 || (argvars[0].v_type == VAR_STRING
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009174 && *get_tv_string(&argvars[0]) != NUL))
Bram Moolenaar071d4272004-06-13 20:20:40 +00009175 curbuf->b_visual_mode_eval = NUL;
9176#else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009177 rettv->vval.v_number = 0; /* return anything, it won't work anyway */
Bram Moolenaar071d4272004-06-13 20:20:40 +00009178#endif
9179}
9180
9181/*
9182 * "winbufnr(nr)" function
9183 */
9184 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009185f_winbufnr(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009186 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009187 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009188{
9189 win_T *wp;
9190
9191 wp = find_win_by_nr(&argvars[0]);
9192 if (wp == NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009193 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009194 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009195 rettv->vval.v_number = wp->w_buffer->b_fnum;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009196}
9197
9198/*
9199 * "wincol()" function
9200 */
9201/*ARGSUSED*/
9202 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009203f_wincol(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009204 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009205 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009206{
9207 validate_cursor();
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009208 rettv->vval.v_number = curwin->w_wcol + 1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009209}
9210
9211/*
9212 * "winheight(nr)" function
9213 */
9214 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009215f_winheight(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009216 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009217 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009218{
9219 win_T *wp;
9220
9221 wp = find_win_by_nr(&argvars[0]);
9222 if (wp == NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009223 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009224 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009225 rettv->vval.v_number = wp->w_height;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009226}
9227
9228/*
9229 * "winline()" function
9230 */
9231/*ARGSUSED*/
9232 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009233f_winline(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009234 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009235 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009236{
9237 validate_cursor();
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009238 rettv->vval.v_number = curwin->w_wrow + 1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009239}
9240
9241/*
9242 * "winnr()" function
9243 */
9244/* ARGSUSED */
9245 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009246f_winnr(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009247 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009248 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009249{
9250 int nr = 1;
9251#ifdef FEAT_WINDOWS
9252 win_T *wp;
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00009253 win_T *twin = curwin;
9254 char_u *arg;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009255
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009256 if (argvars[0].v_type != VAR_UNKNOWN)
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00009257 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009258 arg = get_tv_string(&argvars[0]);
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00009259 if (STRCMP(arg, "$") == 0)
9260 twin = lastwin;
9261 else if (STRCMP(arg, "#") == 0)
9262 {
9263 twin = prevwin;
9264 if (prevwin == NULL)
9265 nr = 0;
9266 }
9267 else
9268 {
9269 EMSG2(_(e_invexpr2), arg);
9270 nr = 0;
9271 }
9272 }
9273
9274 if (nr > 0)
9275 for (wp = firstwin; wp != twin; wp = wp->w_next)
9276 ++nr;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009277#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009278 rettv->vval.v_number = nr;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009279}
9280
9281/*
9282 * "winrestcmd()" function
9283 */
9284/* ARGSUSED */
9285 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009286f_winrestcmd(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009287 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009288 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009289{
9290#ifdef FEAT_WINDOWS
9291 win_T *wp;
9292 int winnr = 1;
9293 garray_T ga;
9294 char_u buf[50];
9295
9296 ga_init2(&ga, (int)sizeof(char), 70);
9297 for (wp = firstwin; wp != NULL; wp = wp->w_next)
9298 {
9299 sprintf((char *)buf, "%dresize %d|", winnr, wp->w_height);
9300 ga_concat(&ga, buf);
9301# ifdef FEAT_VERTSPLIT
9302 sprintf((char *)buf, "vert %dresize %d|", winnr, wp->w_width);
9303 ga_concat(&ga, buf);
9304# endif
9305 ++winnr;
9306 }
Bram Moolenaar269ec652004-07-29 08:43:53 +00009307 ga_append(&ga, NUL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009308
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009309 rettv->vval.v_string = ga.ga_data;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009310#else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009311 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009312#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009313 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009314}
9315
9316/*
9317 * "winwidth(nr)" function
9318 */
9319 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009320f_winwidth(argvars, rettv)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009321 typeval *argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009322 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009323{
9324 win_T *wp;
9325
9326 wp = find_win_by_nr(&argvars[0]);
9327 if (wp == NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009328 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009329 else
9330#ifdef FEAT_VERTSPLIT
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009331 rettv->vval.v_number = wp->w_width;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009332#else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009333 rettv->vval.v_number = Columns;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009334#endif
9335}
9336
9337 static win_T *
9338find_win_by_nr(vp)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009339 typeval *vp;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009340{
9341#ifdef FEAT_WINDOWS
9342 win_T *wp;
9343#endif
9344 int nr;
9345
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009346 nr = get_tv_number(vp);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009347
9348#ifdef FEAT_WINDOWS
9349 if (nr == 0)
9350 return curwin;
9351
9352 for (wp = firstwin; wp != NULL; wp = wp->w_next)
9353 if (--nr <= 0)
9354 break;
9355 return wp;
9356#else
9357 if (nr == 0 || nr == 1)
9358 return curwin;
9359 return NULL;
9360#endif
9361}
9362
9363/*
9364 * Translate a String variable into a position.
9365 */
9366 static pos_T *
9367var2fpos(varp, lnum)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009368 typeval *varp;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009369 int lnum; /* TRUE when $ is last line */
9370{
9371 char_u *name;
9372 static pos_T pos;
9373 pos_T *pp;
9374
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009375 name = get_tv_string(varp);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009376 if (name[0] == '.') /* cursor */
9377 return &curwin->w_cursor;
9378 if (name[0] == '\'') /* mark */
9379 {
9380 pp = getmark(name[1], FALSE);
9381 if (pp == NULL || pp == (pos_T *)-1 || pp->lnum <= 0)
9382 return NULL;
9383 return pp;
9384 }
9385 if (name[0] == '$') /* last column or line */
9386 {
9387 if (lnum)
9388 {
9389 pos.lnum = curbuf->b_ml.ml_line_count;
9390 pos.col = 0;
9391 }
9392 else
9393 {
9394 pos.lnum = curwin->w_cursor.lnum;
9395 pos.col = (colnr_T)STRLEN(ml_get_curline());
9396 }
9397 return &pos;
9398 }
9399 return NULL;
9400}
9401
9402/*
9403 * Get the length of an environment variable name.
9404 * Advance "arg" to the first character after the name.
9405 * Return 0 for error.
9406 */
9407 static int
9408get_env_len(arg)
9409 char_u **arg;
9410{
9411 char_u *p;
9412 int len;
9413
9414 for (p = *arg; vim_isIDc(*p); ++p)
9415 ;
9416 if (p == *arg) /* no name found */
9417 return 0;
9418
9419 len = (int)(p - *arg);
9420 *arg = p;
9421 return len;
9422}
9423
9424/*
9425 * Get the length of the name of a function or internal variable.
9426 * "arg" is advanced to the first non-white character after the name.
9427 * Return 0 if something is wrong.
9428 */
9429 static int
9430get_id_len(arg)
9431 char_u **arg;
9432{
9433 char_u *p;
9434 int len;
9435
9436 /* Find the end of the name. */
9437 for (p = *arg; eval_isnamec(*p); ++p)
9438 ;
9439 if (p == *arg) /* no name found */
9440 return 0;
9441
9442 len = (int)(p - *arg);
9443 *arg = skipwhite(p);
9444
9445 return len;
9446}
9447
9448/*
9449 * Get the length of the name of a function.
9450 * "arg" is advanced to the first non-white character after the name.
9451 * Return 0 if something is wrong.
9452 * If the name contains 'magic' {}'s, expand them and return the
9453 * expanded name in an allocated string via 'alias' - caller must free.
9454 */
9455 static int
9456get_func_len(arg, alias, evaluate)
9457 char_u **arg;
9458 char_u **alias;
9459 int evaluate;
9460{
9461 int len;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009462 char_u *p;
9463 char_u *expr_start;
9464 char_u *expr_end;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009465
9466 *alias = NULL; /* default to no alias */
9467
9468 if ((*arg)[0] == K_SPECIAL && (*arg)[1] == KS_EXTRA
9469 && (*arg)[2] == (int)KE_SNR)
9470 {
9471 /* hard coded <SNR>, already translated */
9472 *arg += 3;
9473 return get_id_len(arg) + 3;
9474 }
9475 len = eval_fname_script(*arg);
9476 if (len > 0)
9477 {
9478 /* literal "<SID>", "s:" or "<SNR>" */
9479 *arg += len;
9480 }
9481
Bram Moolenaar071d4272004-06-13 20:20:40 +00009482 /*
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009483 * Find the end of the name; check for {} construction.
Bram Moolenaar071d4272004-06-13 20:20:40 +00009484 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009485 p = find_name_end(*arg, &expr_start, &expr_end, FALSE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009486 if (expr_start != NULL)
9487 {
9488 char_u *temp_string;
9489
9490 if (!evaluate)
9491 {
9492 len += (int)(p - *arg);
9493 *arg = skipwhite(p);
9494 return len;
9495 }
9496
9497 /*
9498 * Include any <SID> etc in the expanded string:
9499 * Thus the -len here.
9500 */
9501 temp_string = make_expanded_name(*arg - len, expr_start, expr_end, p);
9502 if (temp_string == NULL)
9503 return 0;
9504 *alias = temp_string;
9505 *arg = skipwhite(p);
9506 return (int)STRLEN(temp_string);
9507 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00009508
9509 len += get_id_len(arg);
9510 if (len == 0)
9511 EMSG2(_(e_invexpr2), *arg);
9512
9513 return len;
9514}
9515
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009516/*
9517 * Find the end of a variable or function name, taking care of magic braces.
9518 * If "expr_start" is not NULL then "expr_start" and "expr_end" are set to the
9519 * start and end of the first magic braces item.
9520 * Return a pointer to just after the name. Equal to "arg" if there is no
9521 * valid name.
9522 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00009523 static char_u *
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009524find_name_end(arg, expr_start, expr_end, incl_br)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009525 char_u *arg;
9526 char_u **expr_start;
9527 char_u **expr_end;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009528 int incl_br; /* Include [] indexes */
Bram Moolenaar071d4272004-06-13 20:20:40 +00009529{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009530 int mb_nest = 0;
9531 int br_nest = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009532 char_u *p;
9533
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009534 if (expr_start != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009535 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009536 *expr_start = NULL;
9537 *expr_end = NULL;
9538 }
9539
9540 for (p = arg; *p != NUL
9541 && (eval_isnamec(*p)
9542 || (*p == '[' && incl_br)
9543 || mb_nest != 0
9544 || br_nest != 0); ++p)
9545 {
9546 if (mb_nest == 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009547 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009548 if (*p == '[')
9549 ++br_nest;
9550 else if (*p == ']')
9551 --br_nest;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009552 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009553 if (br_nest == 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009554 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009555 if (*p == '{')
9556 {
9557 mb_nest++;
9558 if (expr_start != NULL && *expr_start == NULL)
9559 *expr_start = p;
9560 }
9561 else if (*p == '}')
9562 {
9563 mb_nest--;
9564 if (expr_start != NULL && mb_nest == 0 && *expr_end == NULL)
9565 *expr_end = p;
9566 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00009567 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00009568 }
9569
9570 return p;
9571}
9572
9573/*
9574 * Return TRUE if character "c" can be used in a variable or function name.
9575 */
9576 static int
9577eval_isnamec(c)
9578 int c;
9579{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009580 return (ASCII_ISALNUM(c) || c == '_' || c == ':' || c == '{' || c == '}');
Bram Moolenaar071d4272004-06-13 20:20:40 +00009581}
9582
9583/*
9584 * Find a v: variable.
9585 * Return it's index, or -1 if not found.
9586 */
9587 static int
9588find_vim_var(name, len)
9589 char_u *name;
9590 int len; /* length of "name" */
9591{
9592 char_u *vname;
9593 int vlen;
9594 int i;
9595
9596 /*
9597 * Ignore "v:" for old built-in variables, require it for new ones.
9598 */
9599 if (name[0] == 'v' && name[1] == ':')
9600 {
9601 vname = name + 2;
9602 vlen = len - 2;
9603 }
9604 else
9605 {
9606 vname = name;
9607 vlen = len;
9608 }
9609 for (i = 0; i < VV_LEN; ++i)
9610 if (vlen == vimvars[i].len && STRCMP(vname, vimvars[i].name) == 0
9611 && ((vimvars[i].flags & VV_COMPAT) || vname != name))
9612 return i;
9613 return -1;
9614}
9615
9616/*
9617 * Set number v: variable to "val".
9618 */
9619 void
9620set_vim_var_nr(idx, val)
9621 int idx;
9622 long val;
9623{
9624 vimvars[idx].val = (char_u *)val;
9625}
9626
9627/*
9628 * Get number v: variable value;
9629 */
9630 long
9631get_vim_var_nr(idx)
9632 int idx;
9633{
9634 return (long)vimvars[idx].val;
9635}
9636
9637/*
9638 * Set v:count, v:count1 and v:prevcount.
9639 */
9640 void
9641set_vcount(count, count1)
9642 long count;
9643 long count1;
9644{
9645 vimvars[VV_PREVCOUNT].val = vimvars[VV_COUNT].val;
9646 vimvars[VV_COUNT].val = (char_u *)count;
9647 vimvars[VV_COUNT1].val = (char_u *)count1;
9648}
9649
9650/*
9651 * Set string v: variable to a copy of "val".
9652 */
9653 void
9654set_vim_var_string(idx, val, len)
9655 int idx;
9656 char_u *val;
9657 int len; /* length of "val" to use or -1 (whole string) */
9658{
9659 vim_free(vimvars[idx].val);
9660 if (val == NULL)
9661 vimvars[idx].val = NULL;
9662 else if (len == -1)
9663 vimvars[idx].val = vim_strsave(val);
9664 else
9665 vimvars[idx].val = vim_strnsave(val, len);
9666}
9667
9668/*
9669 * Set v:register if needed.
9670 */
9671 void
9672set_reg_var(c)
9673 int c;
9674{
9675 char_u regname;
9676
9677 if (c == 0 || c == ' ')
9678 regname = '"';
9679 else
9680 regname = c;
9681 /* Avoid free/alloc when the value is already right. */
9682 if (vimvars[VV_REG].val == NULL || vimvars[VV_REG].val[0] != c)
9683 set_vim_var_string(VV_REG, &regname, 1);
9684}
9685
9686/*
9687 * Get or set v:exception. If "oldval" == NULL, return the current value.
9688 * Otherwise, restore the value to "oldval" and return NULL.
9689 * Must always be called in pairs to save and restore v:exception! Does not
9690 * take care of memory allocations.
9691 */
9692 char_u *
9693v_exception(oldval)
9694 char_u *oldval;
9695{
9696 if (oldval == NULL)
9697 return vimvars[VV_EXCEPTION].val;
9698
9699 vimvars[VV_EXCEPTION].val = oldval;
9700 return NULL;
9701}
9702
9703/*
9704 * Get or set v:throwpoint. If "oldval" == NULL, return the current value.
9705 * Otherwise, restore the value to "oldval" and return NULL.
9706 * Must always be called in pairs to save and restore v:throwpoint! Does not
9707 * take care of memory allocations.
9708 */
9709 char_u *
9710v_throwpoint(oldval)
9711 char_u *oldval;
9712{
9713 if (oldval == NULL)
9714 return vimvars[VV_THROWPOINT].val;
9715
9716 vimvars[VV_THROWPOINT].val = oldval;
9717 return NULL;
9718}
9719
9720#if defined(FEAT_AUTOCMD) || defined(PROTO)
9721/*
9722 * Set v:cmdarg.
9723 * If "eap" != NULL, use "eap" to generate the value and return the old value.
9724 * If "oldarg" != NULL, restore the value to "oldarg" and return NULL.
9725 * Must always be called in pairs!
9726 */
9727 char_u *
9728set_cmdarg(eap, oldarg)
9729 exarg_T *eap;
9730 char_u *oldarg;
9731{
9732 char_u *oldval;
9733 char_u *newval;
9734 unsigned len;
9735
9736 oldval = vimvars[VV_CMDARG].val;
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +00009737 if (eap == NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009738 {
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +00009739 vim_free(oldval);
9740 vimvars[VV_CMDARG].val = oldarg;
9741 return NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009742 }
9743
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +00009744 if (eap->force_bin == FORCE_BIN)
9745 len = 6;
9746 else if (eap->force_bin == FORCE_NOBIN)
9747 len = 8;
9748 else
9749 len = 0;
9750 if (eap->force_ff != 0)
9751 len += (unsigned)STRLEN(eap->cmd + eap->force_ff) + 6;
9752# ifdef FEAT_MBYTE
9753 if (eap->force_enc != 0)
9754 len += (unsigned)STRLEN(eap->cmd + eap->force_enc) + 7;
9755# endif
9756
9757 newval = alloc(len + 1);
9758 if (newval == NULL)
9759 return NULL;
9760
9761 if (eap->force_bin == FORCE_BIN)
9762 sprintf((char *)newval, " ++bin");
9763 else if (eap->force_bin == FORCE_NOBIN)
9764 sprintf((char *)newval, " ++nobin");
9765 else
9766 *newval = NUL;
9767 if (eap->force_ff != 0)
9768 sprintf((char *)newval + STRLEN(newval), " ++ff=%s",
9769 eap->cmd + eap->force_ff);
9770# ifdef FEAT_MBYTE
9771 if (eap->force_enc != 0)
9772 sprintf((char *)newval + STRLEN(newval), " ++enc=%s",
9773 eap->cmd + eap->force_enc);
9774# endif
9775 vimvars[VV_CMDARG].val = newval;
9776 return oldval;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009777}
9778#endif
9779
9780/*
9781 * Get the value of internal variable "name".
9782 * Return OK or FAIL.
9783 */
9784 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009785get_var_tv(name, len, rettv)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009786 char_u *name;
9787 int len; /* length of "name" */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009788 typeval *rettv; /* NULL when only checking existence */
Bram Moolenaar071d4272004-06-13 20:20:40 +00009789{
9790 int ret = OK;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009791 typeval tv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009792 VAR v;
9793 int cc;
9794 int i;
9795
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009796 tv.v_type = VAR_UNKNOWN;
9797
Bram Moolenaar071d4272004-06-13 20:20:40 +00009798 /* truncate the name, so that we can use strcmp() */
9799 cc = name[len];
9800 name[len] = NUL;
9801
9802 /*
9803 * Check for "b:changedtick".
9804 */
9805 if (STRCMP(name, "b:changedtick") == 0)
9806 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009807 tv.v_type = VAR_NUMBER;
9808 tv.vval.v_number = curbuf->b_changedtick;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009809 }
9810
9811 /*
9812 * Check for built-in v: variables.
9813 */
9814 else if ((i = find_vim_var(name, len)) >= 0)
9815 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009816 tv.v_type = vimvars[i].type;
9817 if (tv.v_type == VAR_NUMBER)
9818 tv.vval.v_number = (long)vimvars[i].val;
9819 else
9820 tv.vval.v_string = vimvars[i].val;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009821 }
9822
9823 /*
9824 * Check for user-defined variables.
9825 */
9826 else
9827 {
9828 v = find_var(name, FALSE);
9829 if (v != NULL)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009830 tv = v->tv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009831 }
9832
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009833 if (tv.v_type == VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009834 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009835 if (rettv != NULL)
9836 EMSG2(_(e_undefvar), name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009837 ret = FAIL;
9838 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009839 else if (rettv != NULL)
9840 copy_tv(&tv, rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009841
9842 name[len] = cc;
9843
9844 return ret;
9845}
9846
9847/*
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009848 * Allocate memory for a variable type-value, and make it emtpy (0 or NULL
9849 * value).
9850 */
9851 static typeval *
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009852alloc_tv()
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009853{
9854 return (typeval *)alloc_clear((unsigned)sizeof(typeval));
9855}
9856
9857/*
9858 * Allocate memory for a variable type-value, and assign a string to it.
Bram Moolenaar071d4272004-06-13 20:20:40 +00009859 * The string "s" must have been allocated, it is consumed.
9860 * Return NULL for out of memory, the variable otherwise.
9861 */
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009862 static typeval *
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009863alloc_string_tv(s)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009864 char_u *s;
9865{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009866 typeval *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009867
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009868 rettv = alloc_tv();
9869 if (rettv != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009870 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009871 rettv->v_type = VAR_STRING;
9872 rettv->vval.v_string = s;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009873 }
9874 else
9875 vim_free(s);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009876 return rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009877}
9878
9879/*
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009880 * Free the memory for a variable type-value.
Bram Moolenaar071d4272004-06-13 20:20:40 +00009881 */
9882 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009883free_tv(varp)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009884 typeval *varp;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009885{
9886 if (varp != NULL)
9887 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009888 switch (varp->v_type)
9889 {
9890 case VAR_STRING:
9891 case VAR_FUNC:
9892 vim_free(varp->vval.v_string);
9893 break;
9894 case VAR_LIST:
9895 list_unref(varp->vval.v_list);
9896 break;
9897 default:
9898 break;
9899 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00009900 vim_free(varp);
9901 }
9902}
9903
9904/*
9905 * Free the memory for a variable value and set the value to NULL or 0.
9906 */
9907 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009908clear_tv(varp)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009909 typeval *varp;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009910{
9911 if (varp != NULL)
9912 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009913 switch (varp->v_type)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009914 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009915 case VAR_STRING:
9916 case VAR_FUNC:
9917 vim_free(varp->vval.v_string);
9918 varp->vval.v_string = NULL;
9919 break;
9920 case VAR_LIST:
9921 list_unref(varp->vval.v_list);
9922 break;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009923 case VAR_NUMBER:
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009924 varp->vval.v_number = 0;
9925 break;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009926 case VAR_UNKNOWN:
9927 break;
9928 default:
9929 EMSG2(_(e_intern2), "clear_tv()");
Bram Moolenaar071d4272004-06-13 20:20:40 +00009930 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00009931 }
9932}
9933
9934/*
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009935 * Set the value of a variable to NULL without freeing items.
9936 */
9937 static void
9938init_tv(varp)
9939 typeval *varp;
9940{
9941 if (varp != NULL)
9942 vim_memset(varp, 0, sizeof(typeval));
9943}
9944
9945/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00009946 * Get the number value of a variable.
9947 * If it is a String variable, uses vim_str2nr().
9948 */
9949 static long
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009950get_tv_number(varp)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009951 typeval *varp;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009952{
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009953 long n = 0L;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009954
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009955 switch (varp->v_type)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009956 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009957 case VAR_NUMBER:
9958 n = (long)(varp->vval.v_number);
9959 break;
9960 case VAR_FUNC:
9961 EMSG(_("E999: Using function reference as a number"));
9962 break;
9963 case VAR_STRING:
9964 if (varp->vval.v_string != NULL)
9965 vim_str2nr(varp->vval.v_string, NULL, NULL,
9966 TRUE, TRUE, &n, NULL);
9967 break;
9968 default:
9969 break;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009970 }
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009971 return n;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009972}
9973
9974/*
9975 * Get the lnum from the first argument. Also accepts ".", "$", etc.
9976 */
9977 static linenr_T
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009978get_tv_lnum(argvars)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009979 typeval *argvars;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009980{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009981 typeval rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009982 linenr_T lnum;
9983
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009984 lnum = get_tv_number(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009985 if (lnum == 0) /* no valid number, try using line() */
9986 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009987 rettv.v_type = VAR_NUMBER;
9988 f_line(argvars, &rettv);
9989 lnum = rettv.vval.v_number;
9990 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009991 }
9992 return lnum;
9993}
9994
9995/*
9996 * Get the string value of a variable.
9997 * If it is a Number variable, the number is converted into a string.
9998 * get_var_string() uses a single, static buffer. YOU CAN ONLY USE IT ONCE!
9999 * get_var_string_buf() uses a given buffer.
10000 * If the String variable has never been set, return an empty string.
10001 * Never returns NULL;
10002 */
10003 static char_u *
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010004get_tv_string(varp)
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010005 typeval *varp;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010006{
10007 static char_u mybuf[NUMBUFLEN];
10008
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010009 return get_tv_string_buf(varp, mybuf);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010010}
10011
10012 static char_u *
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010013get_tv_string_buf(varp, buf)
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010014 typeval *varp;
10015 char_u *buf;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010016{
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010017 switch (varp->v_type)
Bram Moolenaar071d4272004-06-13 20:20:40 +000010018 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010019 case VAR_NUMBER:
10020 sprintf((char *)buf, "%ld", (long)varp->vval.v_number);
10021 return buf;
10022 case VAR_FUNC:
10023 EMSG(_("E99: using Funcref as a String"));
10024 break;
10025 case VAR_LIST:
10026 EMSG(_("E99: using List as a String"));
10027 break;
10028 case VAR_STRING:
10029 if (varp->vval.v_string != NULL)
10030 return varp->vval.v_string;
10031 break;
10032 default:
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010033 EMSG2(_(e_intern2), "get_tv_string_buf()");
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010034 break;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010035 }
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010036 return (char_u *)"";
Bram Moolenaar071d4272004-06-13 20:20:40 +000010037}
10038
10039/*
10040 * Find variable "name" in the list of variables.
10041 * Return a pointer to it if found, NULL if not found.
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010042 * Careful: "a:0" variables don't have a name.
Bram Moolenaar071d4272004-06-13 20:20:40 +000010043 */
10044 static VAR
10045find_var(name, writing)
10046 char_u *name;
10047 int writing;
10048{
10049 int i;
10050 char_u *varname;
10051 garray_T *gap;
10052
Bram Moolenaar071d4272004-06-13 20:20:40 +000010053 if (name[0] == 'a' && name[1] == ':')
10054 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010055 /* Function arguments "a:".
10056 * NOTE: We use a typecast, because function arguments don't have a
10057 * name. The caller must not try to access the name! */
Bram Moolenaar071d4272004-06-13 20:20:40 +000010058 if (writing)
10059 {
10060 EMSG2(_(e_readonlyvar), name);
10061 return NULL;
10062 }
10063 name += 2;
10064 if (current_funccal == NULL)
10065 return NULL;
10066 if (VIM_ISDIGIT(*name))
10067 {
10068 i = atol((char *)name);
10069 if (i == 0) /* a:0 */
10070 return &current_funccal->a0_var;
10071 i += current_funccal->func->args.ga_len;
10072 if (i > current_funccal->argcount) /* a:999 */
10073 return NULL;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010074 return (VAR)&(current_funccal->argvars[i - 1]); /* a:1, a:2, etc. */
Bram Moolenaar071d4272004-06-13 20:20:40 +000010075 }
10076 if (STRCMP(name, "firstline") == 0)
10077 return &(current_funccal->firstline);
10078 if (STRCMP(name, "lastline") == 0)
10079 return &(current_funccal->lastline);
10080 for (i = 0; i < current_funccal->func->args.ga_len; ++i)
10081 if (STRCMP(name, ((char_u **)
10082 (current_funccal->func->args.ga_data))[i]) == 0)
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010083 return (VAR)&(current_funccal->argvars[i]); /* a:name */
Bram Moolenaar071d4272004-06-13 20:20:40 +000010084 return NULL;
10085 }
10086
10087 gap = find_var_ga(name, &varname);
10088 if (gap == NULL)
10089 return NULL;
10090 return find_var_in_ga(gap, varname);
10091}
10092
10093 static VAR
10094find_var_in_ga(gap, varname)
10095 garray_T *gap;
10096 char_u *varname;
10097{
10098 int i;
10099
10100 for (i = gap->ga_len; --i >= 0; )
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010101 if (VAR_GAP_ENTRY(i, gap).v_name != NULL
10102 && STRCMP(VAR_GAP_ENTRY(i, gap).v_name, varname) == 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +000010103 break;
10104 if (i < 0)
10105 return NULL;
10106 return &VAR_GAP_ENTRY(i, gap);
10107}
10108
10109/*
10110 * Find the growarray and start of name without ':' for a variable name.
10111 */
10112 static garray_T *
10113find_var_ga(name, varname)
10114 char_u *name;
10115 char_u **varname;
10116{
10117 if (name[1] != ':')
10118 {
10119 /* If not "x:name" there must not be any ":" in the name. */
10120 if (vim_strchr(name, ':') != NULL)
10121 return NULL;
10122 *varname = name;
10123 if (current_funccal == NULL)
10124 return &variables; /* global variable */
10125 return &current_funccal->l_vars; /* local function variable */
10126 }
10127 *varname = name + 2;
10128 if (*name == 'b') /* buffer variable */
10129 return &curbuf->b_vars;
10130 if (*name == 'w') /* window variable */
10131 return &curwin->w_vars;
10132 if (*name == 'g') /* global variable */
10133 return &variables;
10134 if (*name == 'l' && current_funccal != NULL)/* local function variable */
10135 return &current_funccal->l_vars;
10136 if (*name == 's' /* script variable */
10137 && current_SID > 0 && current_SID <= ga_scripts.ga_len)
10138 return &SCRIPT_VARS(current_SID);
10139 return NULL;
10140}
10141
10142/*
10143 * Get the string value of a (global/local) variable.
10144 * Returns NULL when it doesn't exist.
10145 */
10146 char_u *
10147get_var_value(name)
10148 char_u *name;
10149{
10150 VAR v;
10151
10152 v = find_var(name, FALSE);
10153 if (v == NULL)
10154 return NULL;
10155 return get_var_string(v);
10156}
10157
10158/*
10159 * Allocate a new growarry for a sourced script. It will be used while
10160 * sourcing this script and when executing functions defined in the script.
10161 */
10162 void
10163new_script_vars(id)
10164 scid_T id;
10165{
10166 if (ga_grow(&ga_scripts, (int)(id - ga_scripts.ga_len)) == OK)
10167 {
10168 while (ga_scripts.ga_len < id)
10169 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010170 vars_init(&SCRIPT_VARS(ga_scripts.ga_len + 1));
Bram Moolenaar071d4272004-06-13 20:20:40 +000010171 ++ga_scripts.ga_len;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010172 }
10173 }
10174}
10175
10176/*
10177 * Initialize internal variables for use.
10178 */
10179 void
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010180vars_init(gap)
Bram Moolenaar071d4272004-06-13 20:20:40 +000010181 garray_T *gap;
10182{
10183 ga_init2(gap, (int)sizeof(var), 4);
10184}
10185
10186/*
10187 * Clean up a list of internal variables.
10188 */
10189 void
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010190vars_clear(gap)
Bram Moolenaar071d4272004-06-13 20:20:40 +000010191 garray_T *gap;
10192{
10193 int i;
10194
10195 for (i = gap->ga_len; --i >= 0; )
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010196 clear_var(&VAR_GAP_ENTRY(i, gap));
Bram Moolenaar071d4272004-06-13 20:20:40 +000010197 ga_clear(gap);
10198}
10199
10200 static void
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010201clear_var(v)
Bram Moolenaar071d4272004-06-13 20:20:40 +000010202 VAR v;
10203{
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010204 vim_free(v->v_name);
10205 v->v_name = NULL;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010206 clear_tv(&v->tv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010207}
10208
10209/*
10210 * List the value of one internal variable.
10211 */
10212 static void
10213list_one_var(v, prefix)
10214 VAR v;
10215 char_u *prefix;
10216{
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010217 char_u *tofree;
10218 char_u *s;
10219
10220 s = tv2string(&v->tv, &tofree);
10221 list_one_var_a(prefix, v->v_name, v->tv.v_type,
10222 s == NULL ? (char_u *)"" : s);
10223 vim_free(tofree);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010224}
10225
10226/*
10227 * List the value of one "v:" variable.
10228 */
10229 static void
10230list_vim_var(i)
10231 int i; /* index in vimvars[] */
10232{
10233 char_u *p;
10234 char_u numbuf[NUMBUFLEN];
10235
10236 if (vimvars[i].type == VAR_NUMBER)
10237 {
10238 p = numbuf;
10239 sprintf((char *)p, "%ld", (long)vimvars[i].val);
10240 }
10241 else if (vimvars[i].val == NULL)
10242 p = (char_u *)"";
10243 else
10244 p = vimvars[i].val;
10245 list_one_var_a((char_u *)"v:", (char_u *)vimvars[i].name,
10246 vimvars[i].type, p);
10247}
10248
10249 static void
10250list_one_var_a(prefix, name, type, string)
10251 char_u *prefix;
10252 char_u *name;
10253 int type;
10254 char_u *string;
10255{
10256 msg_attr(prefix, 0); /* don't use msg(), it overwrites "v:statusmsg" */
10257 if (name != NULL) /* "a:" vars don't have a name stored */
10258 msg_puts(name);
10259 msg_putchar(' ');
10260 msg_advance(22);
10261 if (type == VAR_NUMBER)
10262 msg_putchar('#');
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010263 else if (type == VAR_FUNC)
10264 msg_putchar('*');
10265 else if (type == VAR_LIST)
10266 {
10267 msg_putchar('[');
10268 if (*string == '[')
10269 ++string;
10270 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000010271 else
10272 msg_putchar(' ');
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010273
Bram Moolenaar071d4272004-06-13 20:20:40 +000010274 msg_outtrans(string);
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010275
10276 if (type == VAR_FUNC)
10277 msg_puts((char_u *)"()");
Bram Moolenaar071d4272004-06-13 20:20:40 +000010278}
10279
10280/*
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010281 * Set variable "name" to value in "tv".
Bram Moolenaar071d4272004-06-13 20:20:40 +000010282 * If the variable already exists, the value is updated.
10283 * Otherwise the variable is created.
10284 */
10285 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010286set_var(name, tv, copy)
Bram Moolenaar071d4272004-06-13 20:20:40 +000010287 char_u *name;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010288 typeval *tv;
10289 int copy; /* make copy of value in "tv" */
Bram Moolenaar071d4272004-06-13 20:20:40 +000010290{
10291 int i;
10292 VAR v;
10293 char_u *varname;
10294 garray_T *gap;
10295
10296 /*
10297 * Handle setting internal v: variables.
10298 */
10299 i = find_vim_var(name, (int)STRLEN(name));
10300 if (i >= 0)
10301 {
10302 if (vimvars[i].flags & VV_RO)
10303 EMSG2(_(e_readonlyvar), name);
Bram Moolenaar7b0294c2004-10-11 10:16:09 +000010304 else if ((vimvars[i].flags & VV_RO_SBX) && sandbox)
10305 EMSG2(_(e_readonlysbx), name);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010306 else
10307 {
10308 if (vimvars[i].type == VAR_STRING)
10309 {
10310 vim_free(vimvars[i].val);
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010311 if (copy || tv->v_type != VAR_STRING)
10312 vimvars[i].val = vim_strsave(get_tv_string(tv));
Bram Moolenaar1c2fda22005-01-02 11:43:19 +000010313 else
10314 {
10315 /* Take over the string to avoid an extra alloc/free. */
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010316 vimvars[i].val = tv->vval.v_string;
10317 tv->vval.v_string = NULL;
Bram Moolenaar1c2fda22005-01-02 11:43:19 +000010318 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000010319 }
10320 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010321 vimvars[i].val = (char_u *)get_tv_number(tv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010322 }
10323 return;
10324 }
10325
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010326 if (tv->v_type == VAR_FUNC)
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010327 {
10328 if (!(vim_strchr((char_u *)"wbs", name[0]) != NULL && name[1] == ':')
10329 && !ASCII_ISUPPER((name[0] != NUL && name[1] == ':')
10330 ? name[2] : name[0]))
10331 {
10332 EMSG2(_("E999: Funcref variable name must start with a capital: %s"), name);
10333 return;
10334 }
10335 if (function_exists(name))
10336 {
10337 EMSG2(_("E999: Variable name conflicts with existing function: %s"), name);
10338 return;
10339 }
10340 }
10341
Bram Moolenaar071d4272004-06-13 20:20:40 +000010342 v = find_var(name, TRUE);
10343 if (v != NULL) /* existing variable, only need to free string */
10344 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010345 if (v->tv.v_type != tv->v_type
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010346 && !((v->tv.v_type == VAR_STRING
10347 || v->tv.v_type == VAR_NUMBER)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010348 && (tv->v_type == VAR_STRING
10349 || tv->v_type == VAR_NUMBER)))
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010350 {
10351 EMSG2(_("E999: Variable type mismatch for: %s"), name);
10352 return;
10353 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010354 clear_tv(&v->tv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010355 }
10356 else /* add a new variable */
10357 {
10358 gap = find_var_ga(name, &varname);
10359 if (gap == NULL) /* illegal name */
10360 {
10361 EMSG2(_("E461: Illegal variable name: %s"), name);
10362 return;
10363 }
10364
10365 /* Try to use an empty entry */
10366 for (i = gap->ga_len; --i >= 0; )
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010367 if (VAR_GAP_ENTRY(i, gap).v_name == NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000010368 break;
10369 if (i < 0) /* need to allocate more room */
10370 {
10371 if (ga_grow(gap, 1) == FAIL)
10372 return;
10373 i = gap->ga_len;
10374 }
10375 v = &VAR_GAP_ENTRY(i, gap);
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010376 if ((v->v_name = vim_strsave(varname)) == NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000010377 return;
10378 if (i == gap->ga_len)
Bram Moolenaar071d4272004-06-13 20:20:40 +000010379 ++gap->ga_len;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010380 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010381 if (copy || tv->v_type == VAR_NUMBER)
10382 copy_tv(tv, &v->tv);
Bram Moolenaar1c2fda22005-01-02 11:43:19 +000010383 else
10384 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010385 v->tv = *tv;
10386 init_tv(tv);
Bram Moolenaar1c2fda22005-01-02 11:43:19 +000010387 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000010388}
10389
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010390/*
10391 * Copy the values from typeval "from" to typeval "to".
10392 * When needed allocates string or increases reference count.
10393 * Does not make a copy of a list!
10394 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000010395 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010396copy_tv(from, to)
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010397 typeval *from;
10398 typeval *to;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010399{
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010400 to->v_type = from->v_type;
10401 switch (from->v_type)
10402 {
10403 case VAR_NUMBER:
10404 to->vval.v_number = from->vval.v_number;
10405 break;
10406 case VAR_STRING:
10407 case VAR_FUNC:
10408 if (from->vval.v_string == NULL)
10409 to->vval.v_string = NULL;
10410 else
10411 to->vval.v_string = vim_strsave(from->vval.v_string);
10412 break;
10413 case VAR_LIST:
10414 if (from->vval.v_list == NULL)
10415 to->vval.v_list = NULL;
10416 else
10417 {
10418 to->vval.v_list = from->vval.v_list;
10419 ++to->vval.v_list->lv_refcount;
10420 }
10421 break;
10422 default:
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010423 EMSG2(_(e_intern2), "copy_tv()");
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010424 break;
10425 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000010426}
10427
10428/*
10429 * ":echo expr1 ..." print each argument separated with a space, add a
10430 * newline at the end.
10431 * ":echon expr1 ..." print each argument plain.
10432 */
10433 void
10434ex_echo(eap)
10435 exarg_T *eap;
10436{
10437 char_u *arg = eap->arg;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010438 typeval rettv;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010439 char_u *tofree;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010440 char_u *p;
10441 int needclr = TRUE;
10442 int atstart = TRUE;
10443
10444 if (eap->skip)
10445 ++emsg_skip;
10446 while (*arg != NUL && *arg != '|' && *arg != '\n' && !got_int)
10447 {
10448 p = arg;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010449 if (eval1(&arg, &rettv, !eap->skip) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000010450 {
10451 /*
10452 * Report the invalid expression unless the expression evaluation
10453 * has been cancelled due to an aborting error, an interrupt, or an
10454 * exception.
10455 */
10456 if (!aborting())
10457 EMSG2(_(e_invexpr2), p);
10458 break;
10459 }
10460 if (!eap->skip)
10461 {
10462 if (atstart)
10463 {
10464 atstart = FALSE;
10465 /* Call msg_start() after eval1(), evaluating the expression
10466 * may cause a message to appear. */
10467 if (eap->cmdidx == CMD_echo)
10468 msg_start();
10469 }
10470 else if (eap->cmdidx == CMD_echo)
10471 msg_puts_attr((char_u *)" ", echo_attr);
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010472 for (p = tv2string(&rettv, &tofree); *p != NUL && !got_int; ++p)
Bram Moolenaar071d4272004-06-13 20:20:40 +000010473 if (*p == '\n' || *p == '\r' || *p == TAB)
10474 {
10475 if (*p != TAB && needclr)
10476 {
10477 /* remove any text still there from the command */
10478 msg_clr_eos();
10479 needclr = FALSE;
10480 }
10481 msg_putchar_attr(*p, echo_attr);
10482 }
10483 else
10484 {
10485#ifdef FEAT_MBYTE
10486 if (has_mbyte)
10487 {
10488 int i = (*mb_ptr2len_check)(p);
10489
10490 (void)msg_outtrans_len_attr(p, i, echo_attr);
10491 p += i - 1;
10492 }
10493 else
10494#endif
10495 (void)msg_outtrans_len_attr(p, 1, echo_attr);
10496 }
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010497 vim_free(tofree);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010498 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010499 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010500 arg = skipwhite(arg);
10501 }
10502 eap->nextcmd = check_nextcmd(arg);
10503
10504 if (eap->skip)
10505 --emsg_skip;
10506 else
10507 {
10508 /* remove text that may still be there from the command */
10509 if (needclr)
10510 msg_clr_eos();
10511 if (eap->cmdidx == CMD_echo)
10512 msg_end();
10513 }
10514}
10515
10516/*
10517 * ":echohl {name}".
10518 */
10519 void
10520ex_echohl(eap)
10521 exarg_T *eap;
10522{
10523 int id;
10524
10525 id = syn_name2id(eap->arg);
10526 if (id == 0)
10527 echo_attr = 0;
10528 else
10529 echo_attr = syn_id2attr(id);
10530}
10531
10532/*
10533 * ":execute expr1 ..." execute the result of an expression.
10534 * ":echomsg expr1 ..." Print a message
10535 * ":echoerr expr1 ..." Print an error
10536 * Each gets spaces around each argument and a newline at the end for
10537 * echo commands
10538 */
10539 void
10540ex_execute(eap)
10541 exarg_T *eap;
10542{
10543 char_u *arg = eap->arg;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010544 typeval rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010545 int ret = OK;
10546 char_u *p;
10547 garray_T ga;
10548 int len;
10549 int save_did_emsg;
10550
10551 ga_init2(&ga, 1, 80);
10552
10553 if (eap->skip)
10554 ++emsg_skip;
10555 while (*arg != NUL && *arg != '|' && *arg != '\n')
10556 {
10557 p = arg;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010558 if (eval1(&arg, &rettv, !eap->skip) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000010559 {
10560 /*
10561 * Report the invalid expression unless the expression evaluation
10562 * has been cancelled due to an aborting error, an interrupt, or an
10563 * exception.
10564 */
10565 if (!aborting())
10566 EMSG2(_(e_invexpr2), p);
10567 ret = FAIL;
10568 break;
10569 }
10570
10571 if (!eap->skip)
10572 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010573 p = get_tv_string(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010574 len = (int)STRLEN(p);
10575 if (ga_grow(&ga, len + 2) == FAIL)
10576 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010577 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010578 ret = FAIL;
10579 break;
10580 }
10581 if (ga.ga_len)
Bram Moolenaar071d4272004-06-13 20:20:40 +000010582 ((char_u *)(ga.ga_data))[ga.ga_len++] = ' ';
Bram Moolenaar071d4272004-06-13 20:20:40 +000010583 STRCPY((char_u *)(ga.ga_data) + ga.ga_len, p);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010584 ga.ga_len += len;
10585 }
10586
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010587 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010588 arg = skipwhite(arg);
10589 }
10590
10591 if (ret != FAIL && ga.ga_data != NULL)
10592 {
10593 if (eap->cmdidx == CMD_echomsg)
10594 MSG_ATTR(ga.ga_data, echo_attr);
10595 else if (eap->cmdidx == CMD_echoerr)
10596 {
10597 /* We don't want to abort following commands, restore did_emsg. */
10598 save_did_emsg = did_emsg;
10599 EMSG((char_u *)ga.ga_data);
10600 if (!force_abort)
10601 did_emsg = save_did_emsg;
10602 }
10603 else if (eap->cmdidx == CMD_execute)
10604 do_cmdline((char_u *)ga.ga_data,
10605 eap->getline, eap->cookie, DOCMD_NOWAIT|DOCMD_VERBOSE);
10606 }
10607
10608 ga_clear(&ga);
10609
10610 if (eap->skip)
10611 --emsg_skip;
10612
10613 eap->nextcmd = check_nextcmd(arg);
10614}
10615
10616/*
10617 * Skip over the name of an option: "&option", "&g:option" or "&l:option".
10618 * "arg" points to the "&" or '+' when called, to "option" when returning.
10619 * Returns NULL when no option name found. Otherwise pointer to the char
10620 * after the option name.
10621 */
10622 static char_u *
10623find_option_end(arg, opt_flags)
10624 char_u **arg;
10625 int *opt_flags;
10626{
10627 char_u *p = *arg;
10628
10629 ++p;
10630 if (*p == 'g' && p[1] == ':')
10631 {
10632 *opt_flags = OPT_GLOBAL;
10633 p += 2;
10634 }
10635 else if (*p == 'l' && p[1] == ':')
10636 {
10637 *opt_flags = OPT_LOCAL;
10638 p += 2;
10639 }
10640 else
10641 *opt_flags = 0;
10642
10643 if (!ASCII_ISALPHA(*p))
10644 return NULL;
10645 *arg = p;
10646
10647 if (p[0] == 't' && p[1] == '_' && p[2] != NUL && p[3] != NUL)
10648 p += 4; /* termcap option */
10649 else
10650 while (ASCII_ISALPHA(*p))
10651 ++p;
10652 return p;
10653}
10654
10655/*
10656 * ":function"
10657 */
10658 void
10659ex_function(eap)
10660 exarg_T *eap;
10661{
10662 char_u *theline;
10663 int j;
10664 int c;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010665 int saved_did_emsg;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010666 char_u *name = NULL;
10667 char_u *p;
10668 char_u *arg;
10669 garray_T newargs;
10670 garray_T newlines;
10671 int varargs = FALSE;
10672 int mustend = FALSE;
10673 int flags = 0;
10674 ufunc_T *fp;
10675 int indent;
10676 int nesting;
10677 char_u *skip_until = NULL;
10678 static char_u e_funcexts[] = N_("E122: Function %s already exists, add ! to replace it");
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010679 VAR v;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010680
10681 /*
10682 * ":function" without argument: list functions.
10683 */
10684 if (ends_excmd(*eap->arg))
10685 {
10686 if (!eap->skip)
10687 for (fp = firstfunc; fp != NULL && !got_int; fp = fp->next)
10688 list_func_head(fp, FALSE);
10689 eap->nextcmd = check_nextcmd(eap->arg);
10690 return;
10691 }
10692
10693 p = eap->arg;
10694 name = trans_function_name(&p, eap->skip, FALSE);
10695 if (name == NULL && !eap->skip)
10696 {
10697 /*
10698 * Return on an invalid expression in braces, unless the expression
10699 * evaluation has been cancelled due to an aborting error, an
10700 * interrupt, or an exception.
10701 */
10702 if (!aborting())
10703 return;
10704 else
10705 eap->skip = TRUE;
10706 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000010707 /* An error in a function call during evaluation of an expression in magic
10708 * braces should not cause the function not to be defined. */
10709 saved_did_emsg = did_emsg;
10710 did_emsg = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010711
10712 /*
10713 * ":function func" with only function name: list function.
10714 */
10715 if (vim_strchr(p, '(') == NULL)
10716 {
10717 if (!ends_excmd(*skipwhite(p)))
10718 {
10719 EMSG(_(e_trailing));
10720 goto erret_name;
10721 }
10722 eap->nextcmd = check_nextcmd(p);
10723 if (eap->nextcmd != NULL)
10724 *p = NUL;
10725 if (!eap->skip && !got_int)
10726 {
10727 fp = find_func(name);
10728 if (fp != NULL)
10729 {
10730 list_func_head(fp, TRUE);
10731 for (j = 0; j < fp->lines.ga_len && !got_int; ++j)
10732 {
10733 msg_putchar('\n');
10734 msg_outnum((long)(j + 1));
10735 if (j < 9)
10736 msg_putchar(' ');
10737 if (j < 99)
10738 msg_putchar(' ');
10739 msg_prt_line(FUNCLINE(fp, j));
10740 out_flush(); /* show a line at a time */
10741 ui_breakcheck();
10742 }
10743 if (!got_int)
10744 {
10745 msg_putchar('\n');
10746 msg_puts((char_u *)" endfunction");
10747 }
10748 }
10749 else
10750 EMSG2(_("E123: Undefined function: %s"), eap->arg);
10751 }
10752 goto erret_name;
10753 }
10754
10755 /*
10756 * ":function name(arg1, arg2)" Define function.
10757 */
10758 p = skipwhite(p);
10759 if (*p != '(')
10760 {
10761 if (!eap->skip)
10762 {
10763 EMSG2(_("E124: Missing '(': %s"), eap->arg);
10764 goto erret_name;
10765 }
10766 /* attempt to continue by skipping some text */
10767 if (vim_strchr(p, '(') != NULL)
10768 p = vim_strchr(p, '(');
10769 }
10770 p = skipwhite(p + 1);
10771
10772 ga_init2(&newargs, (int)sizeof(char_u *), 3);
10773 ga_init2(&newlines, (int)sizeof(char_u *), 3);
10774
10775 /*
10776 * Isolate the arguments: "arg1, arg2, ...)"
10777 */
10778 while (*p != ')')
10779 {
10780 if (p[0] == '.' && p[1] == '.' && p[2] == '.')
10781 {
10782 varargs = TRUE;
10783 p += 3;
10784 mustend = TRUE;
10785 }
10786 else
10787 {
10788 arg = p;
10789 while (ASCII_ISALNUM(*p) || *p == '_')
10790 ++p;
10791 if (arg == p || isdigit(*arg)
10792 || (p - arg == 9 && STRNCMP(arg, "firstline", 9) == 0)
10793 || (p - arg == 8 && STRNCMP(arg, "lastline", 8) == 0))
10794 {
10795 if (!eap->skip)
10796 EMSG2(_("E125: Illegal argument: %s"), arg);
10797 break;
10798 }
10799 if (ga_grow(&newargs, 1) == FAIL)
10800 goto erret;
10801 c = *p;
10802 *p = NUL;
10803 arg = vim_strsave(arg);
10804 if (arg == NULL)
10805 goto erret;
10806 ((char_u **)(newargs.ga_data))[newargs.ga_len] = arg;
10807 *p = c;
10808 newargs.ga_len++;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010809 if (*p == ',')
10810 ++p;
10811 else
10812 mustend = TRUE;
10813 }
10814 p = skipwhite(p);
10815 if (mustend && *p != ')')
10816 {
10817 if (!eap->skip)
10818 EMSG2(_(e_invarg2), eap->arg);
10819 break;
10820 }
10821 }
10822 ++p; /* skip the ')' */
10823
10824 /* find extra arguments "range" and "abort" */
10825 for (;;)
10826 {
10827 p = skipwhite(p);
10828 if (STRNCMP(p, "range", 5) == 0)
10829 {
10830 flags |= FC_RANGE;
10831 p += 5;
10832 }
10833 else if (STRNCMP(p, "abort", 5) == 0)
10834 {
10835 flags |= FC_ABORT;
10836 p += 5;
10837 }
10838 else
10839 break;
10840 }
10841
10842 if (*p != NUL && *p != '"' && *p != '\n' && !eap->skip && !did_emsg)
10843 EMSG(_(e_trailing));
10844
10845 /*
10846 * Read the body of the function, until ":endfunction" is found.
10847 */
10848 if (KeyTyped)
10849 {
10850 /* Check if the function already exists, don't let the user type the
10851 * whole function before telling him it doesn't work! For a script we
10852 * need to skip the body to be able to find what follows. */
10853 if (!eap->skip && !eap->forceit && find_func(name) != NULL)
10854 EMSG2(_(e_funcexts), name);
10855
10856 msg_putchar('\n'); /* don't overwrite the function name */
10857 cmdline_row = msg_row;
10858 }
10859
10860 indent = 2;
10861 nesting = 0;
10862 for (;;)
10863 {
10864 msg_scroll = TRUE;
10865 need_wait_return = FALSE;
10866 if (eap->getline == NULL)
10867 theline = getcmdline(':', 0L, indent);
10868 else
10869 theline = eap->getline(':', eap->cookie, indent);
10870 if (KeyTyped)
10871 lines_left = Rows - 1;
10872 if (theline == NULL)
10873 {
10874 EMSG(_("E126: Missing :endfunction"));
10875 goto erret;
10876 }
10877
10878 if (skip_until != NULL)
10879 {
10880 /* between ":append" and "." and between ":python <<EOF" and "EOF"
10881 * don't check for ":endfunc". */
10882 if (STRCMP(theline, skip_until) == 0)
10883 {
10884 vim_free(skip_until);
10885 skip_until = NULL;
10886 }
10887 }
10888 else
10889 {
10890 /* skip ':' and blanks*/
10891 for (p = theline; vim_iswhite(*p) || *p == ':'; ++p)
10892 ;
10893
10894 /* Check for "endfunction" (should be more strict...). */
10895 if (STRNCMP(p, "endf", 4) == 0 && nesting-- == 0)
10896 {
10897 vim_free(theline);
10898 break;
10899 }
10900
10901 /* Increase indent inside "if", "while", and "try", decrease
10902 * at "end". */
10903 if (indent > 2 && STRNCMP(p, "end", 3) == 0)
10904 indent -= 2;
10905 else if (STRNCMP(p, "if", 2) == 0 || STRNCMP(p, "wh", 2) == 0
10906 || STRNCMP(p, "try", 3) == 0)
10907 indent += 2;
10908
10909 /* Check for defining a function inside this function. */
10910 if (STRNCMP(p, "fu", 2) == 0)
10911 {
10912 p = skipwhite(skiptowhite(p));
10913 p += eval_fname_script(p);
10914 if (ASCII_ISALPHA(*p))
10915 {
10916 vim_free(trans_function_name(&p, TRUE, FALSE));
10917 if (*skipwhite(p) == '(')
10918 {
10919 ++nesting;
10920 indent += 2;
10921 }
10922 }
10923 }
10924
10925 /* Check for ":append" or ":insert". */
10926 p = skip_range(p, NULL);
10927 if ((p[0] == 'a' && (!ASCII_ISALPHA(p[1]) || p[1] == 'p'))
10928 || (p[0] == 'i'
10929 && (!ASCII_ISALPHA(p[1]) || (p[1] == 'n'
10930 && (!ASCII_ISALPHA(p[2]) || (p[2] == 's'))))))
10931 skip_until = vim_strsave((char_u *)".");
10932
10933 /* Check for ":python <<EOF", ":tcl <<EOF", etc. */
10934 arg = skipwhite(skiptowhite(p));
10935 if (arg[0] == '<' && arg[1] =='<'
10936 && ((p[0] == 'p' && p[1] == 'y'
10937 && (!ASCII_ISALPHA(p[2]) || p[2] == 't'))
10938 || (p[0] == 'p' && p[1] == 'e'
10939 && (!ASCII_ISALPHA(p[2]) || p[2] == 'r'))
10940 || (p[0] == 't' && p[1] == 'c'
10941 && (!ASCII_ISALPHA(p[2]) || p[2] == 'l'))
10942 || (p[0] == 'r' && p[1] == 'u' && p[2] == 'b'
10943 && (!ASCII_ISALPHA(p[3]) || p[3] == 'y'))
Bram Moolenaar325b7a22004-07-05 15:58:32 +000010944 || (p[0] == 'm' && p[1] == 'z'
10945 && (!ASCII_ISALPHA(p[2]) || p[2] == 's'))
Bram Moolenaar071d4272004-06-13 20:20:40 +000010946 ))
10947 {
10948 /* ":python <<" continues until a dot, like ":append" */
10949 p = skipwhite(arg + 2);
10950 if (*p == NUL)
10951 skip_until = vim_strsave((char_u *)".");
10952 else
10953 skip_until = vim_strsave(p);
10954 }
10955 }
10956
10957 /* Add the line to the function. */
10958 if (ga_grow(&newlines, 1) == FAIL)
10959 goto erret;
10960 ((char_u **)(newlines.ga_data))[newlines.ga_len] = theline;
10961 newlines.ga_len++;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010962 }
10963
10964 /* Don't define the function when skipping commands or when an error was
10965 * detected. */
10966 if (eap->skip || did_emsg)
10967 goto erret;
10968
10969 /*
10970 * If there are no errors, add the function
10971 */
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010972 v = find_var(name, FALSE);
10973 if (v != NULL && v->tv.v_type == VAR_FUNC)
10974 {
10975 EMSG2(_("E999: Function name conflicts with variable: %s"), name);
10976 goto erret;
10977 }
10978
Bram Moolenaar071d4272004-06-13 20:20:40 +000010979 fp = find_func(name);
10980 if (fp != NULL)
10981 {
10982 if (!eap->forceit)
10983 {
10984 EMSG2(_(e_funcexts), name);
10985 goto erret;
10986 }
10987 if (fp->calls)
10988 {
10989 EMSG2(_("E127: Cannot redefine function %s: It is in use"), name);
10990 goto erret;
10991 }
10992 /* redefine existing function */
10993 ga_clear_strings(&(fp->args));
10994 ga_clear_strings(&(fp->lines));
10995 vim_free(name);
10996 }
10997 else
10998 {
10999 fp = (ufunc_T *)alloc((unsigned)sizeof(ufunc_T));
11000 if (fp == NULL)
11001 goto erret;
11002 /* insert the new function in the function list */
11003 fp->next = firstfunc;
11004 firstfunc = fp;
11005 fp->name = name;
11006 }
11007 fp->args = newargs;
11008 fp->lines = newlines;
11009 fp->varargs = varargs;
11010 fp->flags = flags;
11011 fp->calls = 0;
11012 fp->script_ID = current_SID;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011013 did_emsg |= saved_did_emsg;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011014 vim_free(skip_until);
11015 return;
11016
11017erret:
11018 vim_free(skip_until);
11019 ga_clear_strings(&newargs);
11020 ga_clear_strings(&newlines);
11021erret_name:
11022 vim_free(name);
Bram Moolenaar071d4272004-06-13 20:20:40 +000011023 did_emsg |= saved_did_emsg;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011024}
11025
11026/*
11027 * Get a function name, translating "<SID>" and "<SNR>".
11028 * Returns the function name in allocated memory, or NULL for failure.
11029 * Advances "pp" to just after the function name (if no error).
11030 */
11031 static char_u *
11032trans_function_name(pp, skip, internal)
11033 char_u **pp;
11034 int skip; /* only find the end, don't evaluate */
11035 int internal; /* TRUE if internal function name OK */
11036{
11037 char_u *name;
11038 char_u *start;
11039 char_u *end;
11040 int lead;
11041 char_u sid_buf[20];
11042 char_u *temp_string = NULL;
11043 char_u *expr_start, *expr_end;
11044 int len;
11045
11046 /* A name starting with "<SID>" or "<SNR>" is local to a script. */
11047 start = *pp;
11048 lead = eval_fname_script(start);
11049 if (lead > 0)
11050 start += lead;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011051 end = find_name_end(start, &expr_start, &expr_end, FALSE);
Bram Moolenaar071d4272004-06-13 20:20:40 +000011052 if (end == start)
11053 {
11054 if (!skip)
11055 EMSG(_("E129: Function name required"));
11056 return NULL;
11057 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000011058 if (expr_start != NULL && !skip)
11059 {
11060 /* expand magic curlies */
11061 temp_string = make_expanded_name(start, expr_start, expr_end, end);
11062 if (temp_string == NULL)
11063 {
11064 /*
11065 * Report an invalid expression in braces, unless the expression
11066 * evaluation has been cancelled due to an aborting error, an
11067 * interrupt, or an exception.
11068 */
11069 if (!aborting())
11070 EMSG2(_(e_invarg2), start);
11071 else
11072 *pp = end;
11073 return NULL;
11074 }
11075 start = temp_string;
11076 len = (int)STRLEN(temp_string);
11077 }
11078 else
Bram Moolenaar071d4272004-06-13 20:20:40 +000011079 len = (int)(end - start);
11080
11081 /*
11082 * Copy the function name to allocated memory.
11083 * Accept <SID>name() inside a script, translate into <SNR>123_name().
11084 * Accept <SNR>123_name() outside a script.
11085 */
11086 if (skip)
11087 lead = 0; /* do nothing */
11088 else if (lead > 0)
11089 {
11090 lead = 3;
11091 if (eval_fname_sid(*pp)) /* If it's "<SID>" */
11092 {
11093 if (current_SID <= 0)
11094 {
11095 EMSG(_(e_usingsid));
11096 return NULL;
11097 }
11098 sprintf((char *)sid_buf, "%ld_", (long)current_SID);
11099 lead += (int)STRLEN(sid_buf);
11100 }
11101 }
11102 else if (!internal && !ASCII_ISUPPER(*start))
11103 {
11104 EMSG2(_("E128: Function name must start with a capital: %s"), start);
11105 return NULL;
11106 }
11107 name = alloc((unsigned)(len + lead + 1));
11108 if (name != NULL)
11109 {
11110 if (lead > 0)
11111 {
11112 name[0] = K_SPECIAL;
11113 name[1] = KS_EXTRA;
11114 name[2] = (int)KE_SNR;
11115 if (eval_fname_sid(*pp)) /* If it's "<SID>" */
11116 STRCPY(name + 3, sid_buf);
11117 }
11118 mch_memmove(name + lead, start, (size_t)len);
11119 name[len + lead] = NUL;
11120 }
11121 *pp = end;
11122
11123 vim_free(temp_string);
11124 return name;
11125}
11126
11127/*
11128 * Return 5 if "p" starts with "<SID>" or "<SNR>" (ignoring case).
11129 * Return 2 if "p" starts with "s:".
11130 * Return 0 otherwise.
11131 */
11132 static int
11133eval_fname_script(p)
11134 char_u *p;
11135{
11136 if (p[0] == '<' && (STRNICMP(p + 1, "SID>", 4) == 0
11137 || STRNICMP(p + 1, "SNR>", 4) == 0))
11138 return 5;
11139 if (p[0] == 's' && p[1] == ':')
11140 return 2;
11141 return 0;
11142}
11143
11144/*
11145 * Return TRUE if "p" starts with "<SID>" or "s:".
11146 * Only works if eval_fname_script() returned non-zero for "p"!
11147 */
11148 static int
11149eval_fname_sid(p)
11150 char_u *p;
11151{
11152 return (*p == 's' || TOUPPER_ASC(p[2]) == 'I');
11153}
11154
11155/*
11156 * List the head of the function: "name(arg1, arg2)".
11157 */
11158 static void
11159list_func_head(fp, indent)
11160 ufunc_T *fp;
11161 int indent;
11162{
11163 int j;
11164
11165 msg_start();
11166 if (indent)
11167 MSG_PUTS(" ");
11168 MSG_PUTS("function ");
11169 if (fp->name[0] == K_SPECIAL)
11170 {
11171 MSG_PUTS_ATTR("<SNR>", hl_attr(HLF_8));
11172 msg_puts(fp->name + 3);
11173 }
11174 else
11175 msg_puts(fp->name);
11176 msg_putchar('(');
11177 for (j = 0; j < fp->args.ga_len; ++j)
11178 {
11179 if (j)
11180 MSG_PUTS(", ");
11181 msg_puts(FUNCARG(fp, j));
11182 }
11183 if (fp->varargs)
11184 {
11185 if (j)
11186 MSG_PUTS(", ");
11187 MSG_PUTS("...");
11188 }
11189 msg_putchar(')');
11190}
11191
11192/*
11193 * Find a function by name, return pointer to it in ufuncs.
11194 * Return NULL for unknown function.
11195 */
11196 static ufunc_T *
11197find_func(name)
11198 char_u *name;
11199{
11200 ufunc_T *fp;
11201
11202 for (fp = firstfunc; fp != NULL; fp = fp->next)
11203 if (STRCMP(name, fp->name) == 0)
11204 break;
11205 return fp;
11206}
11207
Bram Moolenaar49cd9572005-01-03 21:06:01 +000011208/*
11209 * Return TRUE if a function "name" exists.
11210 */
11211 static int
11212function_exists(name)
11213 char_u *name;
11214{
11215 char_u *p = name;
11216 int n = FALSE;
11217
11218 p = trans_function_name(&p, FALSE, TRUE);
11219 if (p != NULL)
11220 {
11221 if (ASCII_ISUPPER(*p) || p[0] == K_SPECIAL)
11222 n = (find_func(p) != NULL);
11223 else if (ASCII_ISLOWER(*p))
11224 n = (find_internal_func(p) >= 0);
11225 vim_free(p);
11226 }
11227 return n;
11228}
11229
Bram Moolenaar071d4272004-06-13 20:20:40 +000011230#if defined(FEAT_CMDL_COMPL) || defined(PROTO)
11231
11232/*
11233 * Function given to ExpandGeneric() to obtain the list of user defined
11234 * function names.
11235 */
11236 char_u *
11237get_user_func_name(xp, idx)
11238 expand_T *xp;
11239 int idx;
11240{
11241 static ufunc_T *fp = NULL;
11242
11243 if (idx == 0)
11244 fp = firstfunc;
11245 if (fp != NULL)
11246 {
11247 if (STRLEN(fp->name) + 4 >= IOSIZE)
11248 return fp->name; /* prevents overflow */
11249
11250 cat_func_name(IObuff, fp);
11251 if (xp->xp_context != EXPAND_USER_FUNC)
11252 {
11253 STRCAT(IObuff, "(");
11254 if (!fp->varargs && fp->args.ga_len == 0)
11255 STRCAT(IObuff, ")");
11256 }
11257
11258 fp = fp->next;
11259 return IObuff;
11260 }
11261 return NULL;
11262}
11263
11264#endif /* FEAT_CMDL_COMPL */
11265
11266/*
11267 * Copy the function name of "fp" to buffer "buf".
11268 * "buf" must be able to hold the function name plus three bytes.
11269 * Takes care of script-local function names.
11270 */
11271 static void
11272cat_func_name(buf, fp)
11273 char_u *buf;
11274 ufunc_T *fp;
11275{
11276 if (fp->name[0] == K_SPECIAL)
11277 {
11278 STRCPY(buf, "<SNR>");
11279 STRCAT(buf, fp->name + 3);
11280 }
11281 else
11282 STRCPY(buf, fp->name);
11283}
11284
11285/*
11286 * ":delfunction {name}"
11287 */
11288 void
11289ex_delfunction(eap)
11290 exarg_T *eap;
11291{
11292 ufunc_T *fp = NULL, *pfp;
11293 char_u *p;
11294 char_u *name;
11295
11296 p = eap->arg;
11297 name = trans_function_name(&p, eap->skip, FALSE);
11298 if (name == NULL)
11299 return;
11300 if (!ends_excmd(*skipwhite(p)))
11301 {
11302 vim_free(name);
11303 EMSG(_(e_trailing));
11304 return;
11305 }
11306 eap->nextcmd = check_nextcmd(p);
11307 if (eap->nextcmd != NULL)
11308 *p = NUL;
11309
11310 if (!eap->skip)
11311 fp = find_func(name);
11312 vim_free(name);
11313
11314 if (!eap->skip)
11315 {
11316 if (fp == NULL)
11317 {
11318 EMSG2(_("E130: Undefined function: %s"), eap->arg);
11319 return;
11320 }
11321 if (fp->calls)
11322 {
11323 EMSG2(_("E131: Cannot delete function %s: It is in use"), eap->arg);
11324 return;
11325 }
11326
11327 /* clear this function */
11328 vim_free(fp->name);
11329 ga_clear_strings(&(fp->args));
11330 ga_clear_strings(&(fp->lines));
11331
11332 /* remove the function from the function list */
11333 if (firstfunc == fp)
11334 firstfunc = fp->next;
11335 else
11336 {
11337 for (pfp = firstfunc; pfp != NULL; pfp = pfp->next)
11338 if (pfp->next == fp)
11339 {
11340 pfp->next = fp->next;
11341 break;
11342 }
11343 }
11344 vim_free(fp);
11345 }
11346}
11347
11348/*
11349 * Call a user function.
11350 */
11351 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011352call_user_func(fp, argcount, argvars, rettv, firstline, lastline)
Bram Moolenaar071d4272004-06-13 20:20:40 +000011353 ufunc_T *fp; /* pointer to function */
11354 int argcount; /* nr of args */
Bram Moolenaar49cd9572005-01-03 21:06:01 +000011355 typeval *argvars; /* arguments */
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011356 typeval *rettv; /* return value */
Bram Moolenaar071d4272004-06-13 20:20:40 +000011357 linenr_T firstline; /* first line of range */
11358 linenr_T lastline; /* last line of range */
11359{
11360 char_u *save_sourcing_name;
11361 linenr_T save_sourcing_lnum;
11362 scid_T save_current_SID;
11363 struct funccall fc;
11364 struct funccall *save_fcp = current_funccal;
11365 int save_did_emsg;
11366 static int depth = 0;
11367
11368 /* If depth of calling is getting too high, don't execute the function */
11369 if (depth >= p_mfd)
11370 {
11371 EMSG(_("E132: Function call depth is higher than 'maxfuncdepth'"));
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011372 rettv->v_type = VAR_NUMBER;
11373 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011374 return;
11375 }
11376 ++depth;
11377
11378 line_breakcheck(); /* check for CTRL-C hit */
11379
11380 /* set local variables */
Bram Moolenaar49cd9572005-01-03 21:06:01 +000011381 vars_init(&fc.l_vars);
Bram Moolenaar071d4272004-06-13 20:20:40 +000011382 fc.func = fp;
11383 fc.argcount = argcount;
11384 fc.argvars = argvars;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011385 fc.rettv = rettv;
11386 rettv->vval.v_number = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011387 fc.linenr = 0;
11388 fc.returned = FALSE;
11389 fc.level = ex_nesting_level;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000011390 fc.a0_var.tv.v_type = VAR_NUMBER;
11391 fc.a0_var.tv.vval.v_number = argcount - fp->args.ga_len;
11392 fc.a0_var.v_name = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011393 current_funccal = &fc;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000011394 fc.firstline.tv.v_type = VAR_NUMBER;
11395 fc.firstline.tv.vval.v_number = firstline;
11396 fc.firstline.v_name = NULL;
11397 fc.lastline.tv.v_type = VAR_NUMBER;
11398 fc.lastline.tv.vval.v_number = lastline;
11399 fc.lastline.v_name = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011400 /* Check if this function has a breakpoint. */
11401 fc.breakpoint = dbg_find_breakpoint(FALSE, fp->name, (linenr_T)0);
11402 fc.dbg_tick = debug_tick;
11403
11404 /* Don't redraw while executing the function. */
11405 ++RedrawingDisabled;
11406 save_sourcing_name = sourcing_name;
11407 save_sourcing_lnum = sourcing_lnum;
11408 sourcing_lnum = 1;
11409 sourcing_name = alloc((unsigned)((save_sourcing_name == NULL ? 0
11410 : STRLEN(save_sourcing_name)) + STRLEN(fp->name) + 13));
11411 if (sourcing_name != NULL)
11412 {
11413 if (save_sourcing_name != NULL
11414 && STRNCMP(save_sourcing_name, "function ", 9) == 0)
11415 sprintf((char *)sourcing_name, "%s..", save_sourcing_name);
11416 else
11417 STRCPY(sourcing_name, "function ");
11418 cat_func_name(sourcing_name + STRLEN(sourcing_name), fp);
11419
11420 if (p_verbose >= 12)
11421 {
11422 ++no_wait_return;
11423 msg_scroll = TRUE; /* always scroll up, don't overwrite */
11424 msg_str((char_u *)_("calling %s"), sourcing_name);
11425 if (p_verbose >= 14)
11426 {
11427 int i;
11428 char_u buf[MSG_BUF_LEN];
11429
11430 msg_puts((char_u *)"(");
11431 for (i = 0; i < argcount; ++i)
11432 {
11433 if (i > 0)
11434 msg_puts((char_u *)", ");
Bram Moolenaar49cd9572005-01-03 21:06:01 +000011435 if (argvars[i].v_type == VAR_NUMBER)
11436 msg_outnum((long)argvars[i].vval.v_number);
Bram Moolenaar071d4272004-06-13 20:20:40 +000011437 else
11438 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011439 trunc_string(get_tv_string(&argvars[i]),
Bram Moolenaar071d4272004-06-13 20:20:40 +000011440 buf, MSG_BUF_LEN);
11441 msg_puts((char_u *)"\"");
11442 msg_puts(buf);
11443 msg_puts((char_u *)"\"");
11444 }
11445 }
11446 msg_puts((char_u *)")");
11447 }
11448 msg_puts((char_u *)"\n"); /* don't overwrite this either */
11449 cmdline_row = msg_row;
11450 --no_wait_return;
11451 }
11452 }
11453 save_current_SID = current_SID;
11454 current_SID = fp->script_ID;
11455 save_did_emsg = did_emsg;
11456 did_emsg = FALSE;
11457
11458 /* call do_cmdline() to execute the lines */
11459 do_cmdline(NULL, get_func_line, (void *)&fc,
11460 DOCMD_NOWAIT|DOCMD_VERBOSE|DOCMD_REPEAT);
11461
11462 --RedrawingDisabled;
11463
11464 /* when the function was aborted because of an error, return -1 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011465 if ((did_emsg && (fp->flags & FC_ABORT)) || rettv->v_type == VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +000011466 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011467 clear_tv(rettv);
11468 rettv->v_type = VAR_NUMBER;
11469 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011470 }
11471
11472 /* when being verbose, mention the return value */
11473 if (p_verbose >= 12)
11474 {
11475 char_u *sn, *val;
11476
11477 ++no_wait_return;
11478 msg_scroll = TRUE; /* always scroll up, don't overwrite */
11479
11480 /* Make sure the output fits in IObuff. */
11481 sn = sourcing_name;
11482 if (STRLEN(sourcing_name) > IOSIZE / 2 - 50)
11483 sn = sourcing_name + STRLEN(sourcing_name) - (IOSIZE / 2 - 50);
11484
11485 if (aborting())
11486 smsg((char_u *)_("%s aborted"), sn);
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011487 else if (fc.rettv->v_type == VAR_NUMBER)
Bram Moolenaar071d4272004-06-13 20:20:40 +000011488 smsg((char_u *)_("%s returning #%ld"), sn,
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011489 (long)fc.rettv->vval.v_number);
11490 else if (fc.rettv->v_type == VAR_STRING)
Bram Moolenaar071d4272004-06-13 20:20:40 +000011491 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011492 val = get_tv_string(fc.rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000011493 if (STRLEN(val) > IOSIZE / 2 - 50)
11494 val = val + STRLEN(val) - (IOSIZE / 2 - 50);
11495 smsg((char_u *)_("%s returning \"%s\""), sn, val);
11496 }
11497 msg_puts((char_u *)"\n"); /* don't overwrite this either */
11498 cmdline_row = msg_row;
11499 --no_wait_return;
11500 }
11501
11502 vim_free(sourcing_name);
11503 sourcing_name = save_sourcing_name;
11504 sourcing_lnum = save_sourcing_lnum;
11505 current_SID = save_current_SID;
11506
11507 if (p_verbose >= 12 && sourcing_name != NULL)
11508 {
11509 ++no_wait_return;
11510 msg_scroll = TRUE; /* always scroll up, don't overwrite */
11511 msg_str((char_u *)_("continuing in %s"), sourcing_name);
11512 msg_puts((char_u *)"\n"); /* don't overwrite this either */
11513 cmdline_row = msg_row;
11514 --no_wait_return;
11515 }
11516
11517 did_emsg |= save_did_emsg;
11518 current_funccal = save_fcp;
11519
Bram Moolenaar49cd9572005-01-03 21:06:01 +000011520 vars_clear(&fc.l_vars); /* free all local variables */
Bram Moolenaar071d4272004-06-13 20:20:40 +000011521 --depth;
11522}
11523
11524/*
11525 * ":return [expr]"
11526 */
11527 void
11528ex_return(eap)
11529 exarg_T *eap;
11530{
11531 char_u *arg = eap->arg;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011532 typeval rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011533 int returning = FALSE;
11534
11535 if (current_funccal == NULL)
11536 {
11537 EMSG(_("E133: :return not inside a function"));
11538 return;
11539 }
11540
11541 if (eap->skip)
11542 ++emsg_skip;
11543
11544 eap->nextcmd = NULL;
11545 if ((*arg != NUL && *arg != '|' && *arg != '\n')
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011546 && eval0(arg, &rettv, &eap->nextcmd, !eap->skip) != FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000011547 {
11548 if (!eap->skip)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011549 returning = do_return(eap, FALSE, TRUE, &rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000011550 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011551 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000011552 }
11553 /* It's safer to return also on error. */
11554 else if (!eap->skip)
11555 {
11556 /*
11557 * Return unless the expression evaluation has been cancelled due to an
11558 * aborting error, an interrupt, or an exception.
11559 */
11560 if (!aborting())
11561 returning = do_return(eap, FALSE, TRUE, NULL);
11562 }
11563
11564 /* When skipping or the return gets pending, advance to the next command
11565 * in this line (!returning). Otherwise, ignore the rest of the line.
11566 * Following lines will be ignored by get_func_line(). */
11567 if (returning)
11568 eap->nextcmd = NULL;
11569 else if (eap->nextcmd == NULL) /* no argument */
11570 eap->nextcmd = check_nextcmd(arg);
11571
11572 if (eap->skip)
11573 --emsg_skip;
11574}
11575
11576/*
11577 * Return from a function. Possibly makes the return pending. Also called
11578 * for a pending return at the ":endtry" or after returning from an extra
11579 * do_cmdline(). "reanimate" is used in the latter case. "is_cmd" is set
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011580 * when called due to a ":return" command. "rettv" may point to a typeval
11581 * with the return rettv. Returns TRUE when the return can be carried out,
Bram Moolenaar071d4272004-06-13 20:20:40 +000011582 * FALSE when the return gets pending.
11583 */
11584 int
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011585do_return(eap, reanimate, is_cmd, rettv)
Bram Moolenaar071d4272004-06-13 20:20:40 +000011586 exarg_T *eap;
11587 int reanimate;
11588 int is_cmd;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011589 void *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011590{
11591 int idx;
11592 struct condstack *cstack = eap->cstack;
11593
11594 if (reanimate)
11595 /* Undo the return. */
11596 current_funccal->returned = FALSE;
11597
11598 /*
11599 * Cleanup (and inactivate) conditionals, but stop when a try conditional
11600 * not in its finally clause (which then is to be executed next) is found.
11601 * In this case, make the ":return" pending for execution at the ":endtry".
11602 * Otherwise, return normally.
11603 */
11604 idx = cleanup_conditionals(eap->cstack, 0, TRUE);
11605 if (idx >= 0)
11606 {
11607 cstack->cs_pending[idx] = CSTP_RETURN;
11608
11609 if (!is_cmd && !reanimate)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011610 /* A pending return again gets pending. "rettv" points to an
11611 * allocated variable with the rettv of the original ":return"'s
Bram Moolenaar071d4272004-06-13 20:20:40 +000011612 * argument if present or is NULL else. */
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011613 cstack->cs_rettv[idx] = rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011614 else
11615 {
11616 /* When undoing a return in order to make it pending, get the stored
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011617 * return rettv. */
Bram Moolenaar071d4272004-06-13 20:20:40 +000011618 if (reanimate)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011619 rettv = current_funccal->rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011620
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011621 if (rettv != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000011622 {
11623 /* Store the value of the pending return. */
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011624 if ((cstack->cs_rettv[idx] = alloc_tv()) != NULL)
11625 *(typeval *)cstack->cs_rettv[idx] = *(typeval *)rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011626 else
11627 EMSG(_(e_outofmem));
11628 }
11629 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011630 cstack->cs_rettv[idx] = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011631
11632 if (reanimate)
11633 {
11634 /* The pending return value could be overwritten by a ":return"
11635 * without argument in a finally clause; reset the default
11636 * return value. */
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011637 current_funccal->rettv->v_type = VAR_NUMBER;
11638 current_funccal->rettv->vval.v_number = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011639 }
11640 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011641 report_make_pending(CSTP_RETURN, rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000011642 }
11643 else
11644 {
11645 current_funccal->returned = TRUE;
11646
11647 /* If the return is carried out now, store the return value. For
11648 * a return immediately after reanimation, the value is already
11649 * there. */
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011650 if (!reanimate && rettv != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000011651 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011652 clear_tv(current_funccal->rettv);
11653 *current_funccal->rettv = *(typeval *)rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011654 if (!is_cmd)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011655 vim_free(rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000011656 }
11657 }
11658
11659 return idx < 0;
11660}
11661
11662/*
11663 * Free the variable with a pending return value.
11664 */
11665 void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011666discard_pending_return(rettv)
11667 void *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011668{
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011669 free_tv((typeval *)rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000011670}
11671
11672/*
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011673 * Generate a return command for producing the value of "rettv". The result
Bram Moolenaar071d4272004-06-13 20:20:40 +000011674 * is an allocated string. Used by report_pending() for verbose messages.
11675 */
11676 char_u *
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011677get_return_cmd(rettv)
11678 void *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011679{
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011680 char_u *s;
11681 char_u *tofree = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011682
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011683 if (rettv == NULL)
11684 s = (char_u *)"";
Bram Moolenaar071d4272004-06-13 20:20:40 +000011685 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011686 s = tv2string((typeval *)rettv, &tofree);
11687
11688 STRCPY(IObuff, ":return ");
11689 STRNCPY(IObuff + 8, s, IOSIZE - 8);
11690 if (STRLEN(s) + 8 >= IOSIZE)
11691 STRCPY(IObuff + IOSIZE - 4, "...");
11692 vim_free(tofree);
11693 return vim_strsave(IObuff);
Bram Moolenaar071d4272004-06-13 20:20:40 +000011694}
11695
11696/*
11697 * Get next function line.
11698 * Called by do_cmdline() to get the next line.
11699 * Returns allocated string, or NULL for end of function.
11700 */
11701/* ARGSUSED */
11702 char_u *
11703get_func_line(c, cookie, indent)
11704 int c; /* not used */
11705 void *cookie;
11706 int indent; /* not used */
11707{
11708 struct funccall *fcp = (struct funccall *)cookie;
11709 char_u *retval;
11710 garray_T *gap; /* growarray with function lines */
11711
11712 /* If breakpoints have been added/deleted need to check for it. */
11713 if (fcp->dbg_tick != debug_tick)
11714 {
11715 fcp->breakpoint = dbg_find_breakpoint(FALSE, fcp->func->name,
11716 sourcing_lnum);
11717 fcp->dbg_tick = debug_tick;
11718 }
11719
11720 gap = &fcp->func->lines;
11721 if ((fcp->func->flags & FC_ABORT) && did_emsg && !aborted_in_try())
11722 retval = NULL;
11723 else if (fcp->returned || fcp->linenr >= gap->ga_len)
11724 retval = NULL;
11725 else
11726 {
11727 retval = vim_strsave(((char_u **)(gap->ga_data))[fcp->linenr++]);
11728 sourcing_lnum = fcp->linenr;
11729 }
11730
11731 /* Did we encounter a breakpoint? */
11732 if (fcp->breakpoint != 0 && fcp->breakpoint <= sourcing_lnum)
11733 {
11734 dbg_breakpoint(fcp->func->name, sourcing_lnum);
11735 /* Find next breakpoint. */
11736 fcp->breakpoint = dbg_find_breakpoint(FALSE, fcp->func->name,
11737 sourcing_lnum);
11738 fcp->dbg_tick = debug_tick;
11739 }
11740
11741 return retval;
11742}
11743
11744/*
11745 * Return TRUE if the currently active function should be ended, because a
11746 * return was encountered or an error occured. Used inside a ":while".
11747 */
11748 int
11749func_has_ended(cookie)
11750 void *cookie;
11751{
11752 struct funccall *fcp = (struct funccall *)cookie;
11753
11754 /* Ignore the "abort" flag if the abortion behavior has been changed due to
11755 * an error inside a try conditional. */
11756 return (((fcp->func->flags & FC_ABORT) && did_emsg && !aborted_in_try())
11757 || fcp->returned);
11758}
11759
11760/*
11761 * return TRUE if cookie indicates a function which "abort"s on errors.
11762 */
11763 int
11764func_has_abort(cookie)
11765 void *cookie;
11766{
11767 return ((struct funccall *)cookie)->func->flags & FC_ABORT;
11768}
11769
11770#if defined(FEAT_VIMINFO) || defined(FEAT_SESSION)
11771typedef enum
11772{
11773 VAR_FLAVOUR_DEFAULT,
11774 VAR_FLAVOUR_SESSION,
11775 VAR_FLAVOUR_VIMINFO
11776} var_flavour_T;
11777
11778static var_flavour_T var_flavour __ARGS((char_u *varname));
11779
11780 static var_flavour_T
11781var_flavour(varname)
11782 char_u *varname;
11783{
11784 char_u *p = varname;
11785
11786 if (ASCII_ISUPPER(*p))
11787 {
11788 while (*(++p))
11789 if (ASCII_ISLOWER(*p))
11790 return VAR_FLAVOUR_SESSION;
11791 return VAR_FLAVOUR_VIMINFO;
11792 }
11793 else
11794 return VAR_FLAVOUR_DEFAULT;
11795}
11796#endif
11797
11798#if defined(FEAT_VIMINFO) || defined(PROTO)
11799/*
11800 * Restore global vars that start with a capital from the viminfo file
11801 */
11802 int
11803read_viminfo_varlist(virp, writing)
11804 vir_T *virp;
11805 int writing;
11806{
11807 char_u *tab;
11808 int is_string = FALSE;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011809 typeval *tvp = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011810 char_u *val;
11811
11812 if (!writing && (find_viminfo_parameter('!') != NULL))
11813 {
11814 tab = vim_strchr(virp->vir_line + 1, '\t');
11815 if (tab != NULL)
11816 {
11817 *tab++ = '\0'; /* isolate the variable name */
11818 if (*tab == 'S') /* string var */
11819 is_string = TRUE;
11820
11821 tab = vim_strchr(tab, '\t');
11822 if (tab != NULL)
11823 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011824 /* create a typeval to hold the value */
Bram Moolenaar071d4272004-06-13 20:20:40 +000011825 if (is_string)
11826 {
11827 val = viminfo_readstring(virp,
11828 (int)(tab - virp->vir_line + 1), TRUE);
11829 if (val != NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011830 tvp = alloc_string_tv(val);
Bram Moolenaar071d4272004-06-13 20:20:40 +000011831 }
11832 else
11833 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011834 tvp = alloc_tv();
11835 if (tvp != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000011836 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011837 tvp->v_type = VAR_NUMBER;
11838 tvp->vval.v_number = atol((char *)tab + 1);
Bram Moolenaar071d4272004-06-13 20:20:40 +000011839 }
11840 }
11841 /* assign the value to the variable */
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011842 if (tvp != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000011843 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011844 set_var(virp->vir_line + 1, tvp, FALSE);
11845 free_tv(tvp);
Bram Moolenaar071d4272004-06-13 20:20:40 +000011846 }
11847 }
11848 }
11849 }
11850
11851 return viminfo_readline(virp);
11852}
11853
11854/*
11855 * Write global vars that start with a capital to the viminfo file
11856 */
11857 void
11858write_viminfo_varlist(fp)
11859 FILE *fp;
11860{
11861 garray_T *gap = &variables; /* global variable */
11862 VAR this_var;
11863 int i;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011864 char *s;
11865 char_u *tofree;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011866
11867 if (find_viminfo_parameter('!') == NULL)
11868 return;
11869
11870 fprintf(fp, _("\n# global variables:\n"));
11871 for (i = gap->ga_len; --i >= 0; )
11872 {
11873 this_var = &VAR_GAP_ENTRY(i, gap);
Bram Moolenaar49cd9572005-01-03 21:06:01 +000011874 if (this_var->v_name != NULL
11875 && var_flavour(this_var->v_name) == VAR_FLAVOUR_VIMINFO)
Bram Moolenaar071d4272004-06-13 20:20:40 +000011876 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011877 switch (this_var->tv.v_type)
11878 {
11879 case VAR_STRING: s = "STR"; break;
11880 case VAR_NUMBER: s = "NUM"; break;
11881 case VAR_LIST: s = "LST"; break;
11882 case VAR_FUNC: s = "FUN"; break;
11883 default:
11884 EMSGN(_("E999: Internal error: write_viminfo_varlist(): %ld"), (long)this_var->tv.v_type);
11885 s = "ERR";
11886 }
11887 fprintf(fp, "!%s\t%s\t", this_var->v_name, s);
11888 viminfo_writestring(fp, tv2string(&this_var->tv, &tofree));
11889 vim_free(tofree);
Bram Moolenaar071d4272004-06-13 20:20:40 +000011890 }
11891 }
11892}
11893#endif
11894
11895#if defined(FEAT_SESSION) || defined(PROTO)
11896 int
11897store_session_globals(fd)
11898 FILE *fd;
11899{
11900 garray_T *gap = &variables; /* global variable */
11901 VAR this_var;
11902 int i;
11903 char_u *p, *t;
11904
11905 for (i = gap->ga_len; --i >= 0; )
11906 {
11907 this_var = &VAR_GAP_ENTRY(i, gap);
Bram Moolenaar49cd9572005-01-03 21:06:01 +000011908 if (this_var->v_name != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000011909 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +000011910 if (var_flavour(this_var->v_name) == VAR_FLAVOUR_SESSION)
Bram Moolenaar071d4272004-06-13 20:20:40 +000011911 {
11912 /* Escapse special characters with a backslash. Turn a LF and
11913 * CR into \n and \r. */
11914 p = vim_strsave_escaped(get_var_string(this_var),
11915 (char_u *)"\\\"\n\r");
11916 if (p == NULL) /* out of memory */
11917 continue;
11918 for (t = p; *t != NUL; ++t)
11919 if (*t == '\n')
11920 *t = 'n';
11921 else if (*t == '\r')
11922 *t = 'r';
11923 if ((fprintf(fd, "let %s = %c%s%c",
Bram Moolenaar49cd9572005-01-03 21:06:01 +000011924 this_var->v_name,
11925 (this_var->tv.v_type == VAR_STRING) ? '"' : ' ',
11926 p,
11927 (this_var->tv.v_type == VAR_STRING) ? '"' : ' ') < 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +000011928 || put_eol(fd) == FAIL)
11929 {
11930 vim_free(p);
11931 return FAIL;
11932 }
11933 vim_free(p);
11934 }
11935
11936 }
11937 }
11938 return OK;
11939}
11940#endif
11941
11942#endif /* FEAT_EVAL */
11943
11944#if defined(FEAT_MODIFY_FNAME) || defined(FEAT_EVAL) || defined(PROTO)
11945
11946
11947#ifdef WIN3264
11948/*
11949 * Functions for ":8" filename modifier: get 8.3 version of a filename.
11950 */
11951static int get_short_pathname __ARGS((char_u **fnamep, char_u **bufp, int *fnamelen));
11952static int shortpath_for_invalid_fname __ARGS((char_u **fname, char_u **bufp, int *fnamelen));
11953static int shortpath_for_partial __ARGS((char_u **fnamep, char_u **bufp, int *fnamelen));
11954
11955/*
11956 * Get the short pathname of a file.
11957 * Returns 1 on success. *fnamelen is 0 for nonexistant path.
11958 */
11959 static int
11960get_short_pathname(fnamep, bufp, fnamelen)
11961 char_u **fnamep;
11962 char_u **bufp;
11963 int *fnamelen;
11964{
11965 int l,len;
11966 char_u *newbuf;
11967
11968 len = *fnamelen;
11969
11970 l = GetShortPathName(*fnamep, *fnamep, len);
11971 if (l > len - 1)
11972 {
11973 /* If that doesn't work (not enough space), then save the string
11974 * and try again with a new buffer big enough
11975 */
11976 newbuf = vim_strnsave(*fnamep, l);
11977 if (newbuf == NULL)
11978 return 0;
11979
11980 vim_free(*bufp);
11981 *fnamep = *bufp = newbuf;
11982
11983 l = GetShortPathName(*fnamep,*fnamep,l+1);
11984
11985 /* Really should always succeed, as the buffer is big enough */
11986 }
11987
11988 *fnamelen = l;
11989 return 1;
11990}
11991
11992/*
11993 * Create a short path name. Returns the length of the buffer it needs.
11994 * Doesn't copy over the end of the buffer passed in.
11995 */
11996 static int
11997shortpath_for_invalid_fname(fname, bufp, fnamelen)
11998 char_u **fname;
11999 char_u **bufp;
12000 int *fnamelen;
12001{
12002 char_u *s, *p, *pbuf2, *pbuf3;
12003 char_u ch;
12004 int l,len,len2,plen,slen;
12005
12006 /* Make a copy */
12007 len2 = *fnamelen;
12008 pbuf2 = vim_strnsave(*fname, len2);
12009 pbuf3 = NULL;
12010
12011 s = pbuf2 + len2 - 1; /* Find the end */
12012 slen = 1;
12013 plen = len2;
12014
12015 l = 0;
Bram Moolenaar1cd871b2004-12-19 22:46:22 +000012016 if (after_pathsep(pbuf2, s + 1))
Bram Moolenaar071d4272004-06-13 20:20:40 +000012017 {
12018 --s;
12019 ++slen;
12020 --plen;
12021 }
12022
12023 do
12024 {
12025 /* Go back one path-seperator */
Bram Moolenaar1cd871b2004-12-19 22:46:22 +000012026 while (s > pbuf2 && !after_pathsep(pbuf2, s + 1))
Bram Moolenaar071d4272004-06-13 20:20:40 +000012027 {
12028 --s;
12029 ++slen;
12030 --plen;
12031 }
12032 if (s <= pbuf2)
12033 break;
12034
12035 /* Remeber the character that is about to be blatted */
12036 ch = *s;
12037 *s = 0; /* get_short_pathname requires a null-terminated string */
12038
12039 /* Try it in situ */
12040 p = pbuf2;
12041 if (!get_short_pathname(&p, &pbuf3, &plen))
12042 {
12043 vim_free(pbuf2);
12044 return -1;
12045 }
12046 *s = ch; /* Preserve the string */
12047 } while (plen == 0);
12048
12049 if (plen > 0)
12050 {
12051 /* Remeber the length of the new string. */
12052 *fnamelen = len = plen + slen;
12053 vim_free(*bufp);
12054 if (len > len2)
12055 {
12056 /* If there's not enough space in the currently allocated string,
12057 * then copy it to a buffer big enough.
12058 */
12059 *fname= *bufp = vim_strnsave(p, len);
12060 if (*fname == NULL)
12061 return -1;
12062 }
12063 else
12064 {
12065 /* Transfer pbuf2 to being the main buffer (it's big enough) */
12066 *fname = *bufp = pbuf2;
12067 if (p != pbuf2)
12068 strncpy(*fname, p, plen);
12069 pbuf2 = NULL;
12070 }
12071 /* Concat the next bit */
12072 strncpy(*fname + plen, s, slen);
12073 (*fname)[len] = '\0';
12074 }
12075 vim_free(pbuf3);
12076 vim_free(pbuf2);
12077 return 0;
12078}
12079
12080/*
12081 * Get a pathname for a partial path.
12082 */
12083 static int
12084shortpath_for_partial(fnamep, bufp, fnamelen)
12085 char_u **fnamep;
12086 char_u **bufp;
12087 int *fnamelen;
12088{
12089 int sepcount, len, tflen;
12090 char_u *p;
12091 char_u *pbuf, *tfname;
12092 int hasTilde;
12093
12094 /* Count up the path seperators from the RHS.. so we know which part
12095 * of the path to return.
12096 */
12097 sepcount = 0;
Bram Moolenaar1cd871b2004-12-19 22:46:22 +000012098 for (p = *fnamep; p < *fnamep + *fnamelen; mb_ptr_adv(p))
Bram Moolenaar071d4272004-06-13 20:20:40 +000012099 if (vim_ispathsep(*p))
12100 ++sepcount;
12101
12102 /* Need full path first (use expand_env() to remove a "~/") */
12103 hasTilde = (**fnamep == '~');
12104 if (hasTilde)
12105 pbuf = tfname = expand_env_save(*fnamep);
12106 else
12107 pbuf = tfname = FullName_save(*fnamep, FALSE);
12108
12109 len = tflen = STRLEN(tfname);
12110
12111 if (!get_short_pathname(&tfname, &pbuf, &len))
12112 return -1;
12113
12114 if (len == 0)
12115 {
12116 /* Don't have a valid filename, so shorten the rest of the
12117 * path if we can. This CAN give us invalid 8.3 filenames, but
12118 * there's not a lot of point in guessing what it might be.
12119 */
12120 len = tflen;
12121 if (shortpath_for_invalid_fname(&tfname, &pbuf, &len) == -1)
12122 return -1;
12123 }
12124
12125 /* Count the paths backward to find the beginning of the desired string. */
12126 for (p = tfname + len - 1; p >= tfname; --p)
Bram Moolenaar1cd871b2004-12-19 22:46:22 +000012127 {
12128#ifdef FEAT_MBYTE
12129 if (has_mbyte)
12130 p -= mb_head_off(tfname, p);
12131#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000012132 if (vim_ispathsep(*p))
12133 {
12134 if (sepcount == 0 || (hasTilde && sepcount == 1))
12135 break;
12136 else
12137 sepcount --;
12138 }
Bram Moolenaar1cd871b2004-12-19 22:46:22 +000012139 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000012140 if (hasTilde)
12141 {
12142 --p;
12143 if (p >= tfname)
12144 *p = '~';
12145 else
12146 return -1;
12147 }
12148 else
12149 ++p;
12150
12151 /* Copy in the string - p indexes into tfname - allocated at pbuf */
12152 vim_free(*bufp);
12153 *fnamelen = (int)STRLEN(p);
12154 *bufp = pbuf;
12155 *fnamep = p;
12156
12157 return 0;
12158}
12159#endif /* WIN3264 */
12160
12161/*
12162 * Adjust a filename, according to a string of modifiers.
12163 * *fnamep must be NUL terminated when called. When returning, the length is
12164 * determined by *fnamelen.
12165 * Returns valid flags.
12166 * When there is an error, *fnamep is set to NULL.
12167 */
12168 int
12169modify_fname(src, usedlen, fnamep, bufp, fnamelen)
12170 char_u *src; /* string with modifiers */
12171 int *usedlen; /* characters after src that are used */
12172 char_u **fnamep; /* file name so far */
12173 char_u **bufp; /* buffer for allocated file name or NULL */
12174 int *fnamelen; /* length of fnamep */
12175{
12176 int valid = 0;
12177 char_u *tail;
12178 char_u *s, *p, *pbuf;
12179 char_u dirname[MAXPATHL];
12180 int c;
12181 int has_fullname = 0;
12182#ifdef WIN3264
12183 int has_shortname = 0;
12184#endif
12185
12186repeat:
12187 /* ":p" - full path/file_name */
12188 if (src[*usedlen] == ':' && src[*usedlen + 1] == 'p')
12189 {
12190 has_fullname = 1;
12191
12192 valid |= VALID_PATH;
12193 *usedlen += 2;
12194
12195 /* Expand "~/path" for all systems and "~user/path" for Unix and VMS */
12196 if ((*fnamep)[0] == '~'
12197#if !defined(UNIX) && !(defined(VMS) && defined(USER_HOME))
12198 && ((*fnamep)[1] == '/'
12199# ifdef BACKSLASH_IN_FILENAME
12200 || (*fnamep)[1] == '\\'
12201# endif
12202 || (*fnamep)[1] == NUL)
12203
12204#endif
12205 )
12206 {
12207 *fnamep = expand_env_save(*fnamep);
12208 vim_free(*bufp); /* free any allocated file name */
12209 *bufp = *fnamep;
12210 if (*fnamep == NULL)
12211 return -1;
12212 }
12213
12214 /* When "/." or "/.." is used: force expansion to get rid of it. */
Bram Moolenaar1cd871b2004-12-19 22:46:22 +000012215 for (p = *fnamep; *p != NUL; mb_ptr_adv(p))
Bram Moolenaar071d4272004-06-13 20:20:40 +000012216 {
12217 if (vim_ispathsep(*p)
12218 && p[1] == '.'
12219 && (p[2] == NUL
12220 || vim_ispathsep(p[2])
12221 || (p[2] == '.'
12222 && (p[3] == NUL || vim_ispathsep(p[3])))))
12223 break;
12224 }
12225
12226 /* FullName_save() is slow, don't use it when not needed. */
12227 if (*p != NUL || !vim_isAbsName(*fnamep))
12228 {
12229 *fnamep = FullName_save(*fnamep, *p != NUL);
12230 vim_free(*bufp); /* free any allocated file name */
12231 *bufp = *fnamep;
12232 if (*fnamep == NULL)
12233 return -1;
12234 }
12235
12236 /* Append a path separator to a directory. */
12237 if (mch_isdir(*fnamep))
12238 {
12239 /* Make room for one or two extra characters. */
12240 *fnamep = vim_strnsave(*fnamep, (int)STRLEN(*fnamep) + 2);
12241 vim_free(*bufp); /* free any allocated file name */
12242 *bufp = *fnamep;
12243 if (*fnamep == NULL)
12244 return -1;
12245 add_pathsep(*fnamep);
12246 }
12247 }
12248
12249 /* ":." - path relative to the current directory */
12250 /* ":~" - path relative to the home directory */
12251 /* ":8" - shortname path - postponed till after */
12252 while (src[*usedlen] == ':'
12253 && ((c = src[*usedlen + 1]) == '.' || c == '~' || c == '8'))
12254 {
12255 *usedlen += 2;
12256 if (c == '8')
12257 {
12258#ifdef WIN3264
12259 has_shortname = 1; /* Postpone this. */
12260#endif
12261 continue;
12262 }
12263 pbuf = NULL;
12264 /* Need full path first (use expand_env() to remove a "~/") */
12265 if (!has_fullname)
12266 {
12267 if (c == '.' && **fnamep == '~')
12268 p = pbuf = expand_env_save(*fnamep);
12269 else
12270 p = pbuf = FullName_save(*fnamep, FALSE);
12271 }
12272 else
12273 p = *fnamep;
12274
12275 has_fullname = 0;
12276
12277 if (p != NULL)
12278 {
12279 if (c == '.')
12280 {
12281 mch_dirname(dirname, MAXPATHL);
12282 s = shorten_fname(p, dirname);
12283 if (s != NULL)
12284 {
12285 *fnamep = s;
12286 if (pbuf != NULL)
12287 {
12288 vim_free(*bufp); /* free any allocated file name */
12289 *bufp = pbuf;
12290 pbuf = NULL;
12291 }
12292 }
12293 }
12294 else
12295 {
12296 home_replace(NULL, p, dirname, MAXPATHL, TRUE);
12297 /* Only replace it when it starts with '~' */
12298 if (*dirname == '~')
12299 {
12300 s = vim_strsave(dirname);
12301 if (s != NULL)
12302 {
12303 *fnamep = s;
12304 vim_free(*bufp);
12305 *bufp = s;
12306 }
12307 }
12308 }
12309 vim_free(pbuf);
12310 }
12311 }
12312
12313 tail = gettail(*fnamep);
12314 *fnamelen = (int)STRLEN(*fnamep);
12315
12316 /* ":h" - head, remove "/file_name", can be repeated */
12317 /* Don't remove the first "/" or "c:\" */
12318 while (src[*usedlen] == ':' && src[*usedlen + 1] == 'h')
12319 {
12320 valid |= VALID_HEAD;
12321 *usedlen += 2;
12322 s = get_past_head(*fnamep);
Bram Moolenaar1cd871b2004-12-19 22:46:22 +000012323 while (tail > s && after_pathsep(s, tail))
Bram Moolenaar071d4272004-06-13 20:20:40 +000012324 --tail;
12325 *fnamelen = (int)(tail - *fnamep);
12326#ifdef VMS
12327 if (*fnamelen > 0)
12328 *fnamelen += 1; /* the path separator is part of the path */
12329#endif
Bram Moolenaar1cd871b2004-12-19 22:46:22 +000012330 while (tail > s && !after_pathsep(s, tail))
12331 mb_ptr_back(*fnamep, tail);
Bram Moolenaar071d4272004-06-13 20:20:40 +000012332 }
12333
12334 /* ":8" - shortname */
12335 if (src[*usedlen] == ':' && src[*usedlen + 1] == '8')
12336 {
12337 *usedlen += 2;
12338#ifdef WIN3264
12339 has_shortname = 1;
12340#endif
12341 }
12342
12343#ifdef WIN3264
12344 /* Check shortname after we have done 'heads' and before we do 'tails'
12345 */
12346 if (has_shortname)
12347 {
12348 pbuf = NULL;
12349 /* Copy the string if it is shortened by :h */
12350 if (*fnamelen < (int)STRLEN(*fnamep))
12351 {
12352 p = vim_strnsave(*fnamep, *fnamelen);
12353 if (p == 0)
12354 return -1;
12355 vim_free(*bufp);
12356 *bufp = *fnamep = p;
12357 }
12358
12359 /* Split into two implementations - makes it easier. First is where
12360 * there isn't a full name already, second is where there is.
12361 */
12362 if (!has_fullname && !vim_isAbsName(*fnamep))
12363 {
12364 if (shortpath_for_partial(fnamep, bufp, fnamelen) == -1)
12365 return -1;
12366 }
12367 else
12368 {
12369 int l;
12370
12371 /* Simple case, already have the full-name
12372 * Nearly always shorter, so try first time. */
12373 l = *fnamelen;
12374 if (!get_short_pathname(fnamep, bufp, &l))
12375 return -1;
12376
12377 if (l == 0)
12378 {
12379 /* Couldn't find the filename.. search the paths.
12380 */
12381 l = *fnamelen;
12382 if (shortpath_for_invalid_fname(fnamep, bufp, &l ) == -1)
12383 return -1;
12384 }
12385 *fnamelen = l;
12386 }
12387 }
12388#endif /* WIN3264 */
12389
12390 /* ":t" - tail, just the basename */
12391 if (src[*usedlen] == ':' && src[*usedlen + 1] == 't')
12392 {
12393 *usedlen += 2;
12394 *fnamelen -= (int)(tail - *fnamep);
12395 *fnamep = tail;
12396 }
12397
12398 /* ":e" - extension, can be repeated */
12399 /* ":r" - root, without extension, can be repeated */
12400 while (src[*usedlen] == ':'
12401 && (src[*usedlen + 1] == 'e' || src[*usedlen + 1] == 'r'))
12402 {
12403 /* find a '.' in the tail:
12404 * - for second :e: before the current fname
12405 * - otherwise: The last '.'
12406 */
12407 if (src[*usedlen + 1] == 'e' && *fnamep > tail)
12408 s = *fnamep - 2;
12409 else
12410 s = *fnamep + *fnamelen - 1;
12411 for ( ; s > tail; --s)
12412 if (s[0] == '.')
12413 break;
12414 if (src[*usedlen + 1] == 'e') /* :e */
12415 {
12416 if (s > tail)
12417 {
12418 *fnamelen += (int)(*fnamep - (s + 1));
12419 *fnamep = s + 1;
12420#ifdef VMS
12421 /* cut version from the extension */
12422 s = *fnamep + *fnamelen - 1;
12423 for ( ; s > *fnamep; --s)
12424 if (s[0] == ';')
12425 break;
12426 if (s > *fnamep)
12427 *fnamelen = s - *fnamep;
12428#endif
12429 }
12430 else if (*fnamep <= tail)
12431 *fnamelen = 0;
12432 }
12433 else /* :r */
12434 {
12435 if (s > tail) /* remove one extension */
12436 *fnamelen = (int)(s - *fnamep);
12437 }
12438 *usedlen += 2;
12439 }
12440
12441 /* ":s?pat?foo?" - substitute */
12442 /* ":gs?pat?foo?" - global substitute */
12443 if (src[*usedlen] == ':'
12444 && (src[*usedlen + 1] == 's'
12445 || (src[*usedlen + 1] == 'g' && src[*usedlen + 2] == 's')))
12446 {
12447 char_u *str;
12448 char_u *pat;
12449 char_u *sub;
12450 int sep;
12451 char_u *flags;
12452 int didit = FALSE;
12453
12454 flags = (char_u *)"";
12455 s = src + *usedlen + 2;
12456 if (src[*usedlen + 1] == 'g')
12457 {
12458 flags = (char_u *)"g";
12459 ++s;
12460 }
12461
12462 sep = *s++;
12463 if (sep)
12464 {
12465 /* find end of pattern */
12466 p = vim_strchr(s, sep);
12467 if (p != NULL)
12468 {
12469 pat = vim_strnsave(s, (int)(p - s));
12470 if (pat != NULL)
12471 {
12472 s = p + 1;
12473 /* find end of substitution */
12474 p = vim_strchr(s, sep);
12475 if (p != NULL)
12476 {
12477 sub = vim_strnsave(s, (int)(p - s));
12478 str = vim_strnsave(*fnamep, *fnamelen);
12479 if (sub != NULL && str != NULL)
12480 {
12481 *usedlen = (int)(p + 1 - src);
12482 s = do_string_sub(str, pat, sub, flags);
12483 if (s != NULL)
12484 {
12485 *fnamep = s;
12486 *fnamelen = (int)STRLEN(s);
12487 vim_free(*bufp);
12488 *bufp = s;
12489 didit = TRUE;
12490 }
12491 }
12492 vim_free(sub);
12493 vim_free(str);
12494 }
12495 vim_free(pat);
12496 }
12497 }
12498 /* after using ":s", repeat all the modifiers */
12499 if (didit)
12500 goto repeat;
12501 }
12502 }
12503
12504 return valid;
12505}
12506
12507/*
12508 * Perform a substitution on "str" with pattern "pat" and substitute "sub".
12509 * "flags" can be "g" to do a global substitute.
12510 * Returns an allocated string, NULL for error.
12511 */
12512 char_u *
12513do_string_sub(str, pat, sub, flags)
12514 char_u *str;
12515 char_u *pat;
12516 char_u *sub;
12517 char_u *flags;
12518{
12519 int sublen;
12520 regmatch_T regmatch;
12521 int i;
12522 int do_all;
12523 char_u *tail;
12524 garray_T ga;
12525 char_u *ret;
12526 char_u *save_cpo;
12527
12528 /* Make 'cpoptions' empty, so that the 'l' flag doesn't work here */
12529 save_cpo = p_cpo;
12530 p_cpo = (char_u *)"";
12531
12532 ga_init2(&ga, 1, 200);
12533
12534 do_all = (flags[0] == 'g');
12535
12536 regmatch.rm_ic = p_ic;
12537 regmatch.regprog = vim_regcomp(pat, RE_MAGIC + RE_STRING);
12538 if (regmatch.regprog != NULL)
12539 {
12540 tail = str;
12541 while (vim_regexec_nl(&regmatch, str, (colnr_T)(tail - str)))
12542 {
12543 /*
12544 * Get some space for a temporary buffer to do the substitution
12545 * into. It will contain:
12546 * - The text up to where the match is.
12547 * - The substituted text.
12548 * - The text after the match.
12549 */
12550 sublen = vim_regsub(&regmatch, sub, tail, FALSE, TRUE, FALSE);
12551 if (ga_grow(&ga, (int)(STRLEN(tail) + sublen -
12552 (regmatch.endp[0] - regmatch.startp[0]))) == FAIL)
12553 {
12554 ga_clear(&ga);
12555 break;
12556 }
12557
12558 /* copy the text up to where the match is */
12559 i = (int)(regmatch.startp[0] - tail);
12560 mch_memmove((char_u *)ga.ga_data + ga.ga_len, tail, (size_t)i);
12561 /* add the substituted text */
12562 (void)vim_regsub(&regmatch, sub, (char_u *)ga.ga_data
12563 + ga.ga_len + i, TRUE, TRUE, FALSE);
12564 ga.ga_len += i + sublen - 1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012565 /* avoid getting stuck on a match with an empty string */
12566 if (tail == regmatch.endp[0])
12567 {
12568 if (*tail == NUL)
12569 break;
12570 *((char_u *)ga.ga_data + ga.ga_len) = *tail++;
12571 ++ga.ga_len;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012572 }
12573 else
12574 {
12575 tail = regmatch.endp[0];
12576 if (*tail == NUL)
12577 break;
12578 }
12579 if (!do_all)
12580 break;
12581 }
12582
12583 if (ga.ga_data != NULL)
12584 STRCPY((char *)ga.ga_data + ga.ga_len, tail);
12585
12586 vim_free(regmatch.regprog);
12587 }
12588
12589 ret = vim_strsave(ga.ga_data == NULL ? str : (char_u *)ga.ga_data);
12590 ga_clear(&ga);
12591 p_cpo = save_cpo;
12592
12593 return ret;
12594}
12595
12596#endif /* defined(FEAT_MODIFY_FNAME) || defined(FEAT_EVAL) */