blob: 1aa4dc307c1408b73eac83ff09e53568cb224cf7 [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
Bram Moolenaar33570922005-01-25 22:26:29 +000033#define DICT_MAXNEST 100 /* maximum nesting of lists and dicts */
Bram Moolenaar071d4272004-06-13 20:20:40 +000034
35/*
Bram Moolenaar33570922005-01-25 22:26:29 +000036 * In a hashtab item "hi_key" points to "di_key" in a dictitem.
37 * This avoids adding a pointer to the hashtab item.
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000038 * DI2HIKEY() converts a dictitem pointer to a hashitem key pointer.
39 * HIKEY2DI() converts a hashitem key pointer to a dictitem pointer.
40 * HI2DI() converts a hashitem pointer to a dictitem pointer.
41 */
Bram Moolenaar33570922005-01-25 22:26:29 +000042static dictitem_T dumdi;
Bram Moolenaara7043832005-01-21 11:56:39 +000043#define DI2HIKEY(di) ((di)->di_key)
Bram Moolenaar33570922005-01-25 22:26:29 +000044#define HIKEY2DI(p) ((dictitem_T *)(p - (dumdi.di_key - (char_u *)&dumdi)))
Bram Moolenaara7043832005-01-21 11:56:39 +000045#define HI2DI(hi) HIKEY2DI((hi)->hi_key)
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000046
47/*
Bram Moolenaar7480b5c2005-01-16 22:07:38 +000048 * Structure returned by get_lval() and used by set_var_lval().
49 * For a plain name:
50 * "name" points to the variable name.
51 * "exp_name" is NULL.
52 * "tv" is NULL
53 * For a magic braces name:
54 * "name" points to the expanded variable name.
55 * "exp_name" is non-NULL, to be freed later.
56 * "tv" is NULL
57 * For an index in a list:
58 * "name" points to the (expanded) variable name.
59 * "exp_name" NULL or non-NULL, to be freed later.
60 * "tv" points to the (first) list item value
61 * "li" points to the (first) list item
62 * "range", "n1", "n2" and "empty2" indicate what items are used.
63 * For an existing Dict item:
64 * "name" points to the (expanded) variable name.
65 * "exp_name" NULL or non-NULL, to be freed later.
66 * "tv" points to the dict item value
67 * "newkey" is NULL
68 * For a non-existing Dict item:
69 * "name" points to the (expanded) variable name.
70 * "exp_name" NULL or non-NULL, to be freed later.
Bram Moolenaar33570922005-01-25 22:26:29 +000071 * "tv" points to the Dictionary typval_T
Bram Moolenaar7480b5c2005-01-16 22:07:38 +000072 * "newkey" is the key for the new item.
73 */
74typedef struct lval_S
75{
76 char_u *ll_name; /* start of variable name (can be NULL) */
77 char_u *ll_exp_name; /* NULL or expanded name in allocated memory. */
Bram Moolenaar33570922005-01-25 22:26:29 +000078 typval_T *ll_tv; /* Typeval of item being used. If "newkey"
Bram Moolenaar7480b5c2005-01-16 22:07:38 +000079 isn't NULL it's the Dict to which to add
80 the item. */
Bram Moolenaar33570922005-01-25 22:26:29 +000081 listitem_T *ll_li; /* The list item or NULL. */
82 list_T *ll_list; /* The list or NULL. */
Bram Moolenaar7480b5c2005-01-16 22:07:38 +000083 int ll_range; /* TRUE when a [i:j] range was used */
84 long ll_n1; /* First index for list */
85 long ll_n2; /* Second index for list range */
86 int ll_empty2; /* Second index is empty: [i:] */
Bram Moolenaar33570922005-01-25 22:26:29 +000087 dict_T *ll_dict; /* The Dictionary or NULL */
88 dictitem_T *ll_di; /* The dictitem or NULL */
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000089 char_u *ll_newkey; /* New key for Dict in alloc. mem or NULL. */
Bram Moolenaar33570922005-01-25 22:26:29 +000090} lval_T;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +000091
Bram Moolenaar8c711452005-01-14 21:53:12 +000092
Bram Moolenaarc70646c2005-01-04 21:52:38 +000093static char *e_letunexp = N_("E18: Unexpected characters in :let");
Bram Moolenaare49b69a2005-01-08 16:11:57 +000094static char *e_listidx = N_("E684: list index out of range: %ld");
Bram Moolenaarc70646c2005-01-04 21:52:38 +000095static char *e_undefvar = N_("E121: Undefined variable: %s");
96static char *e_missbrac = N_("E111: Missing ']'");
Bram Moolenaar8c711452005-01-14 21:53:12 +000097static char *e_listarg = N_("E686: Argument of %s must be a List");
Bram Moolenaare9a41262005-01-15 22:18:47 +000098static char *e_listdictarg = N_("E712: Argument of %s must be a List or Dictionaary");
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000099static char *e_emptykey = N_("E713: Cannot use empty key for Dictionary");
Bram Moolenaar9ef486d2005-01-17 22:23:00 +0000100static char *e_listreq = N_("E714: List required");
101static char *e_dictreq = N_("E715: Dictionary required");
Bram Moolenaar8c711452005-01-14 21:53:12 +0000102static char *e_toomanyarg = N_("E118: Too many arguments for function: %s");
Bram Moolenaar9ef486d2005-01-17 22:23:00 +0000103static char *e_dictkey = N_("E716: Key not present in Dictionary: %s");
104static char *e_funcexts = N_("E122: Function %s already exists, add ! to replace it");
105static char *e_funcdict = N_("E717: Dictionary entry already exists");
106static char *e_funcref = N_("E718: Funcref required");
107static char *e_dictrange = N_("E719: Cannot use [:] with a Dictionary");
108static char *e_letwrong = N_("E734: Wrong variable type for %s=");
Bram Moolenaar49cd9572005-01-03 21:06:01 +0000109
110/*
Bram Moolenaar33570922005-01-25 22:26:29 +0000111 * All user-defined global variables are stored in dictionary "globvardict".
112 * "globvars_var" is the variable that is used for "g:".
Bram Moolenaar071d4272004-06-13 20:20:40 +0000113 */
Bram Moolenaar33570922005-01-25 22:26:29 +0000114static dict_T globvardict;
115static dictitem_T globvars_var;
116#define globvarht globvardict.dv_hashtab
Bram Moolenaar071d4272004-06-13 20:20:40 +0000117
118/*
Bram Moolenaar532c7802005-01-27 14:44:31 +0000119 * Old Vim variables such as "v:version" are also available without the "v:".
120 * Also in functions. We need a special hashtable for them.
121 */
122hashtab_T compat_hashtab;
123
124/*
Bram Moolenaar33570922005-01-25 22:26:29 +0000125 * Array to hold the hashtab with variables local to each sourced script.
126 * Each item holds a variable (nameless) that points to the dict_T.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000127 */
Bram Moolenaar33570922005-01-25 22:26:29 +0000128typedef struct
129{
130 dictitem_T sv_var;
131 dict_T sv_dict;
132} scriptvar_T;
133
134static garray_T ga_scripts = {0, 0, sizeof(scriptvar_T), 4, NULL};
135#define SCRIPT_SV(id) (((scriptvar_T *)ga_scripts.ga_data)[(id) - 1])
136#define SCRIPT_VARS(id) (SCRIPT_SV(id).sv_dict.dv_hashtab)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000137
138static int echo_attr = 0; /* attributes used for ":echo" */
139
Bram Moolenaar9ef486d2005-01-17 22:23:00 +0000140/* Values for trans_function_name() argument: */
141#define TFN_INT 1 /* internal function name OK */
142#define TFN_QUIET 2 /* no error messages */
143
Bram Moolenaar071d4272004-06-13 20:20:40 +0000144/*
145 * Structure to hold info for a user function.
146 */
147typedef struct ufunc ufunc_T;
148
149struct ufunc
150{
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000151 int uf_varargs; /* variable nr of arguments */
152 int uf_flags;
153 int uf_calls; /* nr of active calls */
154 garray_T uf_args; /* arguments */
155 garray_T uf_lines; /* function lines */
156 scid_T uf_script_ID; /* ID of script where function was defined,
Bram Moolenaar071d4272004-06-13 20:20:40 +0000157 used for s: variables */
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000158 int uf_refcount; /* for numbered function: reference count */
159 char_u uf_name[1]; /* name of function (actually longer); can
160 start with <SNR>123_ (<SNR> is K_SPECIAL
161 KS_EXTRA KE_SNR) */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000162};
163
164/* function flags */
165#define FC_ABORT 1 /* abort function on error */
166#define FC_RANGE 2 /* function accepts range */
Bram Moolenaare9a41262005-01-15 22:18:47 +0000167#define FC_DICT 4 /* Dict function, uses "self" */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000168
169/*
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000170 * All user-defined functions are found in this hash table.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000171 */
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000172hashtab_T func_hashtab;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000173
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000174/* From user function to hashitem and back. */
175static ufunc_T dumuf;
176#define UF2HIKEY(fp) ((fp)->uf_name)
177#define HIKEY2UF(p) ((ufunc_T *)(p - (dumuf.uf_name - (char_u *)&dumuf)))
178#define HI2UF(hi) HIKEY2UF((hi)->hi_key)
179
180#define FUNCARG(fp, j) ((char_u **)(fp->uf_args.ga_data))[j]
181#define FUNCLINE(fp, j) ((char_u **)(fp->uf_lines.ga_data))[j]
Bram Moolenaar071d4272004-06-13 20:20:40 +0000182
Bram Moolenaar33570922005-01-25 22:26:29 +0000183#define MAX_FUNC_ARGS 20 /* maximum number of function arguments */
184#define VAR_SHORT_LEN 20 /* short variable name length */
185#define FIXVAR_CNT 12 /* number of fixed variables */
186
Bram Moolenaar071d4272004-06-13 20:20:40 +0000187/* structure to hold info for a function that is currently being executed. */
Bram Moolenaar33570922005-01-25 22:26:29 +0000188typedef struct funccall_S
Bram Moolenaar071d4272004-06-13 20:20:40 +0000189{
190 ufunc_T *func; /* function being called */
191 int linenr; /* next line to be executed */
192 int returned; /* ":return" used */
Bram Moolenaar33570922005-01-25 22:26:29 +0000193 struct /* fixed variables for arguments */
194 {
195 dictitem_T var; /* variable (without room for name) */
196 char_u room[VAR_SHORT_LEN]; /* room for the name */
197 } fixvar[FIXVAR_CNT];
198 dict_T l_vars; /* l: local function variables */
199 dictitem_T l_vars_var; /* variable for l: scope */
200 dict_T l_avars; /* a: argument variables */
201 dictitem_T l_avars_var; /* variable for a: scope */
202 list_T l_varlist; /* list for a:000 */
203 listitem_T l_listitems[MAX_FUNC_ARGS]; /* listitems for a:000 */
204 typval_T *rettv; /* return value */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000205 linenr_T breakpoint; /* next line with breakpoint or zero */
206 int dbg_tick; /* debug_tick when breakpoint was set */
207 int level; /* top nesting level of executed function */
Bram Moolenaar33570922005-01-25 22:26:29 +0000208} funccall_T;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000209
210/*
Bram Moolenaar3d60ec22005-01-05 22:19:46 +0000211 * Info used by a ":for" loop.
212 */
Bram Moolenaar33570922005-01-25 22:26:29 +0000213typedef struct
Bram Moolenaar3d60ec22005-01-05 22:19:46 +0000214{
215 int fi_semicolon; /* TRUE if ending in '; var]' */
216 int fi_varcount; /* nr of variables in the list */
Bram Moolenaar33570922005-01-25 22:26:29 +0000217 listwatch_T fi_lw; /* keep an eye on the item used. */
218 list_T *fi_list; /* list being used */
219} forinfo_T;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +0000220
Bram Moolenaar3d60ec22005-01-05 22:19:46 +0000221/*
Bram Moolenaar9ef486d2005-01-17 22:23:00 +0000222 * Struct used by trans_function_name()
223 */
224typedef struct
225{
Bram Moolenaar33570922005-01-25 22:26:29 +0000226 dict_T *fd_dict; /* Dictionary used */
Bram Moolenaar532c7802005-01-27 14:44:31 +0000227 char_u *fd_newkey; /* new key in "dict" in allocated memory */
Bram Moolenaar33570922005-01-25 22:26:29 +0000228 dictitem_T *fd_di; /* Dictionary item used */
229} funcdict_T;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +0000230
Bram Moolenaara7043832005-01-21 11:56:39 +0000231
232/*
Bram Moolenaar33570922005-01-25 22:26:29 +0000233 * Array to hold the value of v: variables.
234 * The value is in a dictitem, so that it can also be used in the v: scope.
235 * The reason to use this table anyway is for very quick access to the
236 * variables with the VV_ defines.
237 */
238#include "version.h"
239
240/* values for vv_flags: */
241#define VV_COMPAT 1 /* compatible, also used without "v:" */
242#define VV_RO 2 /* read-only */
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +0000243#define VV_RO_SBX 4 /* read-only in the sandbox */
Bram Moolenaar33570922005-01-25 22:26:29 +0000244
245#define VV_NAME(s, t) s, sizeof(s) - 1, {{t}}, {0}
246
247static struct vimvar
248{
249 char *vv_name; /* name of variable, without v: */
250 int vv_len; /* length of name */
251 dictitem_T vv_di; /* value and name for key */
252 char vv_filler[16]; /* space for LONGEST name below!!! */
253 char vv_flags; /* VV_COMPAT, VV_RO, VV_RO_SBX */
254} vimvars[VV_LEN] =
255{
256 /*
257 * The order here must match the VV_ defines in vim.h!
258 * Initializing a union does not work, leave tv.vval empty to get zero's.
259 */
260 {VV_NAME("count", VAR_NUMBER), VV_COMPAT+VV_RO},
261 {VV_NAME("count1", VAR_NUMBER), VV_RO},
262 {VV_NAME("prevcount", VAR_NUMBER), VV_RO},
263 {VV_NAME("errmsg", VAR_STRING), VV_COMPAT},
264 {VV_NAME("warningmsg", VAR_STRING), 0},
265 {VV_NAME("statusmsg", VAR_STRING), 0},
266 {VV_NAME("shell_error", VAR_NUMBER), VV_COMPAT+VV_RO},
267 {VV_NAME("this_session", VAR_STRING), VV_COMPAT},
268 {VV_NAME("version", VAR_NUMBER), VV_COMPAT+VV_RO},
269 {VV_NAME("lnum", VAR_NUMBER), VV_RO_SBX},
270 {VV_NAME("termresponse", VAR_STRING), VV_RO},
271 {VV_NAME("fname", VAR_STRING), VV_RO},
272 {VV_NAME("lang", VAR_STRING), VV_RO},
273 {VV_NAME("lc_time", VAR_STRING), VV_RO},
274 {VV_NAME("ctype", VAR_STRING), VV_RO},
275 {VV_NAME("charconvert_from", VAR_STRING), VV_RO},
276 {VV_NAME("charconvert_to", VAR_STRING), VV_RO},
277 {VV_NAME("fname_in", VAR_STRING), VV_RO},
278 {VV_NAME("fname_out", VAR_STRING), VV_RO},
279 {VV_NAME("fname_new", VAR_STRING), VV_RO},
280 {VV_NAME("fname_diff", VAR_STRING), VV_RO},
281 {VV_NAME("cmdarg", VAR_STRING), VV_RO},
282 {VV_NAME("foldstart", VAR_NUMBER), VV_RO_SBX},
283 {VV_NAME("foldend", VAR_NUMBER), VV_RO_SBX},
284 {VV_NAME("folddashes", VAR_STRING), VV_RO_SBX},
285 {VV_NAME("foldlevel", VAR_NUMBER), VV_RO_SBX},
286 {VV_NAME("progname", VAR_STRING), VV_RO},
287 {VV_NAME("servername", VAR_STRING), VV_RO},
288 {VV_NAME("dying", VAR_NUMBER), VV_RO},
289 {VV_NAME("exception", VAR_STRING), VV_RO},
290 {VV_NAME("throwpoint", VAR_STRING), VV_RO},
291 {VV_NAME("register", VAR_STRING), VV_RO},
292 {VV_NAME("cmdbang", VAR_NUMBER), VV_RO},
293 {VV_NAME("insertmode", VAR_STRING), VV_RO},
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +0000294 {VV_NAME("val", VAR_UNKNOWN), VV_RO},
295 {VV_NAME("key", VAR_UNKNOWN), VV_RO},
Bram Moolenaar33570922005-01-25 22:26:29 +0000296};
297
298/* shorthand */
299#define vv_type vv_di.di_tv.v_type
300#define vv_nr vv_di.di_tv.vval.v_number
301#define vv_str vv_di.di_tv.vval.v_string
302#define vv_tv vv_di.di_tv
303
304/*
305 * The v: variables are stored in dictionary "vimvardict".
306 * "vimvars_var" is the variable that is used for the "l:" scope.
307 */
308static dict_T vimvardict;
309static dictitem_T vimvars_var;
310#define vimvarht vimvardict.dv_hashtab
311
312static int eval0 __ARGS((char_u *arg, typval_T *rettv, char_u **nextcmd, int evaluate));
313static int eval1 __ARGS((char_u **arg, typval_T *rettv, int evaluate));
314static int eval2 __ARGS((char_u **arg, typval_T *rettv, int evaluate));
315static int eval3 __ARGS((char_u **arg, typval_T *rettv, int evaluate));
316static int eval4 __ARGS((char_u **arg, typval_T *rettv, int evaluate));
317static int eval5 __ARGS((char_u **arg, typval_T *rettv, int evaluate));
318static int eval6 __ARGS((char_u **arg, typval_T *rettv, int evaluate));
319static int eval7 __ARGS((char_u **arg, typval_T *rettv, int evaluate));
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +0000320static int eval_index __ARGS((char_u **arg, typval_T *rettv, int evaluate, int verbose));
Bram Moolenaar33570922005-01-25 22:26:29 +0000321static int get_option_tv __ARGS((char_u **arg, typval_T *rettv, int evaluate));
322static int get_string_tv __ARGS((char_u **arg, typval_T *rettv, int evaluate));
323static int get_lit_string_tv __ARGS((char_u **arg, typval_T *rettv, int evaluate));
324static int get_list_tv __ARGS((char_u **arg, typval_T *rettv, int evaluate));
325static list_T *list_alloc __ARGS((void));
326static void list_unref __ARGS((list_T *l));
327static void list_free __ARGS((list_T *l));
328static listitem_T *listitem_alloc __ARGS((void));
329static void listitem_free __ARGS((listitem_T *item));
330static void listitem_remove __ARGS((list_T *l, listitem_T *item));
331static long list_len __ARGS((list_T *l));
332static int list_equal __ARGS((list_T *l1, list_T *l2, int ic));
333static int dict_equal __ARGS((dict_T *d1, dict_T *d2, int ic));
334static int tv_equal __ARGS((typval_T *tv1, typval_T *tv2, int ic));
335static int string_isa_number __ARGS((char_u *s));
336static listitem_T *list_find __ARGS((list_T *l, long n));
337static long list_idx_of_item __ARGS((list_T *l, listitem_T *item));
Bram Moolenaar33570922005-01-25 22:26:29 +0000338static void list_append __ARGS((list_T *l, listitem_T *item));
339static int list_append_tv __ARGS((list_T *l, typval_T *tv));
340static int list_insert_tv __ARGS((list_T *l, typval_T *tv, listitem_T *item));
341static int list_extend __ARGS((list_T *l1, list_T *l2, listitem_T *bef));
342static int list_concat __ARGS((list_T *l1, list_T *l2, typval_T *tv));
Bram Moolenaar81bf7082005-02-12 14:31:42 +0000343static list_T *list_copy __ARGS((list_T *orig, int deep, int copyID));
Bram Moolenaar33570922005-01-25 22:26:29 +0000344static void list_remove __ARGS((list_T *l, listitem_T *item, listitem_T *item2));
345static char_u *list2string __ARGS((typval_T *tv));
Bram Moolenaar81bf7082005-02-12 14:31:42 +0000346static int list_join __ARGS((garray_T *gap, list_T *l, char_u *sep, int echo));
Bram Moolenaar33570922005-01-25 22:26:29 +0000347
348static dict_T *dict_alloc __ARGS((void));
349static void dict_unref __ARGS((dict_T *d));
350static void dict_free __ARGS((dict_T *d));
351static dictitem_T *dictitem_alloc __ARGS((char_u *key));
352static dictitem_T *dictitem_copy __ARGS((dictitem_T *org));
353static void dictitem_remove __ARGS((dict_T *dict, dictitem_T *item));
354static void dictitem_free __ARGS((dictitem_T *item));
Bram Moolenaar81bf7082005-02-12 14:31:42 +0000355static dict_T *dict_copy __ARGS((dict_T *orig, int deep, int copyID));
Bram Moolenaar33570922005-01-25 22:26:29 +0000356static int dict_add __ARGS((dict_T *d, dictitem_T *item));
357static long dict_len __ARGS((dict_T *d));
358static dictitem_T *dict_find __ARGS((dict_T *d, char_u *key, int len));
359static char_u *dict2string __ARGS((typval_T *tv));
360static int get_dict_tv __ARGS((char_u **arg, typval_T *rettv, int evaluate));
361
362static char_u *echo_string __ARGS((typval_T *tv, char_u **tofree, char_u *numbuf));
363static char_u *tv2string __ARGS((typval_T *tv, char_u **tofree, char_u *numbuf));
364static char_u *string_quote __ARGS((char_u *str, int function));
365static int get_env_tv __ARGS((char_u **arg, typval_T *rettv, int evaluate));
366static int find_internal_func __ARGS((char_u *name));
367static char_u *deref_func_name __ARGS((char_u *name, int *lenp));
368static int get_func_tv __ARGS((char_u *name, int len, typval_T *rettv, char_u **arg, linenr_T firstline, linenr_T lastline, int *doesrange, int evaluate, dict_T *selfdict));
369static int call_func __ARGS((char_u *name, int len, typval_T *rettv, int argcount, typval_T *argvars, linenr_T firstline, linenr_T lastline, int *doesrange, int evaluate, dict_T *selfdict));
Bram Moolenaar81bf7082005-02-12 14:31:42 +0000370static void emsg_funcname __ARGS((char *msg, char_u *name));
Bram Moolenaar33570922005-01-25 22:26:29 +0000371
372static void f_add __ARGS((typval_T *argvars, typval_T *rettv));
373static void f_append __ARGS((typval_T *argvars, typval_T *rettv));
374static void f_argc __ARGS((typval_T *argvars, typval_T *rettv));
375static void f_argidx __ARGS((typval_T *argvars, typval_T *rettv));
376static void f_argv __ARGS((typval_T *argvars, typval_T *rettv));
377static void f_browse __ARGS((typval_T *argvars, typval_T *rettv));
378static void f_browsedir __ARGS((typval_T *argvars, typval_T *rettv));
379static void f_bufexists __ARGS((typval_T *argvars, typval_T *rettv));
380static void f_buflisted __ARGS((typval_T *argvars, typval_T *rettv));
381static void f_bufloaded __ARGS((typval_T *argvars, typval_T *rettv));
382static void f_bufname __ARGS((typval_T *argvars, typval_T *rettv));
383static void f_bufnr __ARGS((typval_T *argvars, typval_T *rettv));
384static void f_bufwinnr __ARGS((typval_T *argvars, typval_T *rettv));
385static void f_byte2line __ARGS((typval_T *argvars, typval_T *rettv));
386static void f_byteidx __ARGS((typval_T *argvars, typval_T *rettv));
387static void f_call __ARGS((typval_T *argvars, typval_T *rettv));
388static void f_char2nr __ARGS((typval_T *argvars, typval_T *rettv));
389static void f_cindent __ARGS((typval_T *argvars, typval_T *rettv));
390static void f_col __ARGS((typval_T *argvars, typval_T *rettv));
391static void f_confirm __ARGS((typval_T *argvars, typval_T *rettv));
392static void f_copy __ARGS((typval_T *argvars, typval_T *rettv));
393static void f_count __ARGS((typval_T *argvars, typval_T *rettv));
394static void f_cscope_connection __ARGS((typval_T *argvars, typval_T *rettv));
395static void f_cursor __ARGS((typval_T *argsvars, typval_T *rettv));
396static void f_deepcopy __ARGS((typval_T *argvars, typval_T *rettv));
397static void f_delete __ARGS((typval_T *argvars, typval_T *rettv));
398static void f_did_filetype __ARGS((typval_T *argvars, typval_T *rettv));
399static void f_diff_filler __ARGS((typval_T *argvars, typval_T *rettv));
400static void f_diff_hlID __ARGS((typval_T *argvars, typval_T *rettv));
401static void f_empty __ARGS((typval_T *argvars, typval_T *rettv));
402static void f_escape __ARGS((typval_T *argvars, typval_T *rettv));
403static void f_eval __ARGS((typval_T *argvars, typval_T *rettv));
404static void f_eventhandler __ARGS((typval_T *argvars, typval_T *rettv));
405static void f_executable __ARGS((typval_T *argvars, typval_T *rettv));
406static void f_exists __ARGS((typval_T *argvars, typval_T *rettv));
407static void f_expand __ARGS((typval_T *argvars, typval_T *rettv));
408static void f_extend __ARGS((typval_T *argvars, typval_T *rettv));
409static void f_filereadable __ARGS((typval_T *argvars, typval_T *rettv));
410static void f_filewritable __ARGS((typval_T *argvars, typval_T *rettv));
411static void f_filter __ARGS((typval_T *argvars, typval_T *rettv));
412static void f_finddir __ARGS((typval_T *argvars, typval_T *rettv));
413static void f_findfile __ARGS((typval_T *argvars, typval_T *rettv));
414static void f_fnamemodify __ARGS((typval_T *argvars, typval_T *rettv));
415static void f_foldclosed __ARGS((typval_T *argvars, typval_T *rettv));
416static void f_foldclosedend __ARGS((typval_T *argvars, typval_T *rettv));
417static void f_foldlevel __ARGS((typval_T *argvars, typval_T *rettv));
418static void f_foldtext __ARGS((typval_T *argvars, typval_T *rettv));
419static void f_foldtextresult __ARGS((typval_T *argvars, typval_T *rettv));
420static void f_foreground __ARGS((typval_T *argvars, typval_T *rettv));
421static void f_function __ARGS((typval_T *argvars, typval_T *rettv));
422static void f_get __ARGS((typval_T *argvars, typval_T *rettv));
423static void f_getbufvar __ARGS((typval_T *argvars, typval_T *rettv));
424static void f_getchar __ARGS((typval_T *argvars, typval_T *rettv));
425static void f_getcharmod __ARGS((typval_T *argvars, typval_T *rettv));
426static void f_getcmdline __ARGS((typval_T *argvars, typval_T *rettv));
427static void f_getcmdpos __ARGS((typval_T *argvars, typval_T *rettv));
428static void f_getcwd __ARGS((typval_T *argvars, typval_T *rettv));
429static void f_getfontname __ARGS((typval_T *argvars, typval_T *rettv));
430static void f_getfperm __ARGS((typval_T *argvars, typval_T *rettv));
431static void f_getfsize __ARGS((typval_T *argvars, typval_T *rettv));
432static void f_getftime __ARGS((typval_T *argvars, typval_T *rettv));
433static void f_getftype __ARGS((typval_T *argvars, typval_T *rettv));
434static void f_getline __ARGS((typval_T *argvars, typval_T *rettv));
435static void f_getreg __ARGS((typval_T *argvars, typval_T *rettv));
436static void f_getregtype __ARGS((typval_T *argvars, typval_T *rettv));
437static void f_getwinposx __ARGS((typval_T *argvars, typval_T *rettv));
438static void f_getwinposy __ARGS((typval_T *argvars, typval_T *rettv));
439static void f_getwinvar __ARGS((typval_T *argvars, typval_T *rettv));
440static void f_glob __ARGS((typval_T *argvars, typval_T *rettv));
441static void f_globpath __ARGS((typval_T *argvars, typval_T *rettv));
442static void f_has __ARGS((typval_T *argvars, typval_T *rettv));
443static void f_has_key __ARGS((typval_T *argvars, typval_T *rettv));
444static void f_hasmapto __ARGS((typval_T *argvars, typval_T *rettv));
445static void f_histadd __ARGS((typval_T *argvars, typval_T *rettv));
446static void f_histdel __ARGS((typval_T *argvars, typval_T *rettv));
447static void f_histget __ARGS((typval_T *argvars, typval_T *rettv));
448static void f_histnr __ARGS((typval_T *argvars, typval_T *rettv));
449static void f_hlID __ARGS((typval_T *argvars, typval_T *rettv));
450static void f_hlexists __ARGS((typval_T *argvars, typval_T *rettv));
451static void f_hostname __ARGS((typval_T *argvars, typval_T *rettv));
452static void f_iconv __ARGS((typval_T *argvars, typval_T *rettv));
453static void f_indent __ARGS((typval_T *argvars, typval_T *rettv));
454static void f_index __ARGS((typval_T *argvars, typval_T *rettv));
455static void f_input __ARGS((typval_T *argvars, typval_T *rettv));
456static void f_inputdialog __ARGS((typval_T *argvars, typval_T *rettv));
457static void f_inputrestore __ARGS((typval_T *argvars, typval_T *rettv));
458static void f_inputsave __ARGS((typval_T *argvars, typval_T *rettv));
459static void f_inputsecret __ARGS((typval_T *argvars, typval_T *rettv));
460static void f_insert __ARGS((typval_T *argvars, typval_T *rettv));
461static void f_isdirectory __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar2e6aff32005-01-31 19:25:36 +0000462static void f_islocked __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar33570922005-01-25 22:26:29 +0000463static void f_items __ARGS((typval_T *argvars, typval_T *rettv));
464static void f_join __ARGS((typval_T *argvars, typval_T *rettv));
465static void f_keys __ARGS((typval_T *argvars, typval_T *rettv));
466static void f_last_buffer_nr __ARGS((typval_T *argvars, typval_T *rettv));
467static void f_len __ARGS((typval_T *argvars, typval_T *rettv));
468static void f_libcall __ARGS((typval_T *argvars, typval_T *rettv));
469static void f_libcallnr __ARGS((typval_T *argvars, typval_T *rettv));
470static void f_line __ARGS((typval_T *argvars, typval_T *rettv));
471static void f_line2byte __ARGS((typval_T *argvars, typval_T *rettv));
472static void f_lispindent __ARGS((typval_T *argvars, typval_T *rettv));
473static void f_localtime __ARGS((typval_T *argvars, typval_T *rettv));
474static void f_map __ARGS((typval_T *argvars, typval_T *rettv));
475static void f_maparg __ARGS((typval_T *argvars, typval_T *rettv));
476static void f_mapcheck __ARGS((typval_T *argvars, typval_T *rettv));
477static void f_match __ARGS((typval_T *argvars, typval_T *rettv));
478static void f_matchend __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +0000479static void f_matchlist __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar33570922005-01-25 22:26:29 +0000480static void f_matchstr __ARGS((typval_T *argvars, typval_T *rettv));
481static void f_max __ARGS((typval_T *argvars, typval_T *rettv));
482static void f_min __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000483#ifdef vim_mkdir
484static void f_mkdir __ARGS((typval_T *argvars, typval_T *rettv));
485#endif
Bram Moolenaar33570922005-01-25 22:26:29 +0000486static void f_mode __ARGS((typval_T *argvars, typval_T *rettv));
487static void f_nextnonblank __ARGS((typval_T *argvars, typval_T *rettv));
488static void f_nr2char __ARGS((typval_T *argvars, typval_T *rettv));
489static void f_prevnonblank __ARGS((typval_T *argvars, typval_T *rettv));
490static void f_range __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +0000491static void f_readfile __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar33570922005-01-25 22:26:29 +0000492static void f_remote_expr __ARGS((typval_T *argvars, typval_T *rettv));
493static void f_remote_foreground __ARGS((typval_T *argvars, typval_T *rettv));
494static void f_remote_peek __ARGS((typval_T *argvars, typval_T *rettv));
495static void f_remote_read __ARGS((typval_T *argvars, typval_T *rettv));
496static void f_remote_send __ARGS((typval_T *argvars, typval_T *rettv));
497static void f_remove __ARGS((typval_T *argvars, typval_T *rettv));
498static void f_rename __ARGS((typval_T *argvars, typval_T *rettv));
499static void f_repeat __ARGS((typval_T *argvars, typval_T *rettv));
500static void f_resolve __ARGS((typval_T *argvars, typval_T *rettv));
501static void f_reverse __ARGS((typval_T *argvars, typval_T *rettv));
502static void f_search __ARGS((typval_T *argvars, typval_T *rettv));
503static void f_searchpair __ARGS((typval_T *argvars, typval_T *rettv));
504static void f_server2client __ARGS((typval_T *argvars, typval_T *rettv));
505static void f_serverlist __ARGS((typval_T *argvars, typval_T *rettv));
506static void f_setbufvar __ARGS((typval_T *argvars, typval_T *rettv));
507static void f_setcmdpos __ARGS((typval_T *argvars, typval_T *rettv));
508static void f_setline __ARGS((typval_T *argvars, typval_T *rettv));
509static void f_setreg __ARGS((typval_T *argvars, typval_T *rettv));
510static void f_setwinvar __ARGS((typval_T *argvars, typval_T *rettv));
511static void f_simplify __ARGS((typval_T *argvars, typval_T *rettv));
512static void f_sort __ARGS((typval_T *argvars, typval_T *rettv));
513static void f_split __ARGS((typval_T *argvars, typval_T *rettv));
514#ifdef HAVE_STRFTIME
515static void f_strftime __ARGS((typval_T *argvars, typval_T *rettv));
516#endif
517static void f_stridx __ARGS((typval_T *argvars, typval_T *rettv));
518static void f_string __ARGS((typval_T *argvars, typval_T *rettv));
519static void f_strlen __ARGS((typval_T *argvars, typval_T *rettv));
520static void f_strpart __ARGS((typval_T *argvars, typval_T *rettv));
521static void f_strridx __ARGS((typval_T *argvars, typval_T *rettv));
522static void f_strtrans __ARGS((typval_T *argvars, typval_T *rettv));
523static void f_submatch __ARGS((typval_T *argvars, typval_T *rettv));
524static void f_substitute __ARGS((typval_T *argvars, typval_T *rettv));
525static void f_synID __ARGS((typval_T *argvars, typval_T *rettv));
526static void f_synIDattr __ARGS((typval_T *argvars, typval_T *rettv));
527static void f_synIDtrans __ARGS((typval_T *argvars, typval_T *rettv));
528static void f_system __ARGS((typval_T *argvars, typval_T *rettv));
529static void f_tempname __ARGS((typval_T *argvars, typval_T *rettv));
530static void f_tolower __ARGS((typval_T *argvars, typval_T *rettv));
531static void f_toupper __ARGS((typval_T *argvars, typval_T *rettv));
532static void f_tr __ARGS((typval_T *argvars, typval_T *rettv));
533static void f_type __ARGS((typval_T *argvars, typval_T *rettv));
534static void f_values __ARGS((typval_T *argvars, typval_T *rettv));
535static void f_virtcol __ARGS((typval_T *argvars, typval_T *rettv));
536static void f_visualmode __ARGS((typval_T *argvars, typval_T *rettv));
537static void f_winbufnr __ARGS((typval_T *argvars, typval_T *rettv));
538static void f_wincol __ARGS((typval_T *argvars, typval_T *rettv));
539static void f_winheight __ARGS((typval_T *argvars, typval_T *rettv));
540static void f_winline __ARGS((typval_T *argvars, typval_T *rettv));
541static void f_winnr __ARGS((typval_T *argvars, typval_T *rettv));
542static void f_winrestcmd __ARGS((typval_T *argvars, typval_T *rettv));
543static void f_winwidth __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +0000544static void f_writefile __ARGS((typval_T *argvars, typval_T *rettv));
Bram Moolenaar33570922005-01-25 22:26:29 +0000545
546static win_T *find_win_by_nr __ARGS((typval_T *vp));
547static pos_T *var2fpos __ARGS((typval_T *varp, int lnum));
548static int get_env_len __ARGS((char_u **arg));
549static int get_id_len __ARGS((char_u **arg));
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +0000550static int get_name_len __ARGS((char_u **arg, char_u **alias, int evaluate, int verbose));
Bram Moolenaar33570922005-01-25 22:26:29 +0000551static char_u *find_name_end __ARGS((char_u *arg, char_u **expr_start, char_u **expr_end, int incl_br));
552static int eval_isnamec __ARGS((int c));
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +0000553static int get_var_tv __ARGS((char_u *name, int len, typval_T *rettv, int verbose));
554static int handle_subscript __ARGS((char_u **arg, typval_T *rettv, int evaluate, int verbose));
Bram Moolenaar33570922005-01-25 22:26:29 +0000555static typval_T *alloc_tv __ARGS((void));
556static typval_T *alloc_string_tv __ARGS((char_u *string));
557static void free_tv __ARGS((typval_T *varp));
558static void clear_tv __ARGS((typval_T *varp));
559static void init_tv __ARGS((typval_T *varp));
560static long get_tv_number __ARGS((typval_T *varp));
561static linenr_T get_tv_lnum __ARGS((typval_T *argvars));
562static char_u *get_tv_string __ARGS((typval_T *varp));
563static char_u *get_tv_string_buf __ARGS((typval_T *varp, char_u *buf));
564static dictitem_T *find_var __ARGS((char_u *name, hashtab_T **htp));
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000565static dictitem_T *find_var_in_ht __ARGS((hashtab_T *ht, char_u *varname, int writing));
Bram Moolenaar33570922005-01-25 22:26:29 +0000566static hashtab_T *find_var_ht __ARGS((char_u *name, char_u **varname));
567static void vars_clear_ext __ARGS((hashtab_T *ht, int free_val));
568static void delete_var __ARGS((hashtab_T *ht, hashitem_T *hi));
569static void list_one_var __ARGS((dictitem_T *v, char_u *prefix));
570static void list_one_var_a __ARGS((char_u *prefix, char_u *name, int type, char_u *string));
571static void set_var __ARGS((char_u *name, typval_T *varp, int copy));
572static int var_check_ro __ARGS((int flags, char_u *name));
Bram Moolenaar2e6aff32005-01-31 19:25:36 +0000573static int tv_check_lock __ARGS((int lock, char_u *name));
Bram Moolenaar33570922005-01-25 22:26:29 +0000574static void copy_tv __ARGS((typval_T *from, typval_T *to));
Bram Moolenaar81bf7082005-02-12 14:31:42 +0000575static int item_copy __ARGS((typval_T *from, typval_T *to, int deep, int copyID));
Bram Moolenaar33570922005-01-25 22:26:29 +0000576static char_u *find_option_end __ARGS((char_u **arg, int *opt_flags));
577static char_u *trans_function_name __ARGS((char_u **pp, int skip, int flags, funcdict_T *fd));
578static int eval_fname_script __ARGS((char_u *p));
579static int eval_fname_sid __ARGS((char_u *p));
580static void list_func_head __ARGS((ufunc_T *fp, int indent));
581static void cat_func_name __ARGS((char_u *buf, ufunc_T *fp));
582static ufunc_T *find_func __ARGS((char_u *name));
583static int function_exists __ARGS((char_u *name));
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +0000584static int builtin_function __ARGS((char_u *name));
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000585static int script_autoload __ARGS((char_u *name));
586static char_u *autoload_name __ARGS((char_u *name));
Bram Moolenaar33570922005-01-25 22:26:29 +0000587static void func_free __ARGS((ufunc_T *fp));
588static void func_unref __ARGS((char_u *name));
589static void func_ref __ARGS((char_u *name));
590static void call_user_func __ARGS((ufunc_T *fp, int argcount, typval_T *argvars, typval_T *rettv, linenr_T firstline, linenr_T lastline, dict_T *selfdict));
591static void add_nr_var __ARGS((dict_T *dp, dictitem_T *v, char *name, varnumber_T nr));
592
593static char_u * make_expanded_name __ARGS((char_u *in_start, char_u *expr_start, char_u *expr_end, char_u *in_end));
594
595static int ex_let_vars __ARGS((char_u *arg, typval_T *tv, int copy, int semicolon, int var_count, char_u *nextchars));
596static char_u *skip_var_list __ARGS((char_u *arg, int *var_count, int *semicolon));
597static char_u *skip_var_one __ARGS((char_u *arg));
598static void list_hashtable_vars __ARGS((hashtab_T *ht, char_u *prefix, int empty));
599static void list_glob_vars __ARGS((void));
600static void list_buf_vars __ARGS((void));
601static void list_win_vars __ARGS((void));
602static void list_vim_vars __ARGS((void));
603static char_u *list_arg_vars __ARGS((exarg_T *eap, char_u *arg));
604static char_u *ex_let_one __ARGS((char_u *arg, typval_T *tv, int copy, char_u *endchars, char_u *op));
605static int check_changedtick __ARGS((char_u *arg));
606static char_u *get_lval __ARGS((char_u *name, typval_T *rettv, lval_T *lp, int unlet, int skip, int quiet));
607static void clear_lval __ARGS((lval_T *lp));
608static void set_var_lval __ARGS((lval_T *lp, char_u *endp, typval_T *rettv, int copy, char_u *op));
609static int tv_op __ARGS((typval_T *tv1, typval_T *tv2, char_u *op));
610static void list_add_watch __ARGS((list_T *l, listwatch_T *lw));
611static void list_rem_watch __ARGS((list_T *l, listwatch_T *lwrem));
612static void list_fix_watch __ARGS((list_T *l, listitem_T *item));
Bram Moolenaar2e6aff32005-01-31 19:25:36 +0000613static void ex_unletlock __ARGS((exarg_T *eap, char_u *argstart, int deep));
Bram Moolenaar33570922005-01-25 22:26:29 +0000614static int do_unlet_var __ARGS((lval_T *lp, char_u *name_end, int forceit));
Bram Moolenaar2e6aff32005-01-31 19:25:36 +0000615static int do_lock_var __ARGS((lval_T *lp, char_u *name_end, int deep, int lock));
616static void item_lock __ARGS((typval_T *tv, int deep, int lock));
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000617static int tv_islocked __ARGS((typval_T *tv));
Bram Moolenaar33570922005-01-25 22:26:29 +0000618
619/*
620 * Initialize the global and v: variables.
Bram Moolenaara7043832005-01-21 11:56:39 +0000621 */
622 void
623eval_init()
624{
Bram Moolenaar33570922005-01-25 22:26:29 +0000625 int i;
626 struct vimvar *p;
627
628 init_var_dict(&globvardict, &globvars_var);
629 init_var_dict(&vimvardict, &vimvars_var);
Bram Moolenaar532c7802005-01-27 14:44:31 +0000630 hash_init(&compat_hashtab);
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000631 hash_init(&func_hashtab);
Bram Moolenaar33570922005-01-25 22:26:29 +0000632
633 for (i = 0; i < VV_LEN; ++i)
634 {
635 p = &vimvars[i];
636 STRCPY(p->vv_di.di_key, p->vv_name);
637 if (p->vv_flags & VV_RO)
638 p->vv_di.di_flags = DI_FLAGS_RO | DI_FLAGS_FIX;
639 else if (p->vv_flags & VV_RO_SBX)
640 p->vv_di.di_flags = DI_FLAGS_RO_SBX | DI_FLAGS_FIX;
641 else
642 p->vv_di.di_flags = DI_FLAGS_FIX;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +0000643
644 /* add to v: scope dict, unless the value is not always available */
645 if (p->vv_type != VAR_UNKNOWN)
646 hash_add(&vimvarht, p->vv_di.di_key);
Bram Moolenaar33570922005-01-25 22:26:29 +0000647 if (p->vv_flags & VV_COMPAT)
Bram Moolenaar532c7802005-01-27 14:44:31 +0000648 /* add to compat scope dict */
649 hash_add(&compat_hashtab, p->vv_di.di_key);
Bram Moolenaar33570922005-01-25 22:26:29 +0000650 }
Bram Moolenaara7043832005-01-21 11:56:39 +0000651}
652
Bram Moolenaar9ef486d2005-01-17 22:23:00 +0000653/*
Bram Moolenaar071d4272004-06-13 20:20:40 +0000654 * Return the name of the executed function.
655 */
656 char_u *
657func_name(cookie)
658 void *cookie;
659{
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000660 return ((funccall_T *)cookie)->func->uf_name;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000661}
662
663/*
664 * Return the address holding the next breakpoint line for a funccall cookie.
665 */
666 linenr_T *
667func_breakpoint(cookie)
668 void *cookie;
669{
Bram Moolenaar33570922005-01-25 22:26:29 +0000670 return &((funccall_T *)cookie)->breakpoint;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000671}
672
673/*
674 * Return the address holding the debug tick for a funccall cookie.
675 */
676 int *
677func_dbg_tick(cookie)
678 void *cookie;
679{
Bram Moolenaar33570922005-01-25 22:26:29 +0000680 return &((funccall_T *)cookie)->dbg_tick;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000681}
682
683/*
684 * Return the nesting level for a funccall cookie.
685 */
686 int
687func_level(cookie)
688 void *cookie;
689{
Bram Moolenaar33570922005-01-25 22:26:29 +0000690 return ((funccall_T *)cookie)->level;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000691}
692
693/* pointer to funccal for currently active function */
Bram Moolenaar33570922005-01-25 22:26:29 +0000694funccall_T *current_funccal = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000695
696/*
697 * Return TRUE when a function was ended by a ":return" command.
698 */
699 int
700current_func_returned()
701{
702 return current_funccal->returned;
703}
704
705
706/*
Bram Moolenaar071d4272004-06-13 20:20:40 +0000707 * Set an internal variable to a string value. Creates the variable if it does
708 * not already exist.
709 */
710 void
711set_internal_string_var(name, value)
712 char_u *name;
713 char_u *value;
714{
Bram Moolenaar49cd9572005-01-03 21:06:01 +0000715 char_u *val;
Bram Moolenaar33570922005-01-25 22:26:29 +0000716 typval_T *tvp;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000717
718 val = vim_strsave(value);
719 if (val != NULL)
720 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000721 tvp = alloc_string_tv(val);
Bram Moolenaar49cd9572005-01-03 21:06:01 +0000722 if (tvp != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000723 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +0000724 set_var(name, tvp, FALSE);
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000725 free_tv(tvp);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000726 }
727 }
728}
729
Bram Moolenaar5313dcb2005-02-22 08:56:13 +0000730static lval_T *redir_lval = NULL;
731static char_u *redir_endp = NULL;
732static char_u *redir_varname = NULL;
733
734/*
735 * Start recording command output to a variable
736 * Returns OK if successfully completed the setup. FAIL otherwise.
737 */
738 int
739var_redir_start(name, append)
740 char_u *name;
741 int append; /* append to an existing variable */
742{
743 int save_emsg;
744 int err;
745 typval_T tv;
746
747 /* Make sure a valid variable name is specified */
748 if (!eval_isnamec(*name) || VIM_ISDIGIT(*name))
749 {
750 EMSG(_(e_invarg));
751 return FAIL;
752 }
753
754 redir_varname = vim_strsave(name);
755 if (redir_varname == NULL)
756 return FAIL;
757
758 redir_lval = (lval_T *)alloc_clear((unsigned)sizeof(lval_T));
759 if (redir_lval == NULL)
760 {
761 var_redir_stop();
762 return FAIL;
763 }
764
765 /* Parse the variable name (can be a dict or list entry). */
766 redir_endp = get_lval(redir_varname, NULL, redir_lval, FALSE, FALSE, FALSE);
767 if (redir_endp == NULL || redir_lval->ll_name == NULL || *redir_endp != NUL)
768 {
769 if (redir_endp != NULL && *redir_endp != NUL)
770 /* Trailing characters are present after the variable name */
771 EMSG(_(e_trailing));
772 else
773 EMSG(_(e_invarg));
774 var_redir_stop();
775 return FAIL;
776 }
777
778 /* check if we can write to the variable: set it to or append an empty
779 * string */
780 save_emsg = did_emsg;
781 did_emsg = FALSE;
782 tv.v_type = VAR_STRING;
783 tv.vval.v_string = (char_u *)"";
784 if (append)
785 set_var_lval(redir_lval, redir_endp, &tv, TRUE, (char_u *)".");
786 else
787 set_var_lval(redir_lval, redir_endp, &tv, TRUE, (char_u *)"=");
788 err = did_emsg;
789 did_emsg += save_emsg;
790 if (err)
791 {
792 var_redir_stop();
793 return FAIL;
794 }
795 if (redir_lval->ll_newkey != NULL)
796 {
797 /* Dictionary item was created, don't do it again. */
798 vim_free(redir_lval->ll_newkey);
799 redir_lval->ll_newkey = NULL;
800 }
801
802 return OK;
803}
804
805/*
806 * Append "value[len]" to the variable set by var_redir_start().
807 */
808 void
809var_redir_str(value, len)
810 char_u *value;
811 int len;
812{
813 char_u *val;
814 typval_T tv;
815 int save_emsg;
816 int err;
817
818 if (redir_lval == NULL)
819 return;
820
821 if (len == -1)
822 /* Append the entire string */
823 val = vim_strsave(value);
824 else
825 /* Append only the specified number of characters */
826 val = vim_strnsave(value, len);
827 if (val == NULL)
828 return;
829
830 tv.v_type = VAR_STRING;
831 tv.vval.v_string = val;
832
833 save_emsg = did_emsg;
834 did_emsg = FALSE;
835 set_var_lval(redir_lval, redir_endp, &tv, FALSE, (char_u *)".");
836 err = did_emsg;
837 did_emsg += save_emsg;
838 if (err)
839 var_redir_stop();
840
841 vim_free(tv.vval.v_string);
842}
843
844/*
845 * Stop redirecting command output to a variable.
846 */
847 void
848var_redir_stop()
849{
850 if (redir_lval != NULL)
851 {
852 clear_lval(redir_lval);
853 vim_free(redir_lval);
854 redir_lval = NULL;
855 }
856 vim_free(redir_varname);
857 redir_varname = NULL;
858}
859
Bram Moolenaar071d4272004-06-13 20:20:40 +0000860# if defined(FEAT_MBYTE) || defined(PROTO)
861 int
862eval_charconvert(enc_from, enc_to, fname_from, fname_to)
863 char_u *enc_from;
864 char_u *enc_to;
865 char_u *fname_from;
866 char_u *fname_to;
867{
868 int err = FALSE;
869
870 set_vim_var_string(VV_CC_FROM, enc_from, -1);
871 set_vim_var_string(VV_CC_TO, enc_to, -1);
872 set_vim_var_string(VV_FNAME_IN, fname_from, -1);
873 set_vim_var_string(VV_FNAME_OUT, fname_to, -1);
874 if (eval_to_bool(p_ccv, &err, NULL, FALSE))
875 err = TRUE;
876 set_vim_var_string(VV_CC_FROM, NULL, -1);
877 set_vim_var_string(VV_CC_TO, NULL, -1);
878 set_vim_var_string(VV_FNAME_IN, NULL, -1);
879 set_vim_var_string(VV_FNAME_OUT, NULL, -1);
880
881 if (err)
882 return FAIL;
883 return OK;
884}
885# endif
886
887# if defined(FEAT_POSTSCRIPT) || defined(PROTO)
888 int
889eval_printexpr(fname, args)
890 char_u *fname;
891 char_u *args;
892{
893 int err = FALSE;
894
895 set_vim_var_string(VV_FNAME_IN, fname, -1);
896 set_vim_var_string(VV_CMDARG, args, -1);
897 if (eval_to_bool(p_pexpr, &err, NULL, FALSE))
898 err = TRUE;
899 set_vim_var_string(VV_FNAME_IN, NULL, -1);
900 set_vim_var_string(VV_CMDARG, NULL, -1);
901
902 if (err)
903 {
904 mch_remove(fname);
905 return FAIL;
906 }
907 return OK;
908}
909# endif
910
911# if defined(FEAT_DIFF) || defined(PROTO)
912 void
913eval_diff(origfile, newfile, outfile)
914 char_u *origfile;
915 char_u *newfile;
916 char_u *outfile;
917{
918 int err = FALSE;
919
920 set_vim_var_string(VV_FNAME_IN, origfile, -1);
921 set_vim_var_string(VV_FNAME_NEW, newfile, -1);
922 set_vim_var_string(VV_FNAME_OUT, outfile, -1);
923 (void)eval_to_bool(p_dex, &err, NULL, FALSE);
924 set_vim_var_string(VV_FNAME_IN, NULL, -1);
925 set_vim_var_string(VV_FNAME_NEW, NULL, -1);
926 set_vim_var_string(VV_FNAME_OUT, NULL, -1);
927}
928
929 void
930eval_patch(origfile, difffile, outfile)
931 char_u *origfile;
932 char_u *difffile;
933 char_u *outfile;
934{
935 int err;
936
937 set_vim_var_string(VV_FNAME_IN, origfile, -1);
938 set_vim_var_string(VV_FNAME_DIFF, difffile, -1);
939 set_vim_var_string(VV_FNAME_OUT, outfile, -1);
940 (void)eval_to_bool(p_pex, &err, NULL, FALSE);
941 set_vim_var_string(VV_FNAME_IN, NULL, -1);
942 set_vim_var_string(VV_FNAME_DIFF, NULL, -1);
943 set_vim_var_string(VV_FNAME_OUT, NULL, -1);
944}
945# endif
946
947/*
948 * Top level evaluation function, returning a boolean.
949 * Sets "error" to TRUE if there was an error.
950 * Return TRUE or FALSE.
951 */
952 int
953eval_to_bool(arg, error, nextcmd, skip)
954 char_u *arg;
955 int *error;
956 char_u **nextcmd;
957 int skip; /* only parse, don't execute */
958{
Bram Moolenaar33570922005-01-25 22:26:29 +0000959 typval_T tv;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000960 int retval = FALSE;
961
962 if (skip)
963 ++emsg_skip;
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000964 if (eval0(arg, &tv, nextcmd, !skip) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000965 *error = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000966 else
967 {
968 *error = FALSE;
969 if (!skip)
970 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000971 retval = (get_tv_number(&tv) != 0);
972 clear_tv(&tv);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000973 }
974 }
975 if (skip)
976 --emsg_skip;
977
978 return retval;
979}
980
981/*
982 * Top level evaluation function, returning a string. If "skip" is TRUE,
983 * only parsing to "nextcmd" is done, without reporting errors. Return
984 * pointer to allocated memory, or NULL for failure or when "skip" is TRUE.
985 */
986 char_u *
987eval_to_string_skip(arg, nextcmd, skip)
988 char_u *arg;
989 char_u **nextcmd;
990 int skip; /* only parse, don't execute */
991{
Bram Moolenaar33570922005-01-25 22:26:29 +0000992 typval_T tv;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000993 char_u *retval;
994
995 if (skip)
996 ++emsg_skip;
Bram Moolenaarc70646c2005-01-04 21:52:38 +0000997 if (eval0(arg, &tv, nextcmd, !skip) == FAIL || skip)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000998 retval = NULL;
999 else
1000 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001001 retval = vim_strsave(get_tv_string(&tv));
1002 clear_tv(&tv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001003 }
1004 if (skip)
1005 --emsg_skip;
1006
1007 return retval;
1008}
1009
1010/*
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001011 * Skip over an expression at "*pp".
1012 * Return FAIL for an error, OK otherwise.
1013 */
1014 int
1015skip_expr(pp)
1016 char_u **pp;
1017{
Bram Moolenaar33570922005-01-25 22:26:29 +00001018 typval_T rettv;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001019
1020 *pp = skipwhite(*pp);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001021 return eval1(pp, &rettv, FALSE);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001022}
1023
1024/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00001025 * Top level evaluation function, returning a string.
1026 * Return pointer to allocated memory, or NULL for failure.
1027 */
1028 char_u *
1029eval_to_string(arg, nextcmd)
1030 char_u *arg;
1031 char_u **nextcmd;
1032{
Bram Moolenaar33570922005-01-25 22:26:29 +00001033 typval_T tv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001034 char_u *retval;
1035
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001036 if (eval0(arg, &tv, nextcmd, TRUE) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001037 retval = NULL;
1038 else
1039 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001040 retval = vim_strsave(get_tv_string(&tv));
1041 clear_tv(&tv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001042 }
1043
1044 return retval;
1045}
1046
1047/*
1048 * Call eval_to_string() with "sandbox" set and not using local variables.
1049 */
1050 char_u *
1051eval_to_string_safe(arg, nextcmd)
1052 char_u *arg;
1053 char_u **nextcmd;
1054{
1055 char_u *retval;
1056 void *save_funccalp;
1057
1058 save_funccalp = save_funccal();
1059 ++sandbox;
1060 retval = eval_to_string(arg, nextcmd);
1061 --sandbox;
1062 restore_funccal(save_funccalp);
1063 return retval;
1064}
1065
Bram Moolenaar071d4272004-06-13 20:20:40 +00001066/*
1067 * Top level evaluation function, returning a number.
1068 * Evaluates "expr" silently.
1069 * Returns -1 for an error.
1070 */
1071 int
1072eval_to_number(expr)
1073 char_u *expr;
1074{
Bram Moolenaar33570922005-01-25 22:26:29 +00001075 typval_T rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001076 int retval;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00001077 char_u *p = skipwhite(expr);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001078
1079 ++emsg_off;
1080
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001081 if (eval1(&p, &rettv, TRUE) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001082 retval = -1;
1083 else
1084 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001085 retval = get_tv_number(&rettv);
1086 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001087 }
1088 --emsg_off;
1089
1090 return retval;
1091}
1092
1093#if (defined(FEAT_USR_CMDS) && defined(FEAT_CMDL_COMPL)) || defined(PROTO)
1094/*
1095 * Call some vimL function and return the result as a string
1096 * Uses argv[argc] for the function arguments.
1097 */
1098 char_u *
1099call_vim_function(func, argc, argv, safe)
1100 char_u *func;
1101 int argc;
1102 char_u **argv;
1103 int safe; /* use the sandbox */
1104{
1105 char_u *retval = NULL;
Bram Moolenaar33570922005-01-25 22:26:29 +00001106 typval_T rettv;
1107 typval_T *argvars;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001108 long n;
1109 int len;
1110 int i;
1111 int doesrange;
1112 void *save_funccalp = NULL;
1113
Bram Moolenaar33570922005-01-25 22:26:29 +00001114 argvars = (typval_T *)alloc((unsigned)(argc * sizeof(typval_T)));
Bram Moolenaar071d4272004-06-13 20:20:40 +00001115 if (argvars == NULL)
1116 return NULL;
1117
1118 for (i = 0; i < argc; i++)
1119 {
Bram Moolenaarcfbc5ee2004-07-02 15:38:35 +00001120 /* Pass a NULL or empty argument as an empty string */
1121 if (argv[i] == NULL || *argv[i] == NUL)
1122 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +00001123 argvars[i].v_type = VAR_STRING;
1124 argvars[i].vval.v_string = (char_u *)"";
Bram Moolenaarcfbc5ee2004-07-02 15:38:35 +00001125 continue;
1126 }
1127
Bram Moolenaar071d4272004-06-13 20:20:40 +00001128 /* Recognize a number argument, the others must be strings. */
1129 vim_str2nr(argv[i], NULL, &len, TRUE, TRUE, &n, NULL);
1130 if (len != 0 && len == (int)STRLEN(argv[i]))
1131 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +00001132 argvars[i].v_type = VAR_NUMBER;
1133 argvars[i].vval.v_number = n;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001134 }
1135 else
1136 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +00001137 argvars[i].v_type = VAR_STRING;
1138 argvars[i].vval.v_string = argv[i];
Bram Moolenaar071d4272004-06-13 20:20:40 +00001139 }
1140 }
1141
1142 if (safe)
1143 {
1144 save_funccalp = save_funccal();
1145 ++sandbox;
1146 }
1147
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001148 rettv.v_type = VAR_UNKNOWN; /* clear_tv() uses this */
1149 if (call_func(func, (int)STRLEN(func), &rettv, argc, argvars,
Bram Moolenaar071d4272004-06-13 20:20:40 +00001150 curwin->w_cursor.lnum, curwin->w_cursor.lnum,
Bram Moolenaare9a41262005-01-15 22:18:47 +00001151 &doesrange, TRUE, NULL) == OK)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001152 retval = vim_strsave(get_tv_string(&rettv));
Bram Moolenaar071d4272004-06-13 20:20:40 +00001153
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001154 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001155 vim_free(argvars);
1156
1157 if (safe)
1158 {
1159 --sandbox;
1160 restore_funccal(save_funccalp);
1161 }
1162 return retval;
1163}
1164#endif
1165
1166/*
1167 * Save the current function call pointer, and set it to NULL.
1168 * Used when executing autocommands and for ":source".
1169 */
1170 void *
1171save_funccal()
1172{
Bram Moolenaar33570922005-01-25 22:26:29 +00001173 funccall_T *fc;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001174
1175 fc = current_funccal;
1176 current_funccal = NULL;
1177 return (void *)fc;
1178}
1179
1180 void
1181restore_funccal(fc)
1182 void *fc;
1183{
Bram Moolenaar33570922005-01-25 22:26:29 +00001184 current_funccal = (funccall_T *)fc;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001185}
1186
1187#ifdef FEAT_FOLDING
1188/*
1189 * Evaluate 'foldexpr'. Returns the foldlevel, and any character preceding
1190 * it in "*cp". Doesn't give error messages.
1191 */
1192 int
1193eval_foldexpr(arg, cp)
1194 char_u *arg;
1195 int *cp;
1196{
Bram Moolenaar33570922005-01-25 22:26:29 +00001197 typval_T tv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001198 int retval;
1199 char_u *s;
1200
1201 ++emsg_off;
1202 ++sandbox;
1203 *cp = NUL;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001204 if (eval0(arg, &tv, NULL, TRUE) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001205 retval = 0;
1206 else
1207 {
1208 /* If the result is a number, just return the number. */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001209 if (tv.v_type == VAR_NUMBER)
1210 retval = tv.vval.v_number;
Bram Moolenaar758711c2005-02-02 23:11:38 +00001211 else if (tv.v_type != VAR_STRING || tv.vval.v_string == NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001212 retval = 0;
1213 else
1214 {
1215 /* If the result is a string, check if there is a non-digit before
1216 * the number. */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001217 s = tv.vval.v_string;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001218 if (!VIM_ISDIGIT(*s) && *s != '-')
1219 *cp = *s++;
1220 retval = atol((char *)s);
1221 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001222 clear_tv(&tv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001223 }
1224 --emsg_off;
1225 --sandbox;
1226
1227 return retval;
1228}
1229#endif
1230
Bram Moolenaar071d4272004-06-13 20:20:40 +00001231/*
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001232 * ":let" list all variable values
1233 * ":let var1 var2" list variable values
1234 * ":let var = expr" assignment command.
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001235 * ":let var += expr" assignment command.
1236 * ":let var -= expr" assignment command.
1237 * ":let var .= expr" assignment command.
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001238 * ":let [var1, var2] = expr" unpack list.
Bram Moolenaar071d4272004-06-13 20:20:40 +00001239 */
1240 void
1241ex_let(eap)
1242 exarg_T *eap;
1243{
1244 char_u *arg = eap->arg;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001245 char_u *expr = NULL;
Bram Moolenaar33570922005-01-25 22:26:29 +00001246 typval_T rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001247 int i;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001248 int var_count = 0;
1249 int semicolon = 0;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001250 char_u op[2];
Bram Moolenaar071d4272004-06-13 20:20:40 +00001251
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001252 expr = skip_var_list(arg, &var_count, &semicolon);
1253 if (expr == NULL)
1254 return;
1255 expr = vim_strchr(expr, '=');
1256 if (expr == NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001257 {
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00001258 /*
1259 * ":let" without "=": list variables
1260 */
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001261 if (*arg == '[')
1262 EMSG(_(e_invarg));
1263 else if (!ends_excmd(*arg))
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001264 /* ":let var1 var2" */
1265 arg = list_arg_vars(eap, arg);
1266 else if (!eap->skip)
Bram Moolenaara7043832005-01-21 11:56:39 +00001267 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001268 /* ":let" */
Bram Moolenaara7043832005-01-21 11:56:39 +00001269 list_glob_vars();
1270 list_buf_vars();
1271 list_win_vars();
1272 list_vim_vars();
1273 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001274 eap->nextcmd = check_nextcmd(arg);
1275 }
1276 else
1277 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001278 op[0] = '=';
1279 op[1] = NUL;
1280 if (expr > arg)
1281 {
1282 if (vim_strchr((char_u *)"+-.", expr[-1]) != NULL)
1283 op[0] = expr[-1]; /* +=, -= or .= */
1284 }
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001285 expr = skipwhite(expr + 1);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001286
Bram Moolenaar071d4272004-06-13 20:20:40 +00001287 if (eap->skip)
1288 ++emsg_skip;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001289 i = eval0(expr, &rettv, &eap->nextcmd, !eap->skip);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001290 if (eap->skip)
1291 {
1292 if (i != FAIL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001293 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001294 --emsg_skip;
1295 }
1296 else if (i != FAIL)
1297 {
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001298 (void)ex_let_vars(eap->arg, &rettv, FALSE, semicolon, var_count,
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001299 op);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001300 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001301 }
1302 }
1303}
1304
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001305/*
1306 * Assign the typevalue "tv" to the variable or variables at "arg_start".
1307 * Handles both "var" with any type and "[var, var; var]" with a list type.
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001308 * When "nextchars" is not NULL it points to a string with characters that
1309 * must appear after the variable(s). Use "+", "-" or "." for add, subtract
1310 * or concatenate.
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001311 * Returns OK or FAIL;
1312 */
1313 static int
1314ex_let_vars(arg_start, tv, copy, semicolon, var_count, nextchars)
1315 char_u *arg_start;
Bram Moolenaar33570922005-01-25 22:26:29 +00001316 typval_T *tv;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001317 int copy; /* copy values from "tv", don't move */
1318 int semicolon; /* from skip_var_list() */
1319 int var_count; /* from skip_var_list() */
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001320 char_u *nextchars;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001321{
1322 char_u *arg = arg_start;
Bram Moolenaar33570922005-01-25 22:26:29 +00001323 list_T *l;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001324 int i;
Bram Moolenaar33570922005-01-25 22:26:29 +00001325 listitem_T *item;
1326 typval_T ltv;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001327
1328 if (*arg != '[')
1329 {
1330 /*
1331 * ":let var = expr" or ":for var in list"
1332 */
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001333 if (ex_let_one(arg, tv, copy, nextchars, nextchars) == NULL)
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001334 return FAIL;
1335 return OK;
1336 }
1337
1338 /*
1339 * ":let [v1, v2] = list" or ":for [v1, v2] in listlist"
1340 */
Bram Moolenaar758711c2005-02-02 23:11:38 +00001341 if (tv->v_type != VAR_LIST || (l = tv->vval.v_list) == NULL)
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001342 {
1343 EMSG(_(e_listreq));
1344 return FAIL;
1345 }
1346
1347 i = list_len(l);
1348 if (semicolon == 0 && var_count < i)
1349 {
Bram Moolenaare49b69a2005-01-08 16:11:57 +00001350 EMSG(_("E687: Less targets than List items"));
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001351 return FAIL;
1352 }
1353 if (var_count - semicolon > i)
1354 {
Bram Moolenaare49b69a2005-01-08 16:11:57 +00001355 EMSG(_("E688: More targets than List items"));
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001356 return FAIL;
1357 }
1358
1359 item = l->lv_first;
1360 while (*arg != ']')
1361 {
1362 arg = skipwhite(arg + 1);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001363 arg = ex_let_one(arg, &item->li_tv, TRUE, (char_u *)",;]", nextchars);
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001364 item = item->li_next;
1365 if (arg == NULL)
1366 return FAIL;
1367
1368 arg = skipwhite(arg);
1369 if (*arg == ';')
1370 {
1371 /* Put the rest of the list (may be empty) in the var after ';'.
1372 * Create a new list for this. */
1373 l = list_alloc();
1374 if (l == NULL)
1375 return FAIL;
1376 while (item != NULL)
1377 {
1378 list_append_tv(l, &item->li_tv);
1379 item = item->li_next;
1380 }
1381
1382 ltv.v_type = VAR_LIST;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00001383 ltv.v_lock = 0;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001384 ltv.vval.v_list = l;
1385 l->lv_refcount = 1;
1386
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001387 arg = ex_let_one(skipwhite(arg + 1), &ltv, FALSE,
1388 (char_u *)"]", nextchars);
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001389 clear_tv(&ltv);
1390 if (arg == NULL)
1391 return FAIL;
1392 break;
1393 }
1394 else if (*arg != ',' && *arg != ']')
1395 {
1396 EMSG2(_(e_intern2), "ex_let_vars()");
1397 return FAIL;
1398 }
1399 }
1400
1401 return OK;
1402}
1403
1404/*
1405 * Skip over assignable variable "var" or list of variables "[var, var]".
1406 * Used for ":let varvar = expr" and ":for varvar in expr".
1407 * For "[var, var]" increment "*var_count" for each variable.
1408 * for "[var, var; var]" set "semicolon".
1409 * Return NULL for an error.
1410 */
1411 static char_u *
1412skip_var_list(arg, var_count, semicolon)
1413 char_u *arg;
1414 int *var_count;
1415 int *semicolon;
1416{
1417 char_u *p, *s;
1418
1419 if (*arg == '[')
1420 {
1421 /* "[var, var]": find the matching ']'. */
1422 p = arg;
1423 while (1)
1424 {
1425 p = skipwhite(p + 1); /* skip whites after '[', ';' or ',' */
1426 s = skip_var_one(p);
1427 if (s == p)
1428 {
1429 EMSG2(_(e_invarg2), p);
1430 return NULL;
1431 }
1432 ++*var_count;
1433
1434 p = skipwhite(s);
1435 if (*p == ']')
1436 break;
1437 else if (*p == ';')
1438 {
1439 if (*semicolon == 1)
1440 {
1441 EMSG(_("Double ; in list of variables"));
1442 return NULL;
1443 }
1444 *semicolon = 1;
1445 }
1446 else if (*p != ',')
1447 {
1448 EMSG2(_(e_invarg2), p);
1449 return NULL;
1450 }
1451 }
1452 return p + 1;
1453 }
1454 else
1455 return skip_var_one(arg);
1456}
1457
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001458/*
1459 * Skip one (assignable) variable name, includig $VAR, d.key, l[idx].
1460 */
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001461 static char_u *
1462skip_var_one(arg)
1463 char_u *arg;
1464{
1465 if (vim_strchr((char_u *)"$@&", *arg) != NULL)
1466 ++arg;
1467 return find_name_end(arg, NULL, NULL, TRUE);
1468}
1469
Bram Moolenaara7043832005-01-21 11:56:39 +00001470/*
Bram Moolenaar33570922005-01-25 22:26:29 +00001471 * List variables for hashtab "ht" with prefix "prefix".
1472 * If "empty" is TRUE also list NULL strings as empty strings.
Bram Moolenaara7043832005-01-21 11:56:39 +00001473 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001474 static void
Bram Moolenaar33570922005-01-25 22:26:29 +00001475list_hashtable_vars(ht, prefix, empty)
1476 hashtab_T *ht;
Bram Moolenaara7043832005-01-21 11:56:39 +00001477 char_u *prefix;
Bram Moolenaar33570922005-01-25 22:26:29 +00001478 int empty;
Bram Moolenaara7043832005-01-21 11:56:39 +00001479{
Bram Moolenaar33570922005-01-25 22:26:29 +00001480 hashitem_T *hi;
1481 dictitem_T *di;
Bram Moolenaara7043832005-01-21 11:56:39 +00001482 int todo;
1483
1484 todo = ht->ht_used;
1485 for (hi = ht->ht_array; todo > 0 && !got_int; ++hi)
1486 {
1487 if (!HASHITEM_EMPTY(hi))
1488 {
1489 --todo;
Bram Moolenaar33570922005-01-25 22:26:29 +00001490 di = HI2DI(hi);
1491 if (empty || di->di_tv.v_type != VAR_STRING
1492 || di->di_tv.vval.v_string != NULL)
1493 list_one_var(di, prefix);
Bram Moolenaara7043832005-01-21 11:56:39 +00001494 }
1495 }
1496}
1497
1498/*
1499 * List global variables.
1500 */
1501 static void
1502list_glob_vars()
1503{
Bram Moolenaar33570922005-01-25 22:26:29 +00001504 list_hashtable_vars(&globvarht, (char_u *)"", TRUE);
Bram Moolenaara7043832005-01-21 11:56:39 +00001505}
1506
1507/*
1508 * List buffer variables.
1509 */
1510 static void
1511list_buf_vars()
1512{
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001513 char_u numbuf[NUMBUFLEN];
1514
Bram Moolenaar33570922005-01-25 22:26:29 +00001515 list_hashtable_vars(&curbuf->b_vars.dv_hashtab, (char_u *)"b:", TRUE);
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001516
1517 sprintf((char *)numbuf, "%ld", (long)curbuf->b_changedtick);
1518 list_one_var_a((char_u *)"b:", (char_u *)"changedtick", VAR_NUMBER, numbuf);
Bram Moolenaara7043832005-01-21 11:56:39 +00001519}
1520
1521/*
1522 * List window variables.
1523 */
1524 static void
1525list_win_vars()
1526{
Bram Moolenaar33570922005-01-25 22:26:29 +00001527 list_hashtable_vars(&curwin->w_vars.dv_hashtab, (char_u *)"w:", TRUE);
Bram Moolenaara7043832005-01-21 11:56:39 +00001528}
1529
1530/*
1531 * List Vim variables.
1532 */
1533 static void
1534list_vim_vars()
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001535{
Bram Moolenaar33570922005-01-25 22:26:29 +00001536 list_hashtable_vars(&vimvarht, (char_u *)"v:", FALSE);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001537}
1538
1539/*
1540 * List variables in "arg".
1541 */
1542 static char_u *
1543list_arg_vars(eap, arg)
1544 exarg_T *eap;
1545 char_u *arg;
1546{
1547 int error = FALSE;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001548 int len;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001549 char_u *name;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001550 char_u *name_start;
1551 char_u *arg_subsc;
1552 char_u *tofree;
1553 typval_T tv;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001554
1555 while (!ends_excmd(*arg) && !got_int)
1556 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001557 if (error || eap->skip)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001558 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001559 arg = find_name_end(arg, NULL, NULL, TRUE);
1560 if (!vim_iswhite(*arg) && !ends_excmd(*arg))
1561 {
1562 emsg_severe = TRUE;
1563 EMSG(_(e_trailing));
1564 break;
1565 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001566 }
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001567 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001568 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001569 /* get_name_len() takes care of expanding curly braces */
1570 name_start = name = arg;
1571 len = get_name_len(&arg, &tofree, TRUE, TRUE);
1572 if (len <= 0)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001573 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001574 /* This is mainly to keep test 49 working: when expanding
1575 * curly braces fails overrule the exception error message. */
1576 if (len < 0 && !aborting())
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001577 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001578 emsg_severe = TRUE;
1579 EMSG2(_(e_invarg2), arg);
1580 break;
1581 }
1582 error = TRUE;
1583 }
1584 else
1585 {
1586 if (tofree != NULL)
1587 name = tofree;
1588 if (get_var_tv(name, len, &tv, TRUE) == FAIL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001589 error = TRUE;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001590 else
1591 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001592 /* handle d.key, l[idx], f(expr) */
1593 arg_subsc = arg;
1594 if (handle_subscript(&arg, &tv, TRUE, TRUE) == FAIL)
Bram Moolenaara7043832005-01-21 11:56:39 +00001595 error = TRUE;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001596 else
Bram Moolenaara7043832005-01-21 11:56:39 +00001597 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001598 if (arg == arg_subsc && len == 2 && name[1] == ':')
Bram Moolenaara7043832005-01-21 11:56:39 +00001599 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001600 switch (*name)
Bram Moolenaara7043832005-01-21 11:56:39 +00001601 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001602 case 'g': list_glob_vars(); break;
1603 case 'b': list_buf_vars(); break;
1604 case 'w': list_win_vars(); break;
1605 case 'v': list_vim_vars(); break;
1606 default:
1607 EMSG2(_("E738: Can't list variables for %s"), name);
Bram Moolenaara7043832005-01-21 11:56:39 +00001608 }
Bram Moolenaara7043832005-01-21 11:56:39 +00001609 }
1610 else
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001611 {
1612 char_u numbuf[NUMBUFLEN];
1613 char_u *tf;
1614 int c;
1615 char_u *s;
1616
1617 s = echo_string(&tv, &tf, numbuf);
1618 c = *arg;
1619 *arg = NUL;
1620 list_one_var_a((char_u *)"",
1621 arg == arg_subsc ? name : name_start,
1622 tv.v_type, s == NULL ? (char_u *)"" : s);
1623 *arg = c;
1624 vim_free(tf);
1625 }
1626 clear_tv(&tv);
Bram Moolenaara7043832005-01-21 11:56:39 +00001627 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001628 }
1629 }
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001630
1631 vim_free(tofree);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001632 }
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00001633
1634 arg = skipwhite(arg);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001635 }
1636
1637 return arg;
1638}
1639
1640/*
1641 * Set one item of ":let var = expr" or ":let [v1, v2] = list" to its value.
1642 * Returns a pointer to the char just after the var name.
1643 * Returns NULL if there is an error.
1644 */
1645 static char_u *
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001646ex_let_one(arg, tv, copy, endchars, op)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001647 char_u *arg; /* points to variable name */
Bram Moolenaar33570922005-01-25 22:26:29 +00001648 typval_T *tv; /* value to assign to variable */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001649 int copy; /* copy value from "tv" */
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001650 char_u *endchars; /* valid chars after variable name or NULL */
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001651 char_u *op; /* "+", "-", "." or NULL*/
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001652{
1653 int c1;
1654 char_u *name;
1655 char_u *p;
1656 char_u *arg_end = NULL;
1657 int len;
1658 int opt_flags;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001659 char_u *tofree = NULL;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001660
1661 /*
1662 * ":let $VAR = expr": Set environment variable.
1663 */
1664 if (*arg == '$')
1665 {
1666 /* Find the end of the name. */
1667 ++arg;
1668 name = arg;
1669 len = get_env_len(&arg);
1670 if (len == 0)
1671 EMSG2(_(e_invarg2), name - 1);
1672 else
1673 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001674 if (op != NULL && (*op == '+' || *op == '-'))
1675 EMSG2(_(e_letwrong), op);
1676 else if (endchars != NULL
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001677 && vim_strchr(endchars, *skipwhite(arg)) == NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001678 EMSG(_(e_letunexp));
1679 else
1680 {
1681 c1 = name[len];
1682 name[len] = NUL;
1683 p = get_tv_string(tv);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001684 if (op != NULL && *op == '.')
1685 {
1686 int mustfree = FALSE;
1687 char_u *s = vim_getenv(name, &mustfree);
1688
1689 if (s != NULL)
1690 {
1691 p = tofree = concat_str(s, p);
1692 if (mustfree)
1693 vim_free(s);
1694 }
1695 }
1696 if (p != NULL)
1697 vim_setenv(name, p);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001698 if (STRICMP(name, "HOME") == 0)
1699 init_homedir();
1700 else if (didset_vim && STRICMP(name, "VIM") == 0)
1701 didset_vim = FALSE;
1702 else if (didset_vimruntime && STRICMP(name, "VIMRUNTIME") == 0)
1703 didset_vimruntime = FALSE;
1704 name[len] = c1;
1705 arg_end = arg;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001706 vim_free(tofree);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001707 }
1708 }
1709 }
1710
1711 /*
1712 * ":let &option = expr": Set option value.
1713 * ":let &l:option = expr": Set local option value.
1714 * ":let &g:option = expr": Set global option value.
1715 */
1716 else if (*arg == '&')
1717 {
1718 /* Find the end of the name. */
1719 p = find_option_end(&arg, &opt_flags);
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001720 if (p == NULL || (endchars != NULL
1721 && vim_strchr(endchars, *skipwhite(p)) == NULL))
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001722 EMSG(_(e_letunexp));
1723 else
1724 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001725 long n;
1726 int opt_type;
1727 long numval;
1728 char_u *stringval = NULL;
1729 char_u *s;
1730
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001731 c1 = *p;
1732 *p = NUL;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001733
1734 n = get_tv_number(tv);
1735 s = get_tv_string(tv);
1736 if (op != NULL && *op != '=')
1737 {
1738 opt_type = get_option_value(arg, &numval,
1739 &stringval, opt_flags);
1740 if ((opt_type == 1 && *op == '.')
1741 || (opt_type == 0 && *op != '.'))
1742 EMSG2(_(e_letwrong), op);
1743 else
1744 {
1745 if (opt_type == 1) /* number */
1746 {
1747 if (*op == '+')
1748 n = numval + n;
1749 else
1750 n = numval - n;
1751 }
1752 else if (opt_type == 0 && stringval != NULL) /* string */
1753 {
1754 s = concat_str(stringval, s);
1755 vim_free(stringval);
1756 stringval = s;
1757 }
1758 }
1759 }
1760 set_option_value(arg, n, s, opt_flags);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001761 *p = c1;
1762 arg_end = p;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001763 vim_free(stringval);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001764 }
1765 }
1766
1767 /*
1768 * ":let @r = expr": Set register contents.
1769 */
1770 else if (*arg == '@')
1771 {
1772 ++arg;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001773 if (op != NULL && (*op == '+' || *op == '-'))
1774 EMSG2(_(e_letwrong), op);
1775 else if (endchars != NULL
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00001776 && vim_strchr(endchars, *skipwhite(arg + 1)) == NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001777 EMSG(_(e_letunexp));
1778 else
1779 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001780 char_u *tofree = NULL;
1781 char_u *s;
1782
1783 p = get_tv_string(tv);
1784 if (op != NULL && *op == '.')
1785 {
1786 s = get_reg_contents(*arg == '@' ? '"' : *arg, FALSE);
1787 if (s != NULL)
1788 {
1789 p = tofree = concat_str(s, p);
1790 vim_free(s);
1791 }
1792 }
1793 if (p != NULL)
1794 write_reg_contents(*arg == '@' ? '"' : *arg, p, -1, FALSE);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001795 arg_end = arg + 1;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001796 vim_free(tofree);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001797 }
1798 }
1799
1800 /*
1801 * ":let var = expr": Set internal variable.
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00001802 * ":let {expr} = expr": Idem, name made with curly braces
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001803 */
Bram Moolenaare9a41262005-01-15 22:18:47 +00001804 else if ((eval_isnamec(*arg) && !VIM_ISDIGIT(*arg)) || *arg == '{')
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001805 {
Bram Moolenaar33570922005-01-25 22:26:29 +00001806 lval_T lv;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001807
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00001808 p = get_lval(arg, tv, &lv, FALSE, FALSE, FALSE);
1809 if (p != NULL && lv.ll_name != NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001810 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00001811 if (endchars != NULL && vim_strchr(endchars, *skipwhite(p)) == NULL)
1812 EMSG(_(e_letunexp));
1813 else
1814 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001815 set_var_lval(&lv, p, tv, copy, op);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00001816 arg_end = p;
1817 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001818 }
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00001819 clear_lval(&lv);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001820 }
1821
1822 else
1823 EMSG2(_(e_invarg2), arg);
1824
1825 return arg_end;
1826}
1827
1828/*
Bram Moolenaar8c711452005-01-14 21:53:12 +00001829 * If "arg" is equal to "b:changedtick" give an error and return TRUE.
1830 */
1831 static int
1832check_changedtick(arg)
1833 char_u *arg;
1834{
1835 if (STRNCMP(arg, "b:changedtick", 13) == 0 && !eval_isnamec(arg[13]))
1836 {
1837 EMSG2(_(e_readonlyvar), arg);
1838 return TRUE;
1839 }
1840 return FALSE;
1841}
1842
1843/*
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00001844 * Get an lval: variable, Dict item or List item that can be assigned a value
1845 * to: "name", "na{me}", "name[expr]", "name[expr:expr]", "name[expr][expr]",
1846 * "name.key", "name.key[expr]" etc.
1847 * Indexing only works if "name" is an existing List or Dictionary.
1848 * "name" points to the start of the name.
1849 * If "rettv" is not NULL it points to the value to be assigned.
1850 * "unlet" is TRUE for ":unlet": slightly different behavior when something is
1851 * wrong; must end in space or cmd separator.
1852 *
1853 * Returns a pointer to just after the name, including indexes.
Bram Moolenaara7043832005-01-21 11:56:39 +00001854 * When an evaluation error occurs "lp->ll_name" is NULL;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00001855 * Returns NULL for a parsing error. Still need to free items in "lp"!
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001856 */
1857 static char_u *
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00001858get_lval(name, rettv, lp, unlet, skip, quiet)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001859 char_u *name;
Bram Moolenaar33570922005-01-25 22:26:29 +00001860 typval_T *rettv;
1861 lval_T *lp;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00001862 int unlet;
1863 int skip;
1864 int quiet; /* don't give error messages */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001865{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001866 char_u *p;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00001867 char_u *expr_start, *expr_end;
1868 int cc;
Bram Moolenaar33570922005-01-25 22:26:29 +00001869 dictitem_T *v;
1870 typval_T var1;
1871 typval_T var2;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00001872 int empty1 = FALSE;
Bram Moolenaar33570922005-01-25 22:26:29 +00001873 listitem_T *ni;
Bram Moolenaar8c711452005-01-14 21:53:12 +00001874 char_u *key = NULL;
Bram Moolenaar8c711452005-01-14 21:53:12 +00001875 int len;
Bram Moolenaar33570922005-01-25 22:26:29 +00001876 hashtab_T *ht;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001877
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00001878 /* Clear everything in "lp". */
Bram Moolenaar33570922005-01-25 22:26:29 +00001879 vim_memset(lp, 0, sizeof(lval_T));
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00001880
1881 if (skip)
1882 {
1883 /* When skipping just find the end of the name. */
1884 lp->ll_name = name;
1885 return find_name_end(name, NULL, NULL, TRUE);
1886 }
1887
1888 /* Find the end of the name. */
1889 p = find_name_end(name, &expr_start, &expr_end, FALSE);
1890 if (expr_start != NULL)
1891 {
1892 /* Don't expand the name when we already know there is an error. */
1893 if (unlet && !vim_iswhite(*p) && !ends_excmd(*p)
1894 && *p != '[' && *p != '.')
1895 {
1896 EMSG(_(e_trailing));
1897 return NULL;
1898 }
1899
1900 lp->ll_exp_name = make_expanded_name(name, expr_start, expr_end, p);
1901 if (lp->ll_exp_name == NULL)
1902 {
1903 /* Report an invalid expression in braces, unless the
1904 * expression evaluation has been cancelled due to an
1905 * aborting error, an interrupt, or an exception. */
1906 if (!aborting() && !quiet)
1907 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00001908 emsg_severe = TRUE;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00001909 EMSG2(_(e_invarg2), name);
1910 return NULL;
1911 }
1912 }
1913 lp->ll_name = lp->ll_exp_name;
1914 }
1915 else
1916 lp->ll_name = name;
1917
1918 /* Without [idx] or .key we are done. */
1919 if ((*p != '[' && *p != '.') || lp->ll_name == NULL)
1920 return p;
1921
1922 cc = *p;
1923 *p = NUL;
Bram Moolenaara7043832005-01-21 11:56:39 +00001924 v = find_var(lp->ll_name, &ht);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00001925 if (v == NULL && !quiet)
1926 EMSG2(_(e_undefvar), lp->ll_name);
1927 *p = cc;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001928 if (v == NULL)
1929 return NULL;
1930
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00001931 /*
1932 * Loop until no more [idx] or .key is following.
1933 */
Bram Moolenaar33570922005-01-25 22:26:29 +00001934 lp->ll_tv = &v->di_tv;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00001935 while (*p == '[' || (*p == '.' && lp->ll_tv->v_type == VAR_DICT))
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001936 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00001937 if (!(lp->ll_tv->v_type == VAR_LIST && lp->ll_tv->vval.v_list != NULL)
1938 && !(lp->ll_tv->v_type == VAR_DICT
1939 && lp->ll_tv->vval.v_dict != NULL))
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001940 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00001941 if (!quiet)
1942 EMSG(_("E689: Can only index a List or Dictionary"));
1943 return NULL;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001944 }
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00001945 if (lp->ll_range)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001946 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00001947 if (!quiet)
1948 EMSG(_("E708: [:] must come last"));
1949 return NULL;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00001950 }
Bram Moolenaar6cc16192005-01-08 21:49:45 +00001951
Bram Moolenaar8c711452005-01-14 21:53:12 +00001952 len = -1;
1953 if (*p == '.')
1954 {
1955 key = p + 1;
1956 for (len = 0; ASCII_ISALNUM(key[len]) || key[len] == '_'; ++len)
1957 ;
1958 if (len == 0)
1959 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00001960 if (!quiet)
1961 EMSG(_(e_emptykey));
1962 return NULL;
Bram Moolenaar8c711452005-01-14 21:53:12 +00001963 }
1964 p = key + len;
1965 }
Bram Moolenaar6cc16192005-01-08 21:49:45 +00001966 else
1967 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00001968 /* Get the index [expr] or the first index [expr: ]. */
Bram Moolenaar6cc16192005-01-08 21:49:45 +00001969 p = skipwhite(p + 1);
Bram Moolenaar8c711452005-01-14 21:53:12 +00001970 if (*p == ':')
1971 empty1 = TRUE;
Bram Moolenaar6cc16192005-01-08 21:49:45 +00001972 else
1973 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00001974 empty1 = FALSE;
1975 if (eval1(&p, &var1, TRUE) == FAIL) /* recursive! */
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00001976 return NULL;
Bram Moolenaar8c711452005-01-14 21:53:12 +00001977 }
1978
1979 /* Optionally get the second index [ :expr]. */
1980 if (*p == ':')
1981 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00001982 if (lp->ll_tv->v_type == VAR_DICT)
Bram Moolenaar8c711452005-01-14 21:53:12 +00001983 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00001984 if (!quiet)
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00001985 EMSG(_(e_dictrange));
Bram Moolenaar6cc16192005-01-08 21:49:45 +00001986 if (!empty1)
1987 clear_tv(&var1);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00001988 return NULL;
Bram Moolenaar6cc16192005-01-08 21:49:45 +00001989 }
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00001990 if (rettv != NULL && (rettv->v_type != VAR_LIST
1991 || rettv->vval.v_list == NULL))
Bram Moolenaar8c711452005-01-14 21:53:12 +00001992 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00001993 if (!quiet)
1994 EMSG(_("E709: [:] requires a List value"));
Bram Moolenaar8c711452005-01-14 21:53:12 +00001995 if (!empty1)
1996 clear_tv(&var1);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00001997 return NULL;
Bram Moolenaar8c711452005-01-14 21:53:12 +00001998 }
1999 p = skipwhite(p + 1);
2000 if (*p == ']')
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002001 lp->ll_empty2 = TRUE;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002002 else
2003 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002004 lp->ll_empty2 = FALSE;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002005 if (eval1(&p, &var2, TRUE) == FAIL) /* recursive! */
2006 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00002007 if (!empty1)
2008 clear_tv(&var1);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002009 return NULL;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002010 }
2011 }
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002012 lp->ll_range = TRUE;
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002013 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00002014 else
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002015 lp->ll_range = FALSE;
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002016
Bram Moolenaar8c711452005-01-14 21:53:12 +00002017 if (*p != ']')
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002018 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002019 if (!quiet)
2020 EMSG(_(e_missbrac));
Bram Moolenaar8c711452005-01-14 21:53:12 +00002021 if (!empty1)
2022 clear_tv(&var1);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002023 if (lp->ll_range && !lp->ll_empty2)
Bram Moolenaar8c711452005-01-14 21:53:12 +00002024 clear_tv(&var2);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002025 return NULL;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002026 }
2027
2028 /* Skip to past ']'. */
2029 ++p;
2030 }
2031
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002032 if (lp->ll_tv->v_type == VAR_DICT)
Bram Moolenaar8c711452005-01-14 21:53:12 +00002033 {
2034 if (len == -1)
2035 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002036 /* "[key]": get key from "var1" */
Bram Moolenaar8c711452005-01-14 21:53:12 +00002037 key = get_tv_string(&var1);
2038 if (*key == NUL)
2039 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002040 if (!quiet)
2041 EMSG(_(e_emptykey));
Bram Moolenaar8c711452005-01-14 21:53:12 +00002042 clear_tv(&var1);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002043 return NULL;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002044 }
2045 }
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002046 lp->ll_list = NULL;
2047 lp->ll_dict = lp->ll_tv->vval.v_dict;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00002048 lp->ll_di = dict_find(lp->ll_dict, key, len);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002049 if (lp->ll_di == NULL)
Bram Moolenaar8c711452005-01-14 21:53:12 +00002050 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00002051 /* Key does not exist in dict: may need to add it. */
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002052 if (*p == '[' || *p == '.' || unlet)
Bram Moolenaar8c711452005-01-14 21:53:12 +00002053 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002054 if (!quiet)
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002055 EMSG2(_(e_dictkey), key);
Bram Moolenaar8c711452005-01-14 21:53:12 +00002056 if (len == -1)
2057 clear_tv(&var1);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002058 return NULL;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002059 }
2060 if (len == -1)
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002061 lp->ll_newkey = vim_strsave(key);
Bram Moolenaar8c711452005-01-14 21:53:12 +00002062 else
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002063 lp->ll_newkey = vim_strnsave(key, len);
Bram Moolenaar8c711452005-01-14 21:53:12 +00002064 if (len == -1)
2065 clear_tv(&var1);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002066 if (lp->ll_newkey == NULL)
Bram Moolenaar8c711452005-01-14 21:53:12 +00002067 p = NULL;
2068 break;
2069 }
2070 if (len == -1)
2071 clear_tv(&var1);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002072 lp->ll_tv = &lp->ll_di->di_tv;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002073 }
2074 else
2075 {
2076 /*
2077 * Get the number and item for the only or first index of the List.
2078 */
2079 if (empty1)
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002080 lp->ll_n1 = 0;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002081 else
2082 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002083 lp->ll_n1 = get_tv_number(&var1);
Bram Moolenaar8c711452005-01-14 21:53:12 +00002084 clear_tv(&var1);
2085 }
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002086 lp->ll_dict = NULL;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002087 lp->ll_list = lp->ll_tv->vval.v_list;
2088 lp->ll_li = list_find(lp->ll_list, lp->ll_n1);
2089 if (lp->ll_li == NULL)
Bram Moolenaar8c711452005-01-14 21:53:12 +00002090 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002091 if (!quiet)
2092 EMSGN(_(e_listidx), lp->ll_n1);
2093 if (lp->ll_range && !lp->ll_empty2)
Bram Moolenaar8c711452005-01-14 21:53:12 +00002094 clear_tv(&var2);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002095 return NULL;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002096 }
2097
2098 /*
2099 * May need to find the item or absolute index for the second
2100 * index of a range.
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002101 * When no index given: "lp->ll_empty2" is TRUE.
2102 * Otherwise "lp->ll_n2" is set to the second index.
Bram Moolenaar8c711452005-01-14 21:53:12 +00002103 */
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002104 if (lp->ll_range && !lp->ll_empty2)
Bram Moolenaar8c711452005-01-14 21:53:12 +00002105 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002106 lp->ll_n2 = get_tv_number(&var2);
Bram Moolenaar8c711452005-01-14 21:53:12 +00002107 clear_tv(&var2);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002108 if (lp->ll_n2 < 0)
Bram Moolenaar8c711452005-01-14 21:53:12 +00002109 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002110 ni = list_find(lp->ll_list, lp->ll_n2);
Bram Moolenaar8c711452005-01-14 21:53:12 +00002111 if (ni == NULL)
2112 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002113 if (!quiet)
2114 EMSGN(_(e_listidx), lp->ll_n2);
2115 return NULL;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002116 }
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002117 lp->ll_n2 = list_idx_of_item(lp->ll_list, ni);
Bram Moolenaar8c711452005-01-14 21:53:12 +00002118 }
2119
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002120 /* Check that lp->ll_n2 isn't before lp->ll_n1. */
2121 if (lp->ll_n1 < 0)
2122 lp->ll_n1 = list_idx_of_item(lp->ll_list, lp->ll_li);
2123 if (lp->ll_n2 < lp->ll_n1)
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002124 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002125 if (!quiet)
2126 EMSGN(_(e_listidx), lp->ll_n2);
2127 return NULL;
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002128 }
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002129 }
2130
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002131 lp->ll_tv = &lp->ll_li->li_tv;
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002132 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002133 }
2134
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002135 return p;
2136}
2137
2138/*
Bram Moolenaar33570922005-01-25 22:26:29 +00002139 * Clear lval "lp" that was filled by get_lval().
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002140 */
2141 static void
2142clear_lval(lp)
Bram Moolenaar33570922005-01-25 22:26:29 +00002143 lval_T *lp;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002144{
2145 vim_free(lp->ll_exp_name);
2146 vim_free(lp->ll_newkey);
2147}
2148
2149/*
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00002150 * Set a variable that was parsed by get_lval() to "rettv".
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002151 * "endp" points to just after the parsed name.
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002152 * "op" is NULL, "+" for "+=", "-" for "-=", "." for ".=" or "=" for "=".
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002153 */
2154 static void
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002155set_var_lval(lp, endp, rettv, copy, op)
Bram Moolenaar33570922005-01-25 22:26:29 +00002156 lval_T *lp;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002157 char_u *endp;
Bram Moolenaar33570922005-01-25 22:26:29 +00002158 typval_T *rettv;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002159 int copy;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002160 char_u *op;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002161{
2162 int cc;
Bram Moolenaar33570922005-01-25 22:26:29 +00002163 listitem_T *ni;
2164 listitem_T *ri;
2165 dictitem_T *di;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002166
2167 if (lp->ll_tv == NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002168 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002169 if (!check_changedtick(lp->ll_name))
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002170 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002171 cc = *endp;
2172 *endp = NUL;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002173 if (op != NULL && *op != '=')
2174 {
Bram Moolenaar33570922005-01-25 22:26:29 +00002175 typval_T tv;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002176
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00002177 /* handle +=, -= and .= */
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00002178 if (get_var_tv(lp->ll_name, STRLEN(lp->ll_name),
2179 &tv, TRUE) == OK)
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002180 {
2181 if (tv_op(&tv, rettv, op) == OK)
2182 set_var(lp->ll_name, &tv, FALSE);
2183 clear_tv(&tv);
2184 }
2185 }
2186 else
2187 set_var(lp->ll_name, rettv, copy);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002188 *endp = cc;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002189 }
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002190 }
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00002191 else if (tv_check_lock(lp->ll_newkey == NULL
2192 ? lp->ll_tv->v_lock
2193 : lp->ll_tv->vval.v_dict->dv_lock, lp->ll_name))
2194 ;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002195 else if (lp->ll_range)
2196 {
2197 /*
2198 * Assign the List values to the list items.
2199 */
2200 for (ri = rettv->vval.v_list->lv_first; ri != NULL; )
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002201 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002202 if (op != NULL && *op != '=')
2203 tv_op(&lp->ll_li->li_tv, &ri->li_tv, op);
2204 else
2205 {
2206 clear_tv(&lp->ll_li->li_tv);
2207 copy_tv(&ri->li_tv, &lp->ll_li->li_tv);
2208 }
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002209 ri = ri->li_next;
2210 if (ri == NULL || (!lp->ll_empty2 && lp->ll_n2 == lp->ll_n1))
2211 break;
2212 if (lp->ll_li->li_next == NULL)
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002213 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002214 /* Need to add an empty item. */
2215 ni = listitem_alloc();
2216 if (ni == NULL)
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002217 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002218 ri = NULL;
2219 break;
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002220 }
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002221 ni->li_tv.v_type = VAR_NUMBER;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00002222 ni->li_tv.v_lock = 0;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002223 ni->li_tv.vval.v_number = 0;
2224 list_append(lp->ll_list, ni);
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002225 }
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002226 lp->ll_li = lp->ll_li->li_next;
2227 ++lp->ll_n1;
2228 }
2229 if (ri != NULL)
2230 EMSG(_("E710: List value has more items than target"));
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002231 else if (lp->ll_empty2
2232 ? (lp->ll_li != NULL && lp->ll_li->li_next != NULL)
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002233 : lp->ll_n1 != lp->ll_n2)
2234 EMSG(_("E711: List value has not enough items"));
2235 }
2236 else
2237 {
2238 /*
2239 * Assign to a List or Dictionary item.
2240 */
2241 if (lp->ll_newkey != NULL)
2242 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002243 if (op != NULL && *op != '=')
2244 {
2245 EMSG2(_(e_letwrong), op);
2246 return;
2247 }
2248
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002249 /* Need to add an item to the Dictionary. */
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00002250 di = dictitem_alloc(lp->ll_newkey);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002251 if (di == NULL)
2252 return;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00002253 if (dict_add(lp->ll_tv->vval.v_dict, di) == FAIL)
2254 {
2255 vim_free(di);
2256 return;
2257 }
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002258 lp->ll_tv = &di->di_tv;
Bram Moolenaar6cc16192005-01-08 21:49:45 +00002259 }
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002260 else if (op != NULL && *op != '=')
2261 {
2262 tv_op(lp->ll_tv, rettv, op);
2263 return;
2264 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002265 else
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002266 clear_tv(lp->ll_tv);
Bram Moolenaar8c711452005-01-14 21:53:12 +00002267
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002268 /*
2269 * Assign the value to the variable or list item.
2270 */
2271 if (copy)
2272 copy_tv(rettv, lp->ll_tv);
2273 else
2274 {
2275 *lp->ll_tv = *rettv;
Bram Moolenaar758711c2005-02-02 23:11:38 +00002276 lp->ll_tv->v_lock = 0;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002277 init_tv(rettv);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002278 }
2279 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002280}
2281
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002282/*
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002283 * Handle "tv1 += tv2", "tv1 -= tv2" and "tv1 .= tv2"
2284 * Returns OK or FAIL.
2285 */
2286 static int
2287tv_op(tv1, tv2, op)
Bram Moolenaar33570922005-01-25 22:26:29 +00002288 typval_T *tv1;
2289 typval_T *tv2;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002290 char_u *op;
2291{
2292 long n;
2293 char_u numbuf[NUMBUFLEN];
2294 char_u *s;
2295
2296 /* Can't do anything with a Funcref or a Dict on the right. */
2297 if (tv2->v_type != VAR_FUNC && tv2->v_type != VAR_DICT)
2298 {
2299 switch (tv1->v_type)
2300 {
2301 case VAR_DICT:
2302 case VAR_FUNC:
2303 break;
2304
2305 case VAR_LIST:
2306 if (*op != '+' || tv2->v_type != VAR_LIST)
2307 break;
2308 /* List += List */
2309 if (tv1->vval.v_list != NULL && tv2->vval.v_list != NULL)
2310 list_extend(tv1->vval.v_list, tv2->vval.v_list, NULL);
2311 return OK;
2312
2313 case VAR_NUMBER:
2314 case VAR_STRING:
2315 if (tv2->v_type == VAR_LIST)
2316 break;
2317 if (*op == '+' || *op == '-')
2318 {
2319 /* nr += nr or nr -= nr*/
2320 n = get_tv_number(tv1);
2321 if (*op == '+')
2322 n += get_tv_number(tv2);
2323 else
2324 n -= get_tv_number(tv2);
2325 clear_tv(tv1);
2326 tv1->v_type = VAR_NUMBER;
2327 tv1->vval.v_number = n;
2328 }
2329 else
2330 {
2331 /* str .= str */
2332 s = get_tv_string(tv1);
2333 s = concat_str(s, get_tv_string_buf(tv2, numbuf));
2334 clear_tv(tv1);
2335 tv1->v_type = VAR_STRING;
2336 tv1->vval.v_string = s;
2337 }
2338 return OK;
2339 }
2340 }
2341
2342 EMSG2(_(e_letwrong), op);
2343 return FAIL;
2344}
2345
2346/*
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002347 * Add a watcher to a list.
2348 */
2349 static void
2350list_add_watch(l, lw)
Bram Moolenaar33570922005-01-25 22:26:29 +00002351 list_T *l;
2352 listwatch_T *lw;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002353{
2354 lw->lw_next = l->lv_watch;
2355 l->lv_watch = lw;
2356}
2357
2358/*
Bram Moolenaar758711c2005-02-02 23:11:38 +00002359 * Remove a watcher from a list.
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002360 * No warning when it isn't found...
2361 */
2362 static void
2363list_rem_watch(l, lwrem)
Bram Moolenaar33570922005-01-25 22:26:29 +00002364 list_T *l;
2365 listwatch_T *lwrem;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002366{
Bram Moolenaar33570922005-01-25 22:26:29 +00002367 listwatch_T *lw, **lwp;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002368
2369 lwp = &l->lv_watch;
2370 for (lw = l->lv_watch; lw != NULL; lw = lw->lw_next)
2371 {
2372 if (lw == lwrem)
2373 {
2374 *lwp = lw->lw_next;
2375 break;
2376 }
2377 lwp = &lw->lw_next;
2378 }
2379}
2380
2381/*
2382 * Just before removing an item from a list: advance watchers to the next
2383 * item.
2384 */
2385 static void
2386list_fix_watch(l, item)
Bram Moolenaar33570922005-01-25 22:26:29 +00002387 list_T *l;
2388 listitem_T *item;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002389{
Bram Moolenaar33570922005-01-25 22:26:29 +00002390 listwatch_T *lw;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002391
2392 for (lw = l->lv_watch; lw != NULL; lw = lw->lw_next)
2393 if (lw->lw_item == item)
2394 lw->lw_item = item->li_next;
2395}
2396
2397/*
2398 * Evaluate the expression used in a ":for var in expr" command.
2399 * "arg" points to "var".
2400 * Set "*errp" to TRUE for an error, FALSE otherwise;
2401 * Return a pointer that holds the info. Null when there is an error.
2402 */
2403 void *
2404eval_for_line(arg, errp, nextcmdp, skip)
2405 char_u *arg;
2406 int *errp;
2407 char_u **nextcmdp;
2408 int skip;
2409{
Bram Moolenaar33570922005-01-25 22:26:29 +00002410 forinfo_T *fi;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002411 char_u *expr;
Bram Moolenaar33570922005-01-25 22:26:29 +00002412 typval_T tv;
2413 list_T *l;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002414
2415 *errp = TRUE; /* default: there is an error */
2416
Bram Moolenaar33570922005-01-25 22:26:29 +00002417 fi = (forinfo_T *)alloc_clear(sizeof(forinfo_T));
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002418 if (fi == NULL)
2419 return NULL;
2420
2421 expr = skip_var_list(arg, &fi->fi_varcount, &fi->fi_semicolon);
2422 if (expr == NULL)
2423 return fi;
2424
2425 expr = skipwhite(expr);
2426 if (expr[0] != 'i' || expr[1] != 'n' || !vim_iswhite(expr[2]))
2427 {
Bram Moolenaare49b69a2005-01-08 16:11:57 +00002428 EMSG(_("E690: Missing \"in\" after :for"));
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002429 return fi;
2430 }
2431
2432 if (skip)
2433 ++emsg_skip;
2434 if (eval0(skipwhite(expr + 2), &tv, nextcmdp, !skip) == OK)
2435 {
2436 *errp = FALSE;
2437 if (!skip)
2438 {
2439 l = tv.vval.v_list;
2440 if (tv.v_type != VAR_LIST || l == NULL)
2441 EMSG(_(e_listreq));
2442 else
2443 {
2444 fi->fi_list = l;
2445 list_add_watch(l, &fi->fi_lw);
2446 fi->fi_lw.lw_item = l->lv_first;
2447 }
2448 }
2449 }
2450 if (skip)
2451 --emsg_skip;
2452
2453 return fi;
2454}
2455
2456/*
2457 * Use the first item in a ":for" list. Advance to the next.
2458 * Assign the values to the variable (list). "arg" points to the first one.
2459 * Return TRUE when a valid item was found, FALSE when at end of list or
2460 * something wrong.
2461 */
2462 int
2463next_for_item(fi_void, arg)
2464 void *fi_void;
2465 char_u *arg;
2466{
Bram Moolenaar33570922005-01-25 22:26:29 +00002467 forinfo_T *fi = (forinfo_T *)fi_void;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002468 int result;
Bram Moolenaar33570922005-01-25 22:26:29 +00002469 listitem_T *item;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002470
2471 item = fi->fi_lw.lw_item;
2472 if (item == NULL)
2473 result = FALSE;
2474 else
2475 {
2476 fi->fi_lw.lw_item = item->li_next;
2477 result = (ex_let_vars(arg, &item->li_tv, TRUE,
2478 fi->fi_semicolon, fi->fi_varcount, NULL) == OK);
2479 }
2480 return result;
2481}
2482
2483/*
2484 * Free the structure used to store info used by ":for".
2485 */
2486 void
2487free_for_info(fi_void)
2488 void *fi_void;
2489{
Bram Moolenaar33570922005-01-25 22:26:29 +00002490 forinfo_T *fi = (forinfo_T *)fi_void;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002491
Bram Moolenaarab7013c2005-01-09 21:23:56 +00002492 if (fi != NULL && fi->fi_list != NULL)
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002493 list_rem_watch(fi->fi_list, &fi->fi_lw);
2494 vim_free(fi);
2495}
2496
Bram Moolenaar071d4272004-06-13 20:20:40 +00002497#if defined(FEAT_CMDL_COMPL) || defined(PROTO)
2498
2499 void
2500set_context_for_expression(xp, arg, cmdidx)
2501 expand_T *xp;
2502 char_u *arg;
2503 cmdidx_T cmdidx;
2504{
2505 int got_eq = FALSE;
2506 int c;
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002507 char_u *p;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002508
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002509 if (cmdidx == CMD_let)
2510 {
2511 xp->xp_context = EXPAND_USER_VARS;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00002512 if (vim_strpbrk(arg, (char_u *)"\"'+-*/%.=!?~|&$([<>,#") == NULL)
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002513 {
2514 /* ":let var1 var2 ...": find last space. */
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00002515 for (p = arg + STRLEN(arg); p >= arg; )
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002516 {
2517 xp->xp_pattern = p;
Bram Moolenaar33570922005-01-25 22:26:29 +00002518 mb_ptr_back(arg, p);
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002519 if (vim_iswhite(*p))
2520 break;
2521 }
2522 return;
2523 }
2524 }
2525 else
2526 xp->xp_context = cmdidx == CMD_call ? EXPAND_FUNCTIONS
2527 : EXPAND_EXPRESSION;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002528 while ((xp->xp_pattern = vim_strpbrk(arg,
2529 (char_u *)"\"'+-*/%.=!?~|&$([<>,#")) != NULL)
2530 {
2531 c = *xp->xp_pattern;
2532 if (c == '&')
2533 {
2534 c = xp->xp_pattern[1];
2535 if (c == '&')
2536 {
2537 ++xp->xp_pattern;
2538 xp->xp_context = cmdidx != CMD_let || got_eq
2539 ? EXPAND_EXPRESSION : EXPAND_NOTHING;
2540 }
2541 else if (c != ' ')
2542 xp->xp_context = EXPAND_SETTINGS;
2543 }
2544 else if (c == '$')
2545 {
2546 /* environment variable */
2547 xp->xp_context = EXPAND_ENV_VARS;
2548 }
2549 else if (c == '=')
2550 {
2551 got_eq = TRUE;
2552 xp->xp_context = EXPAND_EXPRESSION;
2553 }
2554 else if (c == '<'
2555 && xp->xp_context == EXPAND_FUNCTIONS
2556 && vim_strchr(xp->xp_pattern, '(') == NULL)
2557 {
2558 /* Function name can start with "<SNR>" */
2559 break;
2560 }
2561 else if (cmdidx != CMD_let || got_eq)
2562 {
2563 if (c == '"') /* string */
2564 {
2565 while ((c = *++xp->xp_pattern) != NUL && c != '"')
2566 if (c == '\\' && xp->xp_pattern[1] != NUL)
2567 ++xp->xp_pattern;
2568 xp->xp_context = EXPAND_NOTHING;
2569 }
2570 else if (c == '\'') /* literal string */
2571 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00002572 /* Trick: '' is like stopping and starting a literal string. */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002573 while ((c = *++xp->xp_pattern) != NUL && c != '\'')
2574 /* skip */ ;
2575 xp->xp_context = EXPAND_NOTHING;
2576 }
2577 else if (c == '|')
2578 {
2579 if (xp->xp_pattern[1] == '|')
2580 {
2581 ++xp->xp_pattern;
2582 xp->xp_context = EXPAND_EXPRESSION;
2583 }
2584 else
2585 xp->xp_context = EXPAND_COMMANDS;
2586 }
2587 else
2588 xp->xp_context = EXPAND_EXPRESSION;
2589 }
2590 else
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00002591 /* Doesn't look like something valid, expand as an expression
2592 * anyway. */
2593 xp->xp_context = EXPAND_EXPRESSION;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002594 arg = xp->xp_pattern;
2595 if (*arg != NUL)
2596 while ((c = *++arg) != NUL && (c == ' ' || c == '\t'))
2597 /* skip */ ;
2598 }
2599 xp->xp_pattern = arg;
2600}
2601
2602#endif /* FEAT_CMDL_COMPL */
2603
2604/*
2605 * ":1,25call func(arg1, arg2)" function call.
2606 */
2607 void
2608ex_call(eap)
2609 exarg_T *eap;
2610{
2611 char_u *arg = eap->arg;
2612 char_u *startarg;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002613 char_u *name;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002614 char_u *tofree;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002615 int len;
Bram Moolenaar33570922005-01-25 22:26:29 +00002616 typval_T rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002617 linenr_T lnum;
2618 int doesrange;
2619 int failed = FALSE;
Bram Moolenaar33570922005-01-25 22:26:29 +00002620 funcdict_T fudi;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002621
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00002622 tofree = trans_function_name(&arg, eap->skip, TFN_INT, &fudi);
2623 vim_free(fudi.fd_newkey);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002624 if (tofree == NULL)
2625 return;
2626
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00002627 /* Increase refcount on dictionary, it could get deleted when evaluating
2628 * the arguments. */
2629 if (fudi.fd_dict != NULL)
2630 ++fudi.fd_dict->dv_refcount;
2631
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002632 /* If it is the name of a variable of type VAR_FUNC use its contents. */
2633 len = STRLEN(tofree);
2634 name = deref_func_name(tofree, &len);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002635
Bram Moolenaar532c7802005-01-27 14:44:31 +00002636 /* Skip white space to allow ":call func ()". Not good, but required for
2637 * backward compatibility. */
2638 startarg = skipwhite(arg);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002639 rettv.v_type = VAR_UNKNOWN; /* clear_tv() uses this */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002640
2641 if (*startarg != '(')
2642 {
Bram Moolenaar81bf7082005-02-12 14:31:42 +00002643 EMSG2(_("E107: Missing braces: %s"), eap->arg);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002644 goto end;
2645 }
2646
2647 /*
2648 * When skipping, evaluate the function once, to find the end of the
2649 * arguments.
2650 * When the function takes a range, this is discovered after the first
2651 * call, and the loop is broken.
2652 */
2653 if (eap->skip)
2654 {
2655 ++emsg_skip;
2656 lnum = eap->line2; /* do it once, also with an invalid range */
2657 }
2658 else
2659 lnum = eap->line1;
2660 for ( ; lnum <= eap->line2; ++lnum)
2661 {
2662 if (!eap->skip && eap->addr_count > 0)
2663 {
2664 curwin->w_cursor.lnum = lnum;
2665 curwin->w_cursor.col = 0;
2666 }
2667 arg = startarg;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002668 if (get_func_tv(name, STRLEN(name), &rettv, &arg,
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00002669 eap->line1, eap->line2, &doesrange,
2670 !eap->skip, fudi.fd_dict) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002671 {
2672 failed = TRUE;
2673 break;
2674 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002675 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002676 if (doesrange || eap->skip)
2677 break;
2678 /* Stop when immediately aborting on error, or when an interrupt
Bram Moolenaar49cd9572005-01-03 21:06:01 +00002679 * occurred or an exception was thrown but not caught.
Bram Moolenaarc70646c2005-01-04 21:52:38 +00002680 * get_func_tv() returned OK, so that the check for trailing
Bram Moolenaar49cd9572005-01-03 21:06:01 +00002681 * characters below is executed. */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002682 if (aborting())
2683 break;
2684 }
2685 if (eap->skip)
2686 --emsg_skip;
2687
2688 if (!failed)
2689 {
2690 /* Check for trailing illegal characters and a following command. */
2691 if (!ends_excmd(*arg))
2692 {
2693 emsg_severe = TRUE;
2694 EMSG(_(e_trailing));
2695 }
2696 else
2697 eap->nextcmd = check_nextcmd(arg);
2698 }
2699
2700end:
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00002701 dict_unref(fudi.fd_dict);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00002702 vim_free(tofree);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002703}
2704
2705/*
2706 * ":unlet[!] var1 ... " command.
2707 */
2708 void
2709ex_unlet(eap)
2710 exarg_T *eap;
2711{
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00002712 ex_unletlock(eap, eap->arg, 0);
2713}
2714
2715/*
2716 * ":lockvar" and ":unlockvar" commands
2717 */
2718 void
2719ex_lockvar(eap)
2720 exarg_T *eap;
2721{
Bram Moolenaar071d4272004-06-13 20:20:40 +00002722 char_u *arg = eap->arg;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00002723 int deep = 2;
2724
2725 if (eap->forceit)
2726 deep = -1;
2727 else if (vim_isdigit(*arg))
2728 {
2729 deep = getdigits(&arg);
2730 arg = skipwhite(arg);
2731 }
2732
2733 ex_unletlock(eap, arg, deep);
2734}
2735
2736/*
2737 * ":unlet", ":lockvar" and ":unlockvar" are quite similar.
2738 */
2739 static void
2740ex_unletlock(eap, argstart, deep)
2741 exarg_T *eap;
2742 char_u *argstart;
2743 int deep;
2744{
2745 char_u *arg = argstart;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002746 char_u *name_end;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002747 int error = FALSE;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00002748 lval_T lv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002749
2750 do
2751 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002752 /* Parse the name and find the end. */
2753 name_end = get_lval(arg, NULL, &lv, TRUE, eap->skip || error, FALSE);
2754 if (lv.ll_name == NULL)
2755 error = TRUE; /* error but continue parsing */
2756 if (name_end == NULL || (!vim_iswhite(*name_end)
2757 && !ends_excmd(*name_end)))
Bram Moolenaar071d4272004-06-13 20:20:40 +00002758 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002759 if (name_end != NULL)
2760 {
2761 emsg_severe = TRUE;
2762 EMSG(_(e_trailing));
2763 }
2764 if (!(eap->skip || error))
2765 clear_lval(&lv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002766 break;
2767 }
2768
2769 if (!error && !eap->skip)
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00002770 {
2771 if (eap->cmdidx == CMD_unlet)
2772 {
2773 if (do_unlet_var(&lv, name_end, eap->forceit) == FAIL)
2774 error = TRUE;
2775 }
2776 else
2777 {
2778 if (do_lock_var(&lv, name_end, deep,
2779 eap->cmdidx == CMD_lockvar) == FAIL)
2780 error = TRUE;
2781 }
2782 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00002783
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002784 if (!eap->skip)
2785 clear_lval(&lv);
2786
Bram Moolenaar071d4272004-06-13 20:20:40 +00002787 arg = skipwhite(name_end);
2788 } while (!ends_excmd(*arg));
2789
2790 eap->nextcmd = check_nextcmd(arg);
2791}
2792
Bram Moolenaar8c711452005-01-14 21:53:12 +00002793 static int
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002794do_unlet_var(lp, name_end, forceit)
Bram Moolenaar33570922005-01-25 22:26:29 +00002795 lval_T *lp;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002796 char_u *name_end;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002797 int forceit;
2798{
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002799 int ret = OK;
2800 int cc;
2801
2802 if (lp->ll_tv == NULL)
Bram Moolenaar8c711452005-01-14 21:53:12 +00002803 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002804 cc = *name_end;
2805 *name_end = NUL;
2806
2807 /* Normal name or expanded name. */
2808 if (check_changedtick(lp->ll_name))
2809 ret = FAIL;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00002810 else if (do_unlet(lp->ll_name, forceit) == FAIL)
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002811 ret = FAIL;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002812 *name_end = cc;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002813 }
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00002814 else if (tv_check_lock(lp->ll_tv->v_lock, lp->ll_name))
2815 return FAIL;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002816 else if (lp->ll_range)
2817 {
Bram Moolenaar33570922005-01-25 22:26:29 +00002818 listitem_T *li;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002819
2820 /* Delete a range of List items. */
2821 while (lp->ll_li != NULL && (lp->ll_empty2 || lp->ll_n2 >= lp->ll_n1))
2822 {
2823 li = lp->ll_li->li_next;
2824 listitem_remove(lp->ll_list, lp->ll_li);
2825 lp->ll_li = li;
2826 ++lp->ll_n1;
2827 }
2828 }
2829 else
2830 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002831 if (lp->ll_list != NULL)
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002832 /* unlet a List item. */
2833 listitem_remove(lp->ll_list, lp->ll_li);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002834 else
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002835 /* unlet a Dictionary item. */
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00002836 dictitem_remove(lp->ll_dict, lp->ll_di);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00002837 }
2838
2839 return ret;
Bram Moolenaar8c711452005-01-14 21:53:12 +00002840}
2841
Bram Moolenaar071d4272004-06-13 20:20:40 +00002842/*
2843 * "unlet" a variable. Return OK if it existed, FAIL if not.
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00002844 * When "forceit" is TRUE don't complain if the variable doesn't exist.
Bram Moolenaar071d4272004-06-13 20:20:40 +00002845 */
2846 int
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00002847do_unlet(name, forceit)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002848 char_u *name;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00002849 int forceit;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002850{
Bram Moolenaar33570922005-01-25 22:26:29 +00002851 hashtab_T *ht;
2852 hashitem_T *hi;
Bram Moolenaara7043832005-01-21 11:56:39 +00002853 char_u *varname;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002854
Bram Moolenaar33570922005-01-25 22:26:29 +00002855 ht = find_var_ht(name, &varname);
2856 if (ht != NULL && *varname != NUL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002857 {
Bram Moolenaar33570922005-01-25 22:26:29 +00002858 hi = hash_find(ht, varname);
2859 if (!HASHITEM_EMPTY(hi))
Bram Moolenaara7043832005-01-21 11:56:39 +00002860 {
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00002861 if (var_check_ro(HI2DI(hi)->di_flags, name))
2862 return FAIL;
2863 delete_var(ht, hi);
2864 return OK;
Bram Moolenaara7043832005-01-21 11:56:39 +00002865 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00002866 }
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00002867 if (forceit)
2868 return OK;
2869 EMSG2(_("E108: No such variable: \"%s\""), name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002870 return FAIL;
2871}
2872
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00002873/*
2874 * Lock or unlock variable indicated by "lp".
2875 * "deep" is the levels to go (-1 for unlimited);
2876 * "lock" is TRUE for ":lockvar", FALSE for ":unlockvar".
2877 */
2878 static int
2879do_lock_var(lp, name_end, deep, lock)
2880 lval_T *lp;
2881 char_u *name_end;
2882 int deep;
2883 int lock;
2884{
2885 int ret = OK;
2886 int cc;
2887 dictitem_T *di;
2888
2889 if (deep == 0) /* nothing to do */
2890 return OK;
2891
2892 if (lp->ll_tv == NULL)
2893 {
2894 cc = *name_end;
2895 *name_end = NUL;
2896
2897 /* Normal name or expanded name. */
2898 if (check_changedtick(lp->ll_name))
2899 ret = FAIL;
2900 else
2901 {
2902 di = find_var(lp->ll_name, NULL);
2903 if (di == NULL)
2904 ret = FAIL;
2905 else
2906 {
2907 if (lock)
2908 di->di_flags |= DI_FLAGS_LOCK;
2909 else
2910 di->di_flags &= ~DI_FLAGS_LOCK;
2911 item_lock(&di->di_tv, deep, lock);
2912 }
2913 }
2914 *name_end = cc;
2915 }
2916 else if (lp->ll_range)
2917 {
2918 listitem_T *li = lp->ll_li;
2919
2920 /* (un)lock a range of List items. */
2921 while (li != NULL && (lp->ll_empty2 || lp->ll_n2 >= lp->ll_n1))
2922 {
2923 item_lock(&li->li_tv, deep, lock);
2924 li = li->li_next;
2925 ++lp->ll_n1;
2926 }
2927 }
2928 else if (lp->ll_list != NULL)
2929 /* (un)lock a List item. */
2930 item_lock(&lp->ll_li->li_tv, deep, lock);
2931 else
2932 /* un(lock) a Dictionary item. */
2933 item_lock(&lp->ll_di->di_tv, deep, lock);
2934
2935 return ret;
2936}
2937
2938/*
2939 * Lock or unlock an item. "deep" is nr of levels to go.
2940 */
2941 static void
2942item_lock(tv, deep, lock)
2943 typval_T *tv;
2944 int deep;
2945 int lock;
2946{
2947 static int recurse = 0;
2948 list_T *l;
2949 listitem_T *li;
2950 dict_T *d;
2951 hashitem_T *hi;
2952 int todo;
2953
2954 if (recurse >= DICT_MAXNEST)
2955 {
2956 EMSG(_("E743: variable nested too deep for (un)lock"));
2957 return;
2958 }
2959 if (deep == 0)
2960 return;
2961 ++recurse;
2962
2963 /* lock/unlock the item itself */
2964 if (lock)
2965 tv->v_lock |= VAR_LOCKED;
2966 else
2967 tv->v_lock &= ~VAR_LOCKED;
2968
2969 switch (tv->v_type)
2970 {
2971 case VAR_LIST:
2972 if ((l = tv->vval.v_list) != NULL)
2973 {
2974 if (lock)
2975 l->lv_lock |= VAR_LOCKED;
2976 else
2977 l->lv_lock &= ~VAR_LOCKED;
2978 if (deep < 0 || deep > 1)
2979 /* recursive: lock/unlock the items the List contains */
2980 for (li = l->lv_first; li != NULL; li = li->li_next)
2981 item_lock(&li->li_tv, deep - 1, lock);
2982 }
2983 break;
2984 case VAR_DICT:
2985 if ((d = tv->vval.v_dict) != NULL)
2986 {
2987 if (lock)
2988 d->dv_lock |= VAR_LOCKED;
2989 else
2990 d->dv_lock &= ~VAR_LOCKED;
2991 if (deep < 0 || deep > 1)
2992 {
2993 /* recursive: lock/unlock the items the List contains */
2994 todo = d->dv_hashtab.ht_used;
2995 for (hi = d->dv_hashtab.ht_array; todo > 0; ++hi)
2996 {
2997 if (!HASHITEM_EMPTY(hi))
2998 {
2999 --todo;
3000 item_lock(&HI2DI(hi)->di_tv, deep - 1, lock);
3001 }
3002 }
3003 }
3004 }
3005 }
3006 --recurse;
3007}
3008
Bram Moolenaar071d4272004-06-13 20:20:40 +00003009#if (defined(FEAT_MENU) && defined(FEAT_MULTI_LANG)) || defined(PROTO)
3010/*
3011 * Delete all "menutrans_" variables.
3012 */
3013 void
3014del_menutrans_vars()
3015{
Bram Moolenaar33570922005-01-25 22:26:29 +00003016 hashitem_T *hi;
Bram Moolenaara7043832005-01-21 11:56:39 +00003017 int todo;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003018
Bram Moolenaar33570922005-01-25 22:26:29 +00003019 hash_lock(&globvarht);
3020 todo = globvarht.ht_used;
3021 for (hi = globvarht.ht_array; todo > 0 && !got_int; ++hi)
Bram Moolenaara7043832005-01-21 11:56:39 +00003022 {
3023 if (!HASHITEM_EMPTY(hi))
3024 {
3025 --todo;
Bram Moolenaar33570922005-01-25 22:26:29 +00003026 if (STRNCMP(HI2DI(hi)->di_key, "menutrans_", 10) == 0)
3027 delete_var(&globvarht, hi);
Bram Moolenaara7043832005-01-21 11:56:39 +00003028 }
3029 }
Bram Moolenaar33570922005-01-25 22:26:29 +00003030 hash_unlock(&globvarht);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003031}
3032#endif
3033
3034#if defined(FEAT_CMDL_COMPL) || defined(PROTO)
3035
3036/*
3037 * Local string buffer for the next two functions to store a variable name
3038 * with its prefix. Allocated in cat_prefix_varname(), freed later in
3039 * get_user_var_name().
3040 */
3041
3042static char_u *cat_prefix_varname __ARGS((int prefix, char_u *name));
3043
3044static char_u *varnamebuf = NULL;
3045static int varnamebuflen = 0;
3046
3047/*
3048 * Function to concatenate a prefix and a variable name.
3049 */
3050 static char_u *
3051cat_prefix_varname(prefix, name)
3052 int prefix;
3053 char_u *name;
3054{
3055 int len;
3056
3057 len = (int)STRLEN(name) + 3;
3058 if (len > varnamebuflen)
3059 {
3060 vim_free(varnamebuf);
3061 len += 10; /* some additional space */
3062 varnamebuf = alloc(len);
3063 if (varnamebuf == NULL)
3064 {
3065 varnamebuflen = 0;
3066 return NULL;
3067 }
3068 varnamebuflen = len;
3069 }
3070 *varnamebuf = prefix;
3071 varnamebuf[1] = ':';
3072 STRCPY(varnamebuf + 2, name);
3073 return varnamebuf;
3074}
3075
3076/*
3077 * Function given to ExpandGeneric() to obtain the list of user defined
3078 * (global/buffer/window/built-in) variable names.
3079 */
3080/*ARGSUSED*/
3081 char_u *
3082get_user_var_name(xp, idx)
3083 expand_T *xp;
3084 int idx;
3085{
Bram Moolenaar532c7802005-01-27 14:44:31 +00003086 static long_u gdone;
3087 static long_u bdone;
3088 static long_u wdone;
3089 static int vidx;
3090 static hashitem_T *hi;
3091 hashtab_T *ht;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003092
3093 if (idx == 0)
Bram Moolenaara7043832005-01-21 11:56:39 +00003094 gdone = bdone = wdone = vidx = 0;
Bram Moolenaar33570922005-01-25 22:26:29 +00003095
3096 /* Global variables */
3097 if (gdone < globvarht.ht_used)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003098 {
Bram Moolenaara7043832005-01-21 11:56:39 +00003099 if (gdone++ == 0)
Bram Moolenaar33570922005-01-25 22:26:29 +00003100 hi = globvarht.ht_array;
Bram Moolenaar532c7802005-01-27 14:44:31 +00003101 else
3102 ++hi;
Bram Moolenaara7043832005-01-21 11:56:39 +00003103 while (HASHITEM_EMPTY(hi))
3104 ++hi;
3105 if (STRNCMP("g:", xp->xp_pattern, 2) == 0)
3106 return cat_prefix_varname('g', hi->hi_key);
3107 return hi->hi_key;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003108 }
Bram Moolenaar33570922005-01-25 22:26:29 +00003109
3110 /* b: variables */
3111 ht = &curbuf->b_vars.dv_hashtab;
3112 if (bdone < ht->ht_used)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003113 {
Bram Moolenaara7043832005-01-21 11:56:39 +00003114 if (bdone++ == 0)
Bram Moolenaar33570922005-01-25 22:26:29 +00003115 hi = ht->ht_array;
Bram Moolenaar532c7802005-01-27 14:44:31 +00003116 else
3117 ++hi;
Bram Moolenaara7043832005-01-21 11:56:39 +00003118 while (HASHITEM_EMPTY(hi))
3119 ++hi;
3120 return cat_prefix_varname('b', hi->hi_key);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003121 }
Bram Moolenaar33570922005-01-25 22:26:29 +00003122 if (bdone == ht->ht_used)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003123 {
Bram Moolenaara7043832005-01-21 11:56:39 +00003124 ++bdone;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003125 return (char_u *)"b:changedtick";
3126 }
Bram Moolenaar33570922005-01-25 22:26:29 +00003127
3128 /* w: variables */
3129 ht = &curwin->w_vars.dv_hashtab;
3130 if (wdone < ht->ht_used)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003131 {
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +00003132 if (wdone++ == 0)
Bram Moolenaar33570922005-01-25 22:26:29 +00003133 hi = ht->ht_array;
Bram Moolenaar532c7802005-01-27 14:44:31 +00003134 else
3135 ++hi;
Bram Moolenaara7043832005-01-21 11:56:39 +00003136 while (HASHITEM_EMPTY(hi))
3137 ++hi;
3138 return cat_prefix_varname('w', hi->hi_key);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003139 }
Bram Moolenaar33570922005-01-25 22:26:29 +00003140
3141 /* v: variables */
3142 if (vidx < VV_LEN)
3143 return cat_prefix_varname('v', (char_u *)vimvars[vidx++].vv_name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003144
3145 vim_free(varnamebuf);
3146 varnamebuf = NULL;
3147 varnamebuflen = 0;
3148 return NULL;
3149}
3150
3151#endif /* FEAT_CMDL_COMPL */
3152
3153/*
3154 * types for expressions.
3155 */
3156typedef enum
3157{
3158 TYPE_UNKNOWN = 0
3159 , TYPE_EQUAL /* == */
3160 , TYPE_NEQUAL /* != */
3161 , TYPE_GREATER /* > */
3162 , TYPE_GEQUAL /* >= */
3163 , TYPE_SMALLER /* < */
3164 , TYPE_SEQUAL /* <= */
3165 , TYPE_MATCH /* =~ */
3166 , TYPE_NOMATCH /* !~ */
3167} exptype_T;
3168
3169/*
3170 * The "evaluate" argument: When FALSE, the argument is only parsed but not
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003171 * executed. The function may return OK, but the rettv will be of type
Bram Moolenaar071d4272004-06-13 20:20:40 +00003172 * VAR_UNKNOWN. The function still returns FAIL for a syntax error.
3173 */
3174
3175/*
3176 * Handle zero level expression.
3177 * This calls eval1() and handles error message and nextcmd.
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003178 * Put the result in "rettv" when returning OK and "evaluate" is TRUE.
Bram Moolenaar071d4272004-06-13 20:20:40 +00003179 * Return OK or FAIL.
3180 */
3181 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003182eval0(arg, rettv, nextcmd, evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003183 char_u *arg;
Bram Moolenaar33570922005-01-25 22:26:29 +00003184 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003185 char_u **nextcmd;
3186 int evaluate;
3187{
3188 int ret;
3189 char_u *p;
3190
3191 p = skipwhite(arg);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003192 ret = eval1(&p, rettv, evaluate);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003193 if (ret == FAIL || !ends_excmd(*p))
3194 {
3195 if (ret != FAIL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003196 clear_tv(rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003197 /*
3198 * Report the invalid expression unless the expression evaluation has
3199 * been cancelled due to an aborting error, an interrupt, or an
3200 * exception.
3201 */
3202 if (!aborting())
3203 EMSG2(_(e_invexpr2), arg);
3204 ret = FAIL;
3205 }
3206 if (nextcmd != NULL)
3207 *nextcmd = check_nextcmd(p);
3208
3209 return ret;
3210}
3211
3212/*
3213 * Handle top level expression:
3214 * expr1 ? expr0 : expr0
3215 *
3216 * "arg" must point to the first non-white of the expression.
3217 * "arg" is advanced to the next non-white after the recognized expression.
3218 *
3219 * Return OK or FAIL.
3220 */
3221 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003222eval1(arg, rettv, evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003223 char_u **arg;
Bram Moolenaar33570922005-01-25 22:26:29 +00003224 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003225 int evaluate;
3226{
3227 int result;
Bram Moolenaar33570922005-01-25 22:26:29 +00003228 typval_T var2;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003229
3230 /*
3231 * Get the first variable.
3232 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003233 if (eval2(arg, rettv, evaluate) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003234 return FAIL;
3235
3236 if ((*arg)[0] == '?')
3237 {
3238 result = FALSE;
3239 if (evaluate)
3240 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003241 if (get_tv_number(rettv) != 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003242 result = TRUE;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003243 clear_tv(rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003244 }
3245
3246 /*
3247 * Get the second variable.
3248 */
3249 *arg = skipwhite(*arg + 1);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003250 if (eval1(arg, rettv, evaluate && result) == FAIL) /* recursive! */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003251 return FAIL;
3252
3253 /*
3254 * Check for the ":".
3255 */
3256 if ((*arg)[0] != ':')
3257 {
3258 EMSG(_("E109: Missing ':' after '?'"));
3259 if (evaluate && result)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003260 clear_tv(rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003261 return FAIL;
3262 }
3263
3264 /*
3265 * Get the third variable.
3266 */
3267 *arg = skipwhite(*arg + 1);
3268 if (eval1(arg, &var2, evaluate && !result) == FAIL) /* recursive! */
3269 {
3270 if (evaluate && result)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003271 clear_tv(rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003272 return FAIL;
3273 }
3274 if (evaluate && !result)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003275 *rettv = var2;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003276 }
3277
3278 return OK;
3279}
3280
3281/*
3282 * Handle first level expression:
3283 * expr2 || expr2 || expr2 logical OR
3284 *
3285 * "arg" must point to the first non-white of the expression.
3286 * "arg" is advanced to the next non-white after the recognized expression.
3287 *
3288 * Return OK or FAIL.
3289 */
3290 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003291eval2(arg, rettv, evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003292 char_u **arg;
Bram Moolenaar33570922005-01-25 22:26:29 +00003293 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003294 int evaluate;
3295{
Bram Moolenaar33570922005-01-25 22:26:29 +00003296 typval_T var2;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003297 long result;
3298 int first;
3299
3300 /*
3301 * Get the first variable.
3302 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003303 if (eval3(arg, rettv, evaluate) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003304 return FAIL;
3305
3306 /*
3307 * Repeat until there is no following "||".
3308 */
3309 first = TRUE;
3310 result = FALSE;
3311 while ((*arg)[0] == '|' && (*arg)[1] == '|')
3312 {
3313 if (evaluate && first)
3314 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003315 if (get_tv_number(rettv) != 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003316 result = TRUE;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003317 clear_tv(rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003318 first = FALSE;
3319 }
3320
3321 /*
3322 * Get the second variable.
3323 */
3324 *arg = skipwhite(*arg + 2);
3325 if (eval3(arg, &var2, evaluate && !result) == FAIL)
3326 return FAIL;
3327
3328 /*
3329 * Compute the result.
3330 */
3331 if (evaluate && !result)
3332 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003333 if (get_tv_number(&var2) != 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003334 result = TRUE;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003335 clear_tv(&var2);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003336 }
3337 if (evaluate)
3338 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003339 rettv->v_type = VAR_NUMBER;
3340 rettv->vval.v_number = result;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003341 }
3342 }
3343
3344 return OK;
3345}
3346
3347/*
3348 * Handle second level expression:
3349 * expr3 && expr3 && expr3 logical AND
3350 *
3351 * "arg" must point to the first non-white of the expression.
3352 * "arg" is advanced to the next non-white after the recognized expression.
3353 *
3354 * Return OK or FAIL.
3355 */
3356 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003357eval3(arg, rettv, evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003358 char_u **arg;
Bram Moolenaar33570922005-01-25 22:26:29 +00003359 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003360 int evaluate;
3361{
Bram Moolenaar33570922005-01-25 22:26:29 +00003362 typval_T var2;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003363 long result;
3364 int first;
3365
3366 /*
3367 * Get the first variable.
3368 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003369 if (eval4(arg, rettv, evaluate) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003370 return FAIL;
3371
3372 /*
3373 * Repeat until there is no following "&&".
3374 */
3375 first = TRUE;
3376 result = TRUE;
3377 while ((*arg)[0] == '&' && (*arg)[1] == '&')
3378 {
3379 if (evaluate && first)
3380 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003381 if (get_tv_number(rettv) == 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003382 result = FALSE;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003383 clear_tv(rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003384 first = FALSE;
3385 }
3386
3387 /*
3388 * Get the second variable.
3389 */
3390 *arg = skipwhite(*arg + 2);
3391 if (eval4(arg, &var2, evaluate && result) == FAIL)
3392 return FAIL;
3393
3394 /*
3395 * Compute the result.
3396 */
3397 if (evaluate && result)
3398 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003399 if (get_tv_number(&var2) == 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003400 result = FALSE;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003401 clear_tv(&var2);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003402 }
3403 if (evaluate)
3404 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003405 rettv->v_type = VAR_NUMBER;
3406 rettv->vval.v_number = result;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003407 }
3408 }
3409
3410 return OK;
3411}
3412
3413/*
3414 * Handle third level expression:
3415 * var1 == var2
3416 * var1 =~ var2
3417 * var1 != var2
3418 * var1 !~ var2
3419 * var1 > var2
3420 * var1 >= var2
3421 * var1 < var2
3422 * var1 <= var2
Bram Moolenaar8a283e52005-01-06 23:28:25 +00003423 * var1 is var2
3424 * var1 isnot var2
Bram Moolenaar071d4272004-06-13 20:20:40 +00003425 *
3426 * "arg" must point to the first non-white of the expression.
3427 * "arg" is advanced to the next non-white after the recognized expression.
3428 *
3429 * Return OK or FAIL.
3430 */
3431 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003432eval4(arg, rettv, evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003433 char_u **arg;
Bram Moolenaar33570922005-01-25 22:26:29 +00003434 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003435 int evaluate;
3436{
Bram Moolenaar33570922005-01-25 22:26:29 +00003437 typval_T var2;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003438 char_u *p;
3439 int i;
3440 exptype_T type = TYPE_UNKNOWN;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00003441 int type_is = FALSE; /* TRUE for "is" and "isnot" */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003442 int len = 2;
3443 long n1, n2;
3444 char_u *s1, *s2;
3445 char_u buf1[NUMBUFLEN], buf2[NUMBUFLEN];
3446 regmatch_T regmatch;
3447 int ic;
3448 char_u *save_cpo;
3449
3450 /*
3451 * Get the first variable.
3452 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003453 if (eval5(arg, rettv, evaluate) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003454 return FAIL;
3455
3456 p = *arg;
3457 switch (p[0])
3458 {
3459 case '=': if (p[1] == '=')
3460 type = TYPE_EQUAL;
3461 else if (p[1] == '~')
3462 type = TYPE_MATCH;
3463 break;
3464 case '!': if (p[1] == '=')
3465 type = TYPE_NEQUAL;
3466 else if (p[1] == '~')
3467 type = TYPE_NOMATCH;
3468 break;
3469 case '>': if (p[1] != '=')
3470 {
3471 type = TYPE_GREATER;
3472 len = 1;
3473 }
3474 else
3475 type = TYPE_GEQUAL;
3476 break;
3477 case '<': if (p[1] != '=')
3478 {
3479 type = TYPE_SMALLER;
3480 len = 1;
3481 }
3482 else
3483 type = TYPE_SEQUAL;
3484 break;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00003485 case 'i': if (p[1] == 's')
3486 {
3487 if (p[2] == 'n' && p[3] == 'o' && p[4] == 't')
3488 len = 5;
3489 if (!vim_isIDc(p[len]))
3490 {
3491 type = len == 2 ? TYPE_EQUAL : TYPE_NEQUAL;
3492 type_is = TRUE;
3493 }
3494 }
3495 break;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003496 }
3497
3498 /*
3499 * If there is a comparitive operator, use it.
3500 */
3501 if (type != TYPE_UNKNOWN)
3502 {
3503 /* extra question mark appended: ignore case */
3504 if (p[len] == '?')
3505 {
3506 ic = TRUE;
3507 ++len;
3508 }
3509 /* extra '#' appended: match case */
3510 else if (p[len] == '#')
3511 {
3512 ic = FALSE;
3513 ++len;
3514 }
3515 /* nothing appened: use 'ignorecase' */
3516 else
3517 ic = p_ic;
3518
3519 /*
3520 * Get the second variable.
3521 */
3522 *arg = skipwhite(p + len);
3523 if (eval5(arg, &var2, evaluate) == FAIL)
3524 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003525 clear_tv(rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003526 return FAIL;
3527 }
3528
3529 if (evaluate)
3530 {
Bram Moolenaar8a283e52005-01-06 23:28:25 +00003531 if (type_is && rettv->v_type != var2.v_type)
3532 {
3533 /* For "is" a different type always means FALSE, for "notis"
3534 * it means TRUE. */
3535 n1 = (type == TYPE_NEQUAL);
3536 }
3537 else if (rettv->v_type == VAR_LIST || var2.v_type == VAR_LIST)
3538 {
3539 if (type_is)
3540 {
3541 n1 = (rettv->v_type == var2.v_type
3542 && rettv->vval.v_list == var2.vval.v_list);
3543 if (type == TYPE_NEQUAL)
3544 n1 = !n1;
3545 }
3546 else if (rettv->v_type != var2.v_type
3547 || (type != TYPE_EQUAL && type != TYPE_NEQUAL))
3548 {
3549 if (rettv->v_type != var2.v_type)
Bram Moolenaare49b69a2005-01-08 16:11:57 +00003550 EMSG(_("E691: Can only compare List with List"));
Bram Moolenaar8a283e52005-01-06 23:28:25 +00003551 else
Bram Moolenaare49b69a2005-01-08 16:11:57 +00003552 EMSG(_("E692: Invalid operation for Lists"));
Bram Moolenaar8a283e52005-01-06 23:28:25 +00003553 clear_tv(rettv);
3554 clear_tv(&var2);
3555 return FAIL;
3556 }
3557 else
3558 {
3559 /* Compare two Lists for being equal or unequal. */
3560 n1 = list_equal(rettv->vval.v_list, var2.vval.v_list, ic);
3561 if (type == TYPE_NEQUAL)
3562 n1 = !n1;
3563 }
3564 }
3565
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00003566 else if (rettv->v_type == VAR_DICT || var2.v_type == VAR_DICT)
3567 {
3568 if (type_is)
3569 {
3570 n1 = (rettv->v_type == var2.v_type
3571 && rettv->vval.v_dict == var2.vval.v_dict);
3572 if (type == TYPE_NEQUAL)
3573 n1 = !n1;
3574 }
3575 else if (rettv->v_type != var2.v_type
3576 || (type != TYPE_EQUAL && type != TYPE_NEQUAL))
3577 {
3578 if (rettv->v_type != var2.v_type)
3579 EMSG(_("E735: Can only compare Dictionary with Dictionary"));
3580 else
3581 EMSG(_("E736: Invalid operation for Dictionary"));
3582 clear_tv(rettv);
3583 clear_tv(&var2);
3584 return FAIL;
3585 }
3586 else
3587 {
3588 /* Compare two Dictionaries for being equal or unequal. */
3589 n1 = dict_equal(rettv->vval.v_dict, var2.vval.v_dict, ic);
3590 if (type == TYPE_NEQUAL)
3591 n1 = !n1;
3592 }
3593 }
3594
Bram Moolenaar8a283e52005-01-06 23:28:25 +00003595 else if (rettv->v_type == VAR_FUNC || var2.v_type == VAR_FUNC)
3596 {
3597 if (rettv->v_type != var2.v_type
3598 || (type != TYPE_EQUAL && type != TYPE_NEQUAL))
3599 {
3600 if (rettv->v_type != var2.v_type)
Bram Moolenaare49b69a2005-01-08 16:11:57 +00003601 EMSG(_("E693: Can only compare Funcref with Funcref"));
Bram Moolenaar8a283e52005-01-06 23:28:25 +00003602 else
Bram Moolenaare49b69a2005-01-08 16:11:57 +00003603 EMSG(_("E694: Invalid operation for Funcrefs"));
Bram Moolenaar8a283e52005-01-06 23:28:25 +00003604 clear_tv(rettv);
3605 clear_tv(&var2);
3606 return FAIL;
3607 }
3608 else
3609 {
3610 /* Compare two Funcrefs for being equal or unequal. */
3611 if (rettv->vval.v_string == NULL
3612 || var2.vval.v_string == NULL)
3613 n1 = FALSE;
3614 else
3615 n1 = STRCMP(rettv->vval.v_string,
3616 var2.vval.v_string) == 0;
3617 if (type == TYPE_NEQUAL)
3618 n1 = !n1;
3619 }
3620 }
3621
Bram Moolenaar071d4272004-06-13 20:20:40 +00003622 /*
3623 * If one of the two variables is a number, compare as a number.
3624 * When using "=~" or "!~", always compare as string.
3625 */
Bram Moolenaar8a283e52005-01-06 23:28:25 +00003626 else if ((rettv->v_type == VAR_NUMBER || var2.v_type == VAR_NUMBER)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003627 && type != TYPE_MATCH && type != TYPE_NOMATCH)
3628 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003629 n1 = get_tv_number(rettv);
3630 n2 = get_tv_number(&var2);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003631 switch (type)
3632 {
3633 case TYPE_EQUAL: n1 = (n1 == n2); break;
3634 case TYPE_NEQUAL: n1 = (n1 != n2); break;
3635 case TYPE_GREATER: n1 = (n1 > n2); break;
3636 case TYPE_GEQUAL: n1 = (n1 >= n2); break;
3637 case TYPE_SMALLER: n1 = (n1 < n2); break;
3638 case TYPE_SEQUAL: n1 = (n1 <= n2); break;
3639 case TYPE_UNKNOWN:
3640 case TYPE_MATCH:
3641 case TYPE_NOMATCH: break; /* avoid gcc warning */
3642 }
3643 }
3644 else
3645 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003646 s1 = get_tv_string_buf(rettv, buf1);
3647 s2 = get_tv_string_buf(&var2, buf2);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003648 if (type != TYPE_MATCH && type != TYPE_NOMATCH)
3649 i = ic ? MB_STRICMP(s1, s2) : STRCMP(s1, s2);
3650 else
3651 i = 0;
3652 n1 = FALSE;
3653 switch (type)
3654 {
3655 case TYPE_EQUAL: n1 = (i == 0); break;
3656 case TYPE_NEQUAL: n1 = (i != 0); break;
3657 case TYPE_GREATER: n1 = (i > 0); break;
3658 case TYPE_GEQUAL: n1 = (i >= 0); break;
3659 case TYPE_SMALLER: n1 = (i < 0); break;
3660 case TYPE_SEQUAL: n1 = (i <= 0); break;
3661
3662 case TYPE_MATCH:
3663 case TYPE_NOMATCH:
3664 /* avoid 'l' flag in 'cpoptions' */
3665 save_cpo = p_cpo;
3666 p_cpo = (char_u *)"";
3667 regmatch.regprog = vim_regcomp(s2,
3668 RE_MAGIC + RE_STRING);
3669 regmatch.rm_ic = ic;
3670 if (regmatch.regprog != NULL)
3671 {
3672 n1 = vim_regexec_nl(&regmatch, s1, (colnr_T)0);
3673 vim_free(regmatch.regprog);
3674 if (type == TYPE_NOMATCH)
3675 n1 = !n1;
3676 }
3677 p_cpo = save_cpo;
3678 break;
3679
3680 case TYPE_UNKNOWN: break; /* avoid gcc warning */
3681 }
3682 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003683 clear_tv(rettv);
3684 clear_tv(&var2);
3685 rettv->v_type = VAR_NUMBER;
3686 rettv->vval.v_number = n1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003687 }
3688 }
3689
3690 return OK;
3691}
3692
3693/*
3694 * Handle fourth level expression:
3695 * + number addition
3696 * - number subtraction
3697 * . string concatenation
3698 *
3699 * "arg" must point to the first non-white of the expression.
3700 * "arg" is advanced to the next non-white after the recognized expression.
3701 *
3702 * Return OK or FAIL.
3703 */
3704 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003705eval5(arg, rettv, evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003706 char_u **arg;
Bram Moolenaar33570922005-01-25 22:26:29 +00003707 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003708 int evaluate;
3709{
Bram Moolenaar33570922005-01-25 22:26:29 +00003710 typval_T var2;
3711 typval_T var3;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003712 int op;
3713 long n1, n2;
3714 char_u *s1, *s2;
3715 char_u buf1[NUMBUFLEN], buf2[NUMBUFLEN];
3716 char_u *p;
3717
3718 /*
3719 * Get the first variable.
3720 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003721 if (eval6(arg, rettv, evaluate) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003722 return FAIL;
3723
3724 /*
3725 * Repeat computing, until no '+', '-' or '.' is following.
3726 */
3727 for (;;)
3728 {
3729 op = **arg;
3730 if (op != '+' && op != '-' && op != '.')
3731 break;
3732
3733 /*
3734 * Get the second variable.
3735 */
3736 *arg = skipwhite(*arg + 1);
3737 if (eval6(arg, &var2, evaluate) == FAIL)
3738 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003739 clear_tv(rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003740 return FAIL;
3741 }
3742
3743 if (evaluate)
3744 {
3745 /*
3746 * Compute the result.
3747 */
3748 if (op == '.')
3749 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003750 s1 = get_tv_string_buf(rettv, buf1);
3751 s2 = get_tv_string_buf(&var2, buf2);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00003752 p = concat_str(s1, s2);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003753 clear_tv(rettv);
3754 rettv->v_type = VAR_STRING;
3755 rettv->vval.v_string = p;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003756 }
Bram Moolenaare9a41262005-01-15 22:18:47 +00003757 else if (op == '+' && rettv->v_type == VAR_LIST
3758 && var2.v_type == VAR_LIST)
Bram Moolenaar8a283e52005-01-06 23:28:25 +00003759 {
3760 /* concatenate Lists */
3761 if (list_concat(rettv->vval.v_list, var2.vval.v_list,
3762 &var3) == FAIL)
3763 {
3764 clear_tv(rettv);
3765 clear_tv(&var2);
3766 return FAIL;
3767 }
3768 clear_tv(rettv);
3769 *rettv = var3;
3770 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00003771 else
3772 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003773 n1 = get_tv_number(rettv);
3774 n2 = get_tv_number(&var2);
3775 clear_tv(rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003776 if (op == '+')
3777 n1 = n1 + n2;
3778 else
3779 n1 = n1 - n2;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003780 rettv->v_type = VAR_NUMBER;
3781 rettv->vval.v_number = n1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003782 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003783 clear_tv(&var2);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003784 }
3785 }
3786 return OK;
3787}
3788
3789/*
3790 * Handle fifth level expression:
3791 * * number multiplication
3792 * / number division
3793 * % number modulo
3794 *
3795 * "arg" must point to the first non-white of the expression.
3796 * "arg" is advanced to the next non-white after the recognized expression.
3797 *
3798 * Return OK or FAIL.
3799 */
3800 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003801eval6(arg, rettv, evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003802 char_u **arg;
Bram Moolenaar33570922005-01-25 22:26:29 +00003803 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003804 int evaluate;
3805{
Bram Moolenaar33570922005-01-25 22:26:29 +00003806 typval_T var2;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003807 int op;
3808 long n1, n2;
3809
3810 /*
3811 * Get the first variable.
3812 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003813 if (eval7(arg, rettv, evaluate) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003814 return FAIL;
3815
3816 /*
3817 * Repeat computing, until no '*', '/' or '%' is following.
3818 */
3819 for (;;)
3820 {
3821 op = **arg;
3822 if (op != '*' && op != '/' && op != '%')
3823 break;
3824
3825 if (evaluate)
3826 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003827 n1 = get_tv_number(rettv);
3828 clear_tv(rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003829 }
3830 else
3831 n1 = 0;
3832
3833 /*
3834 * Get the second variable.
3835 */
3836 *arg = skipwhite(*arg + 1);
3837 if (eval7(arg, &var2, evaluate) == FAIL)
3838 return FAIL;
3839
3840 if (evaluate)
3841 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003842 n2 = get_tv_number(&var2);
3843 clear_tv(&var2);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003844
3845 /*
3846 * Compute the result.
3847 */
3848 if (op == '*')
3849 n1 = n1 * n2;
3850 else if (op == '/')
3851 {
3852 if (n2 == 0) /* give an error message? */
3853 n1 = 0x7fffffffL;
3854 else
3855 n1 = n1 / n2;
3856 }
3857 else
3858 {
3859 if (n2 == 0) /* give an error message? */
3860 n1 = 0;
3861 else
3862 n1 = n1 % n2;
3863 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003864 rettv->v_type = VAR_NUMBER;
3865 rettv->vval.v_number = n1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003866 }
3867 }
3868
3869 return OK;
3870}
3871
3872/*
3873 * Handle sixth level expression:
3874 * number number constant
3875 * "string" string contstant
3876 * 'string' literal string contstant
3877 * &option-name option value
3878 * @r register contents
3879 * identifier variable value
3880 * function() function call
3881 * $VAR environment variable
3882 * (expression) nested expression
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00003883 * [expr, expr] List
3884 * {key: val, key: val} Dictionary
Bram Moolenaar071d4272004-06-13 20:20:40 +00003885 *
3886 * Also handle:
3887 * ! in front logical NOT
3888 * - in front unary minus
3889 * + in front unary plus (ignored)
Bram Moolenaar8c711452005-01-14 21:53:12 +00003890 * trailing [] subscript in String or List
3891 * trailing .name entry in Dictionary
Bram Moolenaar071d4272004-06-13 20:20:40 +00003892 *
3893 * "arg" must point to the first non-white of the expression.
3894 * "arg" is advanced to the next non-white after the recognized expression.
3895 *
3896 * Return OK or FAIL.
3897 */
3898 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003899eval7(arg, rettv, evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003900 char_u **arg;
Bram Moolenaar33570922005-01-25 22:26:29 +00003901 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003902 int evaluate;
3903{
Bram Moolenaar071d4272004-06-13 20:20:40 +00003904 long n;
3905 int len;
3906 char_u *s;
3907 int val;
3908 char_u *start_leader, *end_leader;
3909 int ret = OK;
3910 char_u *alias;
3911
3912 /*
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003913 * Initialise variable so that clear_tv() can't mistake this for a
Bram Moolenaar49cd9572005-01-03 21:06:01 +00003914 * string and free a string that isn't there.
Bram Moolenaar071d4272004-06-13 20:20:40 +00003915 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003916 rettv->v_type = VAR_UNKNOWN;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003917
3918 /*
3919 * Skip '!' and '-' characters. They are handled later.
3920 */
3921 start_leader = *arg;
3922 while (**arg == '!' || **arg == '-' || **arg == '+')
3923 *arg = skipwhite(*arg + 1);
3924 end_leader = *arg;
3925
3926 switch (**arg)
3927 {
3928 /*
3929 * Number constant.
3930 */
3931 case '0':
3932 case '1':
3933 case '2':
3934 case '3':
3935 case '4':
3936 case '5':
3937 case '6':
3938 case '7':
3939 case '8':
3940 case '9':
3941 vim_str2nr(*arg, NULL, &len, TRUE, TRUE, &n, NULL);
3942 *arg += len;
3943 if (evaluate)
3944 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003945 rettv->v_type = VAR_NUMBER;
3946 rettv->vval.v_number = n;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003947 }
3948 break;
3949
3950 /*
3951 * String constant: "string".
3952 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003953 case '"': ret = get_string_tv(arg, rettv, evaluate);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003954 break;
3955
3956 /*
Bram Moolenaar8c711452005-01-14 21:53:12 +00003957 * Literal string constant: 'str''ing'.
Bram Moolenaar071d4272004-06-13 20:20:40 +00003958 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003959 case '\'': ret = get_lit_string_tv(arg, rettv, evaluate);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00003960 break;
3961
3962 /*
3963 * List: [expr, expr]
3964 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003965 case '[': ret = get_list_tv(arg, rettv, evaluate);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003966 break;
3967
3968 /*
Bram Moolenaar8c711452005-01-14 21:53:12 +00003969 * Dictionary: {key: val, key: val}
3970 */
3971 case '{': ret = get_dict_tv(arg, rettv, evaluate);
3972 break;
3973
3974 /*
Bram Moolenaare9a41262005-01-15 22:18:47 +00003975 * Option value: &name
Bram Moolenaar071d4272004-06-13 20:20:40 +00003976 */
Bram Moolenaare9a41262005-01-15 22:18:47 +00003977 case '&': ret = get_option_tv(arg, rettv, evaluate);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003978 break;
3979
3980 /*
3981 * Environment variable: $VAR.
3982 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003983 case '$': ret = get_env_tv(arg, rettv, evaluate);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003984 break;
3985
3986 /*
3987 * Register contents: @r.
3988 */
3989 case '@': ++*arg;
3990 if (evaluate)
3991 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00003992 rettv->v_type = VAR_STRING;
3993 rettv->vval.v_string = get_reg_contents(**arg, FALSE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003994 }
3995 if (**arg != NUL)
3996 ++*arg;
3997 break;
3998
3999 /*
4000 * nested expression: (expression).
4001 */
4002 case '(': *arg = skipwhite(*arg + 1);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004003 ret = eval1(arg, rettv, evaluate); /* recursive! */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004004 if (**arg == ')')
4005 ++*arg;
4006 else if (ret == OK)
4007 {
4008 EMSG(_("E110: Missing ')'"));
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004009 clear_tv(rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004010 ret = FAIL;
4011 }
4012 break;
4013
Bram Moolenaar8c711452005-01-14 21:53:12 +00004014 default: ret = NOTDONE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004015 break;
4016 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00004017
4018 if (ret == NOTDONE)
4019 {
4020 /*
4021 * Must be a variable or function name.
4022 * Can also be a curly-braces kind of name: {expr}.
4023 */
4024 s = *arg;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00004025 len = get_name_len(arg, &alias, evaluate, TRUE);
Bram Moolenaar8c711452005-01-14 21:53:12 +00004026 if (alias != NULL)
4027 s = alias;
4028
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00004029 if (len <= 0)
Bram Moolenaar8c711452005-01-14 21:53:12 +00004030 ret = FAIL;
4031 else
4032 {
4033 if (**arg == '(') /* recursive! */
4034 {
4035 /* If "s" is the name of a variable of type VAR_FUNC
4036 * use its contents. */
4037 s = deref_func_name(s, &len);
4038
4039 /* Invoke the function. */
4040 ret = get_func_tv(s, len, rettv, arg,
4041 curwin->w_cursor.lnum, curwin->w_cursor.lnum,
Bram Moolenaare9a41262005-01-15 22:18:47 +00004042 &len, evaluate, NULL);
Bram Moolenaar8c711452005-01-14 21:53:12 +00004043 /* Stop the expression evaluation when immediately
4044 * aborting on error, or when an interrupt occurred or
4045 * an exception was thrown but not caught. */
4046 if (aborting())
4047 {
4048 if (ret == OK)
4049 clear_tv(rettv);
4050 ret = FAIL;
4051 }
4052 }
4053 else if (evaluate)
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00004054 ret = get_var_tv(s, len, rettv, TRUE);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00004055 else
4056 ret = OK;
Bram Moolenaar8c711452005-01-14 21:53:12 +00004057 }
4058
4059 if (alias != NULL)
4060 vim_free(alias);
4061 }
4062
Bram Moolenaar071d4272004-06-13 20:20:40 +00004063 *arg = skipwhite(*arg);
4064
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00004065 /* Handle following '[', '(' and '.' for expr[expr], expr.name,
4066 * expr(expr). */
4067 if (ret == OK)
4068 ret = handle_subscript(arg, rettv, evaluate, TRUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004069
4070 /*
4071 * Apply logical NOT and unary '-', from right to left, ignore '+'.
4072 */
4073 if (ret == OK && evaluate && end_leader > start_leader)
4074 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004075 val = get_tv_number(rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004076 while (end_leader > start_leader)
4077 {
4078 --end_leader;
4079 if (*end_leader == '!')
4080 val = !val;
4081 else if (*end_leader == '-')
4082 val = -val;
4083 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004084 clear_tv(rettv);
4085 rettv->v_type = VAR_NUMBER;
4086 rettv->vval.v_number = val;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004087 }
4088
4089 return ret;
4090}
4091
4092/*
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004093 * Evaluate an "[expr]" or "[expr:expr]" index.
4094 * "*arg" points to the '['.
4095 * Returns FAIL or OK. "*arg" is advanced to after the ']'.
4096 */
4097 static int
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00004098eval_index(arg, rettv, evaluate, verbose)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004099 char_u **arg;
Bram Moolenaar33570922005-01-25 22:26:29 +00004100 typval_T *rettv;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004101 int evaluate;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00004102 int verbose; /* give error messages */
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004103{
4104 int empty1 = FALSE, empty2 = FALSE;
Bram Moolenaar33570922005-01-25 22:26:29 +00004105 typval_T var1, var2;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004106 long n1, n2 = 0;
Bram Moolenaar8c711452005-01-14 21:53:12 +00004107 long len = -1;
4108 int range = FALSE;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004109 char_u *s;
Bram Moolenaar8c711452005-01-14 21:53:12 +00004110 char_u *key = NULL;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004111
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004112 if (rettv->v_type == VAR_FUNC)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004113 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00004114 if (verbose)
4115 EMSG(_("E695: Cannot index a Funcref"));
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004116 return FAIL;
4117 }
4118
Bram Moolenaar8c711452005-01-14 21:53:12 +00004119 if (**arg == '.')
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004120 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00004121 /*
4122 * dict.name
4123 */
4124 key = *arg + 1;
4125 for (len = 0; ASCII_ISALNUM(key[len]) || key[len] == '_'; ++len)
4126 ;
4127 if (len == 0)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004128 return FAIL;
Bram Moolenaar8c711452005-01-14 21:53:12 +00004129 *arg = skipwhite(key + len);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004130 }
4131 else
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004132 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00004133 /*
4134 * something[idx]
4135 *
4136 * Get the (first) variable from inside the [].
4137 */
4138 *arg = skipwhite(*arg + 1);
4139 if (**arg == ':')
4140 empty1 = TRUE;
4141 else if (eval1(arg, &var1, evaluate) == FAIL) /* recursive! */
4142 return FAIL;
4143
4144 /*
4145 * Get the second variable from inside the [:].
4146 */
4147 if (**arg == ':')
4148 {
4149 range = TRUE;
4150 *arg = skipwhite(*arg + 1);
4151 if (**arg == ']')
4152 empty2 = TRUE;
4153 else if (eval1(arg, &var2, evaluate) == FAIL) /* recursive! */
4154 {
4155 clear_tv(&var1);
4156 return FAIL;
4157 }
4158 }
4159
4160 /* Check for the ']'. */
4161 if (**arg != ']')
4162 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00004163 if (verbose)
4164 EMSG(_(e_missbrac));
Bram Moolenaar8c711452005-01-14 21:53:12 +00004165 clear_tv(&var1);
4166 if (range)
4167 clear_tv(&var2);
4168 return FAIL;
4169 }
4170 *arg = skipwhite(*arg + 1); /* skip the ']' */
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004171 }
4172
4173 if (evaluate)
4174 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00004175 n1 = 0;
4176 if (!empty1 && rettv->v_type != VAR_DICT)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004177 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004178 n1 = get_tv_number(&var1);
4179 clear_tv(&var1);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004180 }
4181 if (range)
4182 {
4183 if (empty2)
4184 n2 = -1;
4185 else
4186 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004187 n2 = get_tv_number(&var2);
4188 clear_tv(&var2);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004189 }
4190 }
4191
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004192 switch (rettv->v_type)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004193 {
4194 case VAR_NUMBER:
4195 case VAR_STRING:
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004196 s = get_tv_string(rettv);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004197 len = (long)STRLEN(s);
4198 if (range)
4199 {
4200 /* The resulting variable is a substring. If the indexes
4201 * are out of range the result is empty. */
4202 if (n1 < 0)
4203 {
4204 n1 = len + n1;
4205 if (n1 < 0)
4206 n1 = 0;
4207 }
4208 if (n2 < 0)
4209 n2 = len + n2;
4210 else if (n2 >= len)
4211 n2 = len;
4212 if (n1 >= len || n2 < 0 || n1 > n2)
4213 s = NULL;
4214 else
4215 s = vim_strnsave(s + n1, (int)(n2 - n1 + 1));
4216 }
4217 else
4218 {
4219 /* The resulting variable is a string of a single
4220 * character. If the index is too big or negative the
4221 * result is empty. */
4222 if (n1 >= len || n1 < 0)
4223 s = NULL;
4224 else
4225 s = vim_strnsave(s + n1, 1);
4226 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004227 clear_tv(rettv);
4228 rettv->v_type = VAR_STRING;
4229 rettv->vval.v_string = s;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004230 break;
4231
4232 case VAR_LIST:
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004233 len = list_len(rettv->vval.v_list);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004234 if (n1 < 0)
4235 n1 = len + n1;
4236 if (!empty1 && (n1 < 0 || n1 >= len))
4237 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00004238 if (verbose)
4239 EMSGN(_(e_listidx), n1);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004240 return FAIL;
4241 }
4242 if (range)
4243 {
Bram Moolenaar33570922005-01-25 22:26:29 +00004244 list_T *l;
4245 listitem_T *item;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004246
4247 if (n2 < 0)
4248 n2 = len + n2;
Bram Moolenaar8c711452005-01-14 21:53:12 +00004249 if (!empty2 && (n2 < 0 || n2 >= len || n2 + 1 < n1))
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004250 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00004251 if (verbose)
4252 EMSGN(_(e_listidx), n2);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004253 return FAIL;
4254 }
4255 l = list_alloc();
4256 if (l == NULL)
4257 return FAIL;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004258 for (item = list_find(rettv->vval.v_list, n1);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004259 n1 <= n2; ++n1)
4260 {
4261 if (list_append_tv(l, &item->li_tv) == FAIL)
4262 {
4263 list_free(l);
4264 return FAIL;
4265 }
4266 item = item->li_next;
4267 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004268 clear_tv(rettv);
4269 rettv->v_type = VAR_LIST;
4270 rettv->vval.v_list = l;
Bram Moolenaar0d660222005-01-07 21:51:51 +00004271 ++l->lv_refcount;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004272 }
4273 else
4274 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004275 copy_tv(&list_find(rettv->vval.v_list, n1)->li_tv,
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004276 &var1);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004277 clear_tv(rettv);
4278 *rettv = var1;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004279 }
4280 break;
Bram Moolenaar8c711452005-01-14 21:53:12 +00004281
4282 case VAR_DICT:
4283 if (range)
4284 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00004285 if (verbose)
4286 EMSG(_(e_dictrange));
Bram Moolenaar8c711452005-01-14 21:53:12 +00004287 if (len == -1)
4288 clear_tv(&var1);
4289 return FAIL;
4290 }
4291 {
Bram Moolenaar33570922005-01-25 22:26:29 +00004292 dictitem_T *item;
Bram Moolenaar8c711452005-01-14 21:53:12 +00004293
4294 if (len == -1)
4295 {
4296 key = get_tv_string(&var1);
4297 if (*key == NUL)
4298 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00004299 if (verbose)
4300 EMSG(_(e_emptykey));
Bram Moolenaar8c711452005-01-14 21:53:12 +00004301 clear_tv(&var1);
4302 return FAIL;
4303 }
4304 }
4305
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00004306 item = dict_find(rettv->vval.v_dict, key, (int)len);
Bram Moolenaar8c711452005-01-14 21:53:12 +00004307
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00004308 if (item == NULL && verbose)
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00004309 EMSG2(_(e_dictkey), key);
Bram Moolenaar8c711452005-01-14 21:53:12 +00004310 if (len == -1)
4311 clear_tv(&var1);
4312 if (item == NULL)
4313 return FAIL;
4314
4315 copy_tv(&item->di_tv, &var1);
4316 clear_tv(rettv);
4317 *rettv = var1;
4318 }
4319 break;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004320 }
4321 }
4322
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004323 return OK;
4324}
4325
4326/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00004327 * Get an option value.
4328 * "arg" points to the '&' or '+' before the option name.
4329 * "arg" is advanced to character after the option name.
4330 * Return OK or FAIL.
4331 */
4332 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004333get_option_tv(arg, rettv, evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004334 char_u **arg;
Bram Moolenaar33570922005-01-25 22:26:29 +00004335 typval_T *rettv; /* when NULL, only check if option exists */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004336 int evaluate;
4337{
4338 char_u *option_end;
4339 long numval;
4340 char_u *stringval;
4341 int opt_type;
4342 int c;
4343 int working = (**arg == '+'); /* has("+option") */
4344 int ret = OK;
4345 int opt_flags;
4346
4347 /*
4348 * Isolate the option name and find its value.
4349 */
4350 option_end = find_option_end(arg, &opt_flags);
4351 if (option_end == NULL)
4352 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004353 if (rettv != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004354 EMSG2(_("E112: Option name missing: %s"), *arg);
4355 return FAIL;
4356 }
4357
4358 if (!evaluate)
4359 {
4360 *arg = option_end;
4361 return OK;
4362 }
4363
4364 c = *option_end;
4365 *option_end = NUL;
4366 opt_type = get_option_value(*arg, &numval,
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004367 rettv == NULL ? NULL : &stringval, opt_flags);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004368
4369 if (opt_type == -3) /* invalid name */
4370 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004371 if (rettv != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004372 EMSG2(_("E113: Unknown option: %s"), *arg);
4373 ret = FAIL;
4374 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004375 else if (rettv != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004376 {
4377 if (opt_type == -2) /* hidden string option */
4378 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004379 rettv->v_type = VAR_STRING;
4380 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004381 }
4382 else if (opt_type == -1) /* hidden number option */
4383 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004384 rettv->v_type = VAR_NUMBER;
4385 rettv->vval.v_number = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004386 }
4387 else if (opt_type == 1) /* number option */
4388 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004389 rettv->v_type = VAR_NUMBER;
4390 rettv->vval.v_number = numval;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004391 }
4392 else /* string option */
4393 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004394 rettv->v_type = VAR_STRING;
4395 rettv->vval.v_string = stringval;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004396 }
4397 }
4398 else if (working && (opt_type == -2 || opt_type == -1))
4399 ret = FAIL;
4400
4401 *option_end = c; /* put back for error messages */
4402 *arg = option_end;
4403
4404 return ret;
4405}
4406
4407/*
4408 * Allocate a variable for a string constant.
4409 * Return OK or FAIL.
4410 */
4411 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004412get_string_tv(arg, rettv, evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004413 char_u **arg;
Bram Moolenaar33570922005-01-25 22:26:29 +00004414 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004415 int evaluate;
4416{
4417 char_u *p;
4418 char_u *name;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004419 int extra = 0;
4420
4421 /*
4422 * Find the end of the string, skipping backslashed characters.
4423 */
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00004424 for (p = *arg + 1; *p != NUL && *p != '"'; mb_ptr_adv(p))
Bram Moolenaar071d4272004-06-13 20:20:40 +00004425 {
4426 if (*p == '\\' && p[1] != NUL)
4427 {
4428 ++p;
4429 /* A "\<x>" form occupies at least 4 characters, and produces up
4430 * to 6 characters: reserve space for 2 extra */
4431 if (*p == '<')
4432 extra += 2;
4433 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004434 }
4435
4436 if (*p != '"')
4437 {
4438 EMSG2(_("E114: Missing quote: %s"), *arg);
4439 return FAIL;
4440 }
4441
4442 /* If only parsing, set *arg and return here */
4443 if (!evaluate)
4444 {
4445 *arg = p + 1;
4446 return OK;
4447 }
4448
4449 /*
4450 * Copy the string into allocated memory, handling backslashed
4451 * characters.
4452 */
4453 name = alloc((unsigned)(p - *arg + extra));
4454 if (name == NULL)
4455 return FAIL;
Bram Moolenaar8c711452005-01-14 21:53:12 +00004456 rettv->v_type = VAR_STRING;
4457 rettv->vval.v_string = name;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004458
Bram Moolenaar8c711452005-01-14 21:53:12 +00004459 for (p = *arg + 1; *p != NUL && *p != '"'; )
Bram Moolenaar071d4272004-06-13 20:20:40 +00004460 {
4461 if (*p == '\\')
4462 {
4463 switch (*++p)
4464 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00004465 case 'b': *name++ = BS; ++p; break;
4466 case 'e': *name++ = ESC; ++p; break;
4467 case 'f': *name++ = FF; ++p; break;
4468 case 'n': *name++ = NL; ++p; break;
4469 case 'r': *name++ = CAR; ++p; break;
4470 case 't': *name++ = TAB; ++p; break;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004471
4472 case 'X': /* hex: "\x1", "\x12" */
4473 case 'x':
4474 case 'u': /* Unicode: "\u0023" */
4475 case 'U':
4476 if (vim_isxdigit(p[1]))
4477 {
4478 int n, nr;
4479 int c = toupper(*p);
4480
4481 if (c == 'X')
4482 n = 2;
4483 else
4484 n = 4;
4485 nr = 0;
4486 while (--n >= 0 && vim_isxdigit(p[1]))
4487 {
4488 ++p;
4489 nr = (nr << 4) + hex2nr(*p);
4490 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00004491 ++p;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004492#ifdef FEAT_MBYTE
4493 /* For "\u" store the number according to
4494 * 'encoding'. */
4495 if (c != 'X')
Bram Moolenaar8c711452005-01-14 21:53:12 +00004496 name += (*mb_char2bytes)(nr, name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004497 else
4498#endif
Bram Moolenaar8c711452005-01-14 21:53:12 +00004499 *name++ = nr;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004500 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004501 break;
4502
4503 /* octal: "\1", "\12", "\123" */
4504 case '0':
4505 case '1':
4506 case '2':
4507 case '3':
4508 case '4':
4509 case '5':
4510 case '6':
Bram Moolenaar8c711452005-01-14 21:53:12 +00004511 case '7': *name = *p++ - '0';
4512 if (*p >= '0' && *p <= '7')
Bram Moolenaar071d4272004-06-13 20:20:40 +00004513 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00004514 *name = (*name << 3) + *p++ - '0';
4515 if (*p >= '0' && *p <= '7')
4516 *name = (*name << 3) + *p++ - '0';
Bram Moolenaar071d4272004-06-13 20:20:40 +00004517 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00004518 ++name;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004519 break;
4520
4521 /* Special key, e.g.: "\<C-W>" */
Bram Moolenaar8c711452005-01-14 21:53:12 +00004522 case '<': extra = trans_special(&p, name, TRUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004523 if (extra != 0)
4524 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00004525 name += extra;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004526 break;
4527 }
4528 /* FALLTHROUGH */
4529
Bram Moolenaar8c711452005-01-14 21:53:12 +00004530 default: MB_COPY_CHAR(p, name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004531 break;
4532 }
4533 }
4534 else
Bram Moolenaar8c711452005-01-14 21:53:12 +00004535 MB_COPY_CHAR(p, name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004536
Bram Moolenaar071d4272004-06-13 20:20:40 +00004537 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00004538 *name = NUL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004539 *arg = p + 1;
4540
Bram Moolenaar071d4272004-06-13 20:20:40 +00004541 return OK;
4542}
4543
4544/*
Bram Moolenaar8c711452005-01-14 21:53:12 +00004545 * Allocate a variable for a 'str''ing' constant.
Bram Moolenaar071d4272004-06-13 20:20:40 +00004546 * Return OK or FAIL.
4547 */
4548 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004549get_lit_string_tv(arg, rettv, evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004550 char_u **arg;
Bram Moolenaar33570922005-01-25 22:26:29 +00004551 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004552 int evaluate;
4553{
4554 char_u *p;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00004555 char_u *str;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00004556 int reduce = 0;
4557
4558 /*
Bram Moolenaar8c711452005-01-14 21:53:12 +00004559 * Find the end of the string, skipping ''.
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00004560 */
4561 for (p = *arg + 1; *p != NUL; mb_ptr_adv(p))
4562 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00004563 if (*p == '\'')
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00004564 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00004565 if (p[1] != '\'')
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00004566 break;
4567 ++reduce;
4568 ++p;
4569 }
4570 }
4571
Bram Moolenaar8c711452005-01-14 21:53:12 +00004572 if (*p != '\'')
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00004573 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00004574 EMSG2(_("E115: Missing quote: %s"), *arg);
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00004575 return FAIL;
4576 }
4577
Bram Moolenaar8c711452005-01-14 21:53:12 +00004578 /* If only parsing return after setting "*arg" */
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00004579 if (!evaluate)
4580 {
4581 *arg = p + 1;
4582 return OK;
4583 }
4584
4585 /*
Bram Moolenaar8c711452005-01-14 21:53:12 +00004586 * Copy the string into allocated memory, handling '' to ' reduction.
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00004587 */
4588 str = alloc((unsigned)((p - *arg) - reduce));
4589 if (str == NULL)
4590 return FAIL;
Bram Moolenaar8c711452005-01-14 21:53:12 +00004591 rettv->v_type = VAR_STRING;
4592 rettv->vval.v_string = str;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00004593
Bram Moolenaar8c711452005-01-14 21:53:12 +00004594 for (p = *arg + 1; *p != NUL; )
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00004595 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00004596 if (*p == '\'')
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00004597 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00004598 if (p[1] != '\'')
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00004599 break;
4600 ++p;
4601 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00004602 MB_COPY_CHAR(p, str);
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00004603 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00004604 *str = NUL;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00004605 *arg = p + 1;
4606
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00004607 return OK;
4608}
4609
4610/*
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004611 * Allocate a variable for a List and fill it from "*arg".
4612 * Return OK or FAIL.
4613 */
4614 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004615get_list_tv(arg, rettv, evaluate)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004616 char_u **arg;
Bram Moolenaar33570922005-01-25 22:26:29 +00004617 typval_T *rettv;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004618 int evaluate;
4619{
Bram Moolenaar33570922005-01-25 22:26:29 +00004620 list_T *l = NULL;
4621 typval_T tv;
4622 listitem_T *item;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004623
4624 if (evaluate)
4625 {
4626 l = list_alloc();
4627 if (l == NULL)
4628 return FAIL;
4629 }
4630
4631 *arg = skipwhite(*arg + 1);
4632 while (**arg != ']' && **arg != NUL)
4633 {
4634 if (eval1(arg, &tv, evaluate) == FAIL) /* recursive! */
4635 goto failret;
4636 if (evaluate)
4637 {
4638 item = listitem_alloc();
4639 if (item != NULL)
4640 {
4641 item->li_tv = tv;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00004642 item->li_tv.v_lock = 0;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004643 list_append(l, item);
4644 }
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00004645 else
4646 clear_tv(&tv);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004647 }
4648
4649 if (**arg == ']')
4650 break;
4651 if (**arg != ',')
4652 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00004653 EMSG2(_("E696: Missing comma in List: %s"), *arg);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004654 goto failret;
4655 }
4656 *arg = skipwhite(*arg + 1);
4657 }
4658
4659 if (**arg != ']')
4660 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00004661 EMSG2(_("E697: Missing end of List ']': %s"), *arg);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004662failret:
4663 if (evaluate)
4664 list_free(l);
4665 return FAIL;
4666 }
4667
4668 *arg = skipwhite(*arg + 1);
4669 if (evaluate)
4670 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004671 rettv->v_type = VAR_LIST;
4672 rettv->vval.v_list = l;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004673 ++l->lv_refcount;
4674 }
4675
4676 return OK;
4677}
4678
4679/*
4680 * Allocate an empty header for a list.
4681 */
Bram Moolenaar33570922005-01-25 22:26:29 +00004682 static list_T *
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004683list_alloc()
4684{
Bram Moolenaar33570922005-01-25 22:26:29 +00004685 return (list_T *)alloc_clear(sizeof(list_T));
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004686}
4687
4688/*
4689 * Unreference a list: decrement the reference count and free it when it
4690 * becomes zero.
4691 */
4692 static void
4693list_unref(l)
Bram Moolenaar33570922005-01-25 22:26:29 +00004694 list_T *l;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004695{
4696 if (l != NULL && --l->lv_refcount <= 0)
4697 list_free(l);
4698}
4699
4700/*
4701 * Free a list, including all items it points to.
4702 * Ignores the reference count.
4703 */
4704 static void
4705list_free(l)
Bram Moolenaar33570922005-01-25 22:26:29 +00004706 list_T *l;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004707{
Bram Moolenaar33570922005-01-25 22:26:29 +00004708 listitem_T *item;
4709 listitem_T *next;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004710
4711 for (item = l->lv_first; item != NULL; item = next)
4712 {
4713 next = item->li_next;
4714 listitem_free(item);
4715 }
4716 vim_free(l);
4717}
4718
4719/*
4720 * Allocate a list item.
4721 */
Bram Moolenaar33570922005-01-25 22:26:29 +00004722 static listitem_T *
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004723listitem_alloc()
4724{
Bram Moolenaar33570922005-01-25 22:26:29 +00004725 return (listitem_T *)alloc(sizeof(listitem_T));
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004726}
4727
4728/*
Bram Moolenaar3d60ec22005-01-05 22:19:46 +00004729 * Free a list item. Also clears the value. Does not notify watchers.
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004730 */
4731 static void
4732listitem_free(item)
Bram Moolenaar33570922005-01-25 22:26:29 +00004733 listitem_T *item;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004734{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00004735 clear_tv(&item->li_tv);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004736 vim_free(item);
4737}
4738
4739/*
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00004740 * Remove a list item from a List and free it. Also clears the value.
4741 */
4742 static void
4743listitem_remove(l, item)
Bram Moolenaar33570922005-01-25 22:26:29 +00004744 list_T *l;
4745 listitem_T *item;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00004746{
4747 list_remove(l, item, item);
4748 listitem_free(item);
4749}
4750
4751/*
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004752 * Get the number of items in a list.
4753 */
4754 static long
4755list_len(l)
Bram Moolenaar33570922005-01-25 22:26:29 +00004756 list_T *l;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004757{
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004758 if (l == NULL)
4759 return 0L;
Bram Moolenaar758711c2005-02-02 23:11:38 +00004760 return l->lv_len;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004761}
4762
4763/*
Bram Moolenaar8a283e52005-01-06 23:28:25 +00004764 * Return TRUE when two lists have exactly the same values.
4765 */
4766 static int
4767list_equal(l1, l2, ic)
Bram Moolenaar33570922005-01-25 22:26:29 +00004768 list_T *l1;
4769 list_T *l2;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00004770 int ic; /* ignore case for strings */
4771{
Bram Moolenaar33570922005-01-25 22:26:29 +00004772 listitem_T *item1, *item2;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00004773
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00004774 if (list_len(l1) != list_len(l2))
4775 return FALSE;
4776
Bram Moolenaar8a283e52005-01-06 23:28:25 +00004777 for (item1 = l1->lv_first, item2 = l2->lv_first;
4778 item1 != NULL && item2 != NULL;
4779 item1 = item1->li_next, item2 = item2->li_next)
4780 if (!tv_equal(&item1->li_tv, &item2->li_tv, ic))
4781 return FALSE;
4782 return item1 == NULL && item2 == NULL;
4783}
4784
4785/*
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00004786 * Return TRUE when two dictionaries have exactly the same key/values.
4787 */
4788 static int
4789dict_equal(d1, d2, ic)
Bram Moolenaar33570922005-01-25 22:26:29 +00004790 dict_T *d1;
4791 dict_T *d2;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00004792 int ic; /* ignore case for strings */
4793{
Bram Moolenaar33570922005-01-25 22:26:29 +00004794 hashitem_T *hi;
4795 dictitem_T *item2;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00004796 int todo;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00004797
4798 if (dict_len(d1) != dict_len(d2))
4799 return FALSE;
4800
Bram Moolenaar33570922005-01-25 22:26:29 +00004801 todo = d1->dv_hashtab.ht_used;
4802 for (hi = d1->dv_hashtab.ht_array; todo > 0; ++hi)
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00004803 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00004804 if (!HASHITEM_EMPTY(hi))
4805 {
4806 item2 = dict_find(d2, hi->hi_key, -1);
4807 if (item2 == NULL)
4808 return FALSE;
4809 if (!tv_equal(&HI2DI(hi)->di_tv, &item2->di_tv, ic))
4810 return FALSE;
4811 --todo;
4812 }
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00004813 }
4814 return TRUE;
4815}
4816
4817/*
Bram Moolenaar8a283e52005-01-06 23:28:25 +00004818 * Return TRUE if "tv1" and "tv2" have the same value.
4819 * Compares the items just like "==" would compare them.
4820 */
4821 static int
4822tv_equal(tv1, tv2, ic)
Bram Moolenaar33570922005-01-25 22:26:29 +00004823 typval_T *tv1;
4824 typval_T *tv2;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00004825 int ic; /* ignore case */
4826{
4827 char_u buf1[NUMBUFLEN], buf2[NUMBUFLEN];
4828
4829 if (tv1->v_type == VAR_LIST || tv2->v_type == VAR_LIST)
4830 {
4831 /* recursive! */
4832 if (tv1->v_type != tv2->v_type
4833 || !list_equal(tv1->vval.v_list, tv2->vval.v_list, ic))
4834 return FALSE;
4835 }
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00004836 else if (tv1->v_type == VAR_DICT || tv2->v_type == VAR_DICT)
4837 {
4838 /* recursive! */
4839 if (tv1->v_type != tv2->v_type
4840 || !dict_equal(tv1->vval.v_dict, tv2->vval.v_dict, ic))
4841 return FALSE;
4842 }
Bram Moolenaar8a283e52005-01-06 23:28:25 +00004843 else if (tv1->v_type == VAR_FUNC || tv2->v_type == VAR_FUNC)
4844 {
4845 if (tv1->v_type != tv2->v_type
4846 || tv1->vval.v_string == NULL
4847 || tv2->vval.v_string == NULL
4848 || STRCMP(tv1->vval.v_string, tv2->vval.v_string) != 0)
4849 return FALSE;
4850 }
4851 else if (tv1->v_type == VAR_NUMBER || tv2->v_type == VAR_NUMBER)
4852 {
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00004853 /* "4" is equal to 4. But don't consider 'a' and zero to be equal.
4854 * Don't consider "4x" to be equal to 4. */
4855 if ((tv1->v_type == VAR_STRING
4856 && !string_isa_number(tv1->vval.v_string))
4857 || (tv2->v_type == VAR_STRING
4858 && !string_isa_number(tv2->vval.v_string)))
4859 return FALSE;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00004860 if (get_tv_number(tv1) != get_tv_number(tv2))
4861 return FALSE;
4862 }
4863 else if (!ic && STRCMP(get_tv_string_buf(tv1, buf1),
4864 get_tv_string_buf(tv2, buf2)) != 0)
4865 return FALSE;
4866 else if (ic && STRICMP(get_tv_string_buf(tv1, buf1),
4867 get_tv_string_buf(tv2, buf2)) != 0)
4868 return FALSE;
4869 return TRUE;
4870}
4871
4872/*
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00004873 * Return TRUE if "tv" is a number without other non-white characters.
4874 */
4875 static int
4876string_isa_number(s)
4877 char_u *s;
4878{
4879 int len;
4880
4881 vim_str2nr(s, NULL, &len, TRUE, TRUE, NULL, NULL);
4882 return len > 0 && *skipwhite(s + len) == NUL;
4883}
4884
4885/*
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004886 * Locate item with index "n" in list "l" and return it.
4887 * A negative index is counted from the end; -1 is the last item.
4888 * Returns NULL when "n" is out of range.
4889 */
Bram Moolenaar33570922005-01-25 22:26:29 +00004890 static listitem_T *
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004891list_find(l, n)
Bram Moolenaar33570922005-01-25 22:26:29 +00004892 list_T *l;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004893 long n;
4894{
Bram Moolenaar33570922005-01-25 22:26:29 +00004895 listitem_T *item;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004896 long idx;
4897
4898 if (l == NULL)
4899 return NULL;
Bram Moolenaar758711c2005-02-02 23:11:38 +00004900
4901 /* Negative index is relative to the end. */
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004902 if (n < 0)
Bram Moolenaar758711c2005-02-02 23:11:38 +00004903 n = l->lv_len + n;
4904
4905 /* Check for index out of range. */
4906 if (n < 0 || n >= l->lv_len)
4907 return NULL;
4908
4909 /* When there is a cached index may start search from there. */
4910 if (l->lv_idx_item != NULL)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004911 {
Bram Moolenaar758711c2005-02-02 23:11:38 +00004912 if (n < l->lv_idx / 2)
4913 {
4914 /* closest to the start of the list */
4915 item = l->lv_first;
4916 idx = 0;
4917 }
4918 else if (n > (l->lv_idx + l->lv_len) / 2)
4919 {
4920 /* closest to the end of the list */
4921 item = l->lv_last;
4922 idx = l->lv_len - 1;
4923 }
4924 else
4925 {
4926 /* closest to the cached index */
4927 item = l->lv_idx_item;
4928 idx = l->lv_idx;
4929 }
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004930 }
4931 else
4932 {
Bram Moolenaar758711c2005-02-02 23:11:38 +00004933 if (n < l->lv_len / 2)
4934 {
4935 /* closest to the start of the list */
4936 item = l->lv_first;
4937 idx = 0;
4938 }
4939 else
4940 {
4941 /* closest to the end of the list */
4942 item = l->lv_last;
4943 idx = l->lv_len - 1;
4944 }
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004945 }
Bram Moolenaar758711c2005-02-02 23:11:38 +00004946
4947 while (n > idx)
4948 {
4949 /* search forward */
4950 item = item->li_next;
4951 ++idx;
4952 }
4953 while (n < idx)
4954 {
4955 /* search backward */
4956 item = item->li_prev;
4957 --idx;
4958 }
4959
4960 /* cache the used index */
4961 l->lv_idx = idx;
4962 l->lv_idx_item = item;
4963
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004964 return item;
4965}
4966
4967/*
Bram Moolenaar6cc16192005-01-08 21:49:45 +00004968 * Locate "item" list "l" and return its index.
4969 * Returns -1 when "item" is not in the list.
4970 */
4971 static long
4972list_idx_of_item(l, item)
Bram Moolenaar33570922005-01-25 22:26:29 +00004973 list_T *l;
4974 listitem_T *item;
Bram Moolenaar6cc16192005-01-08 21:49:45 +00004975{
4976 long idx = 0;
Bram Moolenaar33570922005-01-25 22:26:29 +00004977 listitem_T *li;
Bram Moolenaar6cc16192005-01-08 21:49:45 +00004978
4979 if (l == NULL)
4980 return -1;
4981 idx = 0;
4982 for (li = l->lv_first; li != NULL && li != item; li = li->li_next)
4983 ++idx;
4984 if (li == NULL)
4985 return -1;
4986 return idx;;
4987}
4988
4989/*
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004990 * Append item "item" to the end of list "l".
4991 */
4992 static void
4993list_append(l, item)
Bram Moolenaar33570922005-01-25 22:26:29 +00004994 list_T *l;
4995 listitem_T *item;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00004996{
4997 if (l->lv_last == NULL)
4998 {
4999 /* empty list */
5000 l->lv_first = item;
5001 l->lv_last = item;
5002 item->li_prev = NULL;
5003 }
5004 else
5005 {
5006 l->lv_last->li_next = item;
5007 item->li_prev = l->lv_last;
5008 l->lv_last = item;
5009 }
Bram Moolenaar758711c2005-02-02 23:11:38 +00005010 ++l->lv_len;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005011 item->li_next = NULL;
5012}
5013
5014/*
Bram Moolenaar33570922005-01-25 22:26:29 +00005015 * Append typval_T "tv" to the end of list "l".
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005016 * Return FAIL when out of memory.
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005017 */
5018 static int
5019list_append_tv(l, tv)
Bram Moolenaar33570922005-01-25 22:26:29 +00005020 list_T *l;
5021 typval_T *tv;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005022{
Bram Moolenaar33570922005-01-25 22:26:29 +00005023 listitem_T *ni = listitem_alloc();
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005024
5025 if (ni == NULL)
5026 return FAIL;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005027 copy_tv(tv, &ni->li_tv);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005028 list_append(l, ni);
5029 return OK;
5030}
5031
5032/*
Bram Moolenaar33570922005-01-25 22:26:29 +00005033 * Insert typval_T "tv" in list "l" before "item".
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005034 * If "item" is NULL append at the end.
5035 * Return FAIL when out of memory.
5036 */
5037 static int
5038list_insert_tv(l, tv, item)
Bram Moolenaar33570922005-01-25 22:26:29 +00005039 list_T *l;
5040 typval_T *tv;
5041 listitem_T *item;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005042{
Bram Moolenaar33570922005-01-25 22:26:29 +00005043 listitem_T *ni = listitem_alloc();
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005044
5045 if (ni == NULL)
5046 return FAIL;
5047 copy_tv(tv, &ni->li_tv);
5048 if (item == NULL)
5049 /* Append new item at end of list. */
5050 list_append(l, ni);
5051 else
5052 {
5053 /* Insert new item before existing item. */
5054 ni->li_prev = item->li_prev;
5055 ni->li_next = item;
5056 if (item->li_prev == NULL)
Bram Moolenaar758711c2005-02-02 23:11:38 +00005057 {
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005058 l->lv_first = ni;
Bram Moolenaar758711c2005-02-02 23:11:38 +00005059 ++l->lv_idx;
5060 }
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005061 else
Bram Moolenaar758711c2005-02-02 23:11:38 +00005062 {
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005063 item->li_prev->li_next = ni;
Bram Moolenaar758711c2005-02-02 23:11:38 +00005064 l->lv_idx_item = NULL;
5065 }
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005066 item->li_prev = ni;
Bram Moolenaar758711c2005-02-02 23:11:38 +00005067 ++l->lv_len;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005068 }
5069 return OK;
5070}
5071
5072/*
5073 * Extend "l1" with "l2".
5074 * If "bef" is NULL append at the end, otherwise insert before this item.
5075 * Returns FAIL when out of memory.
5076 */
5077 static int
5078list_extend(l1, l2, bef)
Bram Moolenaar33570922005-01-25 22:26:29 +00005079 list_T *l1;
5080 list_T *l2;
5081 listitem_T *bef;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005082{
Bram Moolenaar33570922005-01-25 22:26:29 +00005083 listitem_T *item;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005084
5085 for (item = l2->lv_first; item != NULL; item = item->li_next)
5086 if (list_insert_tv(l1, &item->li_tv, bef) == FAIL)
5087 return FAIL;
5088 return OK;
5089}
5090
5091/*
5092 * Concatenate lists "l1" and "l2" into a new list, stored in "tv".
5093 * Return FAIL when out of memory.
5094 */
5095 static int
5096list_concat(l1, l2, tv)
Bram Moolenaar33570922005-01-25 22:26:29 +00005097 list_T *l1;
5098 list_T *l2;
5099 typval_T *tv;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005100{
Bram Moolenaar33570922005-01-25 22:26:29 +00005101 list_T *l;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005102
5103 /* make a copy of the first list. */
Bram Moolenaar81bf7082005-02-12 14:31:42 +00005104 l = list_copy(l1, FALSE, 0);
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005105 if (l == NULL)
5106 return FAIL;
5107 tv->v_type = VAR_LIST;
5108 tv->vval.v_list = l;
5109
5110 /* append all items from the second list */
5111 return list_extend(l, l2, NULL);
5112}
5113
5114/*
Bram Moolenaare9a41262005-01-15 22:18:47 +00005115 * Make a copy of list "orig". Shallow if "deep" is FALSE.
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005116 * The refcount of the new list is set to 1.
Bram Moolenaar81bf7082005-02-12 14:31:42 +00005117 * See item_copy() for "copyID".
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005118 * Returns NULL when out of memory.
5119 */
Bram Moolenaar33570922005-01-25 22:26:29 +00005120 static list_T *
Bram Moolenaar81bf7082005-02-12 14:31:42 +00005121list_copy(orig, deep, copyID)
Bram Moolenaar33570922005-01-25 22:26:29 +00005122 list_T *orig;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005123 int deep;
Bram Moolenaar81bf7082005-02-12 14:31:42 +00005124 int copyID;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005125{
Bram Moolenaar33570922005-01-25 22:26:29 +00005126 list_T *copy;
5127 listitem_T *item;
5128 listitem_T *ni;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005129
5130 if (orig == NULL)
5131 return NULL;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005132
5133 copy = list_alloc();
5134 if (copy != NULL)
5135 {
Bram Moolenaar81bf7082005-02-12 14:31:42 +00005136 if (copyID != 0)
5137 {
5138 /* Do this before adding the items, because one of the items may
5139 * refer back to this list. */
5140 orig->lv_copyID = copyID;
5141 orig->lv_copylist = copy;
5142 }
5143 for (item = orig->lv_first; item != NULL && !got_int;
5144 item = item->li_next)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005145 {
5146 ni = listitem_alloc();
5147 if (ni == NULL)
5148 break;
Bram Moolenaare9a41262005-01-15 22:18:47 +00005149 if (deep)
Bram Moolenaar81bf7082005-02-12 14:31:42 +00005150 {
5151 if (item_copy(&item->li_tv, &ni->li_tv, deep, copyID) == FAIL)
5152 {
5153 vim_free(ni);
5154 break;
5155 }
5156 }
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005157 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005158 copy_tv(&item->li_tv, &ni->li_tv);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005159 list_append(copy, ni);
5160 }
5161 ++copy->lv_refcount;
Bram Moolenaar81bf7082005-02-12 14:31:42 +00005162 if (item != NULL)
5163 {
5164 list_unref(copy);
5165 copy = NULL;
5166 }
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005167 }
5168
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005169 return copy;
5170}
5171
5172/*
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005173 * Remove items "item" to "item2" from list "l".
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00005174 * Does not free the listitem or the value!
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005175 */
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005176 static void
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00005177list_remove(l, item, item2)
Bram Moolenaar33570922005-01-25 22:26:29 +00005178 list_T *l;
5179 listitem_T *item;
5180 listitem_T *item2;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005181{
Bram Moolenaar33570922005-01-25 22:26:29 +00005182 listitem_T *ip;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005183
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005184 /* notify watchers */
5185 for (ip = item; ip != NULL; ip = ip->li_next)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005186 {
Bram Moolenaar758711c2005-02-02 23:11:38 +00005187 --l->lv_len;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005188 list_fix_watch(l, ip);
5189 if (ip == item2)
5190 break;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005191 }
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005192
5193 if (item2->li_next == NULL)
5194 l->lv_last = item->li_prev;
5195 else
5196 item2->li_next->li_prev = item->li_prev;
5197 if (item->li_prev == NULL)
5198 l->lv_first = item2->li_next;
5199 else
5200 item->li_prev->li_next = item2->li_next;
Bram Moolenaar758711c2005-02-02 23:11:38 +00005201 l->lv_idx_item = NULL;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005202}
5203
5204/*
5205 * Return an allocated string with the string representation of a list.
5206 * May return NULL.
5207 */
5208 static char_u *
5209list2string(tv)
Bram Moolenaar33570922005-01-25 22:26:29 +00005210 typval_T *tv;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005211{
5212 garray_T ga;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005213
5214 if (tv->vval.v_list == NULL)
5215 return NULL;
5216 ga_init2(&ga, (int)sizeof(char), 80);
5217 ga_append(&ga, '[');
Bram Moolenaar81bf7082005-02-12 14:31:42 +00005218 if (list_join(&ga, tv->vval.v_list, (char_u *)", ", FALSE) == FAIL)
5219 {
5220 vim_free(ga.ga_data);
5221 return NULL;
5222 }
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005223 ga_append(&ga, ']');
5224 ga_append(&ga, NUL);
5225 return (char_u *)ga.ga_data;
5226}
5227
5228/*
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005229 * Join list "l" into a string in "*gap", using separator "sep".
5230 * When "echo" is TRUE use String as echoed, otherwise as inside a List.
Bram Moolenaar81bf7082005-02-12 14:31:42 +00005231 * Return FAIL or OK.
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005232 */
Bram Moolenaar81bf7082005-02-12 14:31:42 +00005233 static int
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005234list_join(gap, l, sep, echo)
5235 garray_T *gap;
Bram Moolenaar33570922005-01-25 22:26:29 +00005236 list_T *l;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005237 char_u *sep;
5238 int echo;
5239{
5240 int first = TRUE;
5241 char_u *tofree;
5242 char_u numbuf[NUMBUFLEN];
Bram Moolenaar33570922005-01-25 22:26:29 +00005243 listitem_T *item;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005244 char_u *s;
5245
Bram Moolenaar81bf7082005-02-12 14:31:42 +00005246 for (item = l->lv_first; item != NULL && !got_int; item = item->li_next)
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005247 {
5248 if (first)
5249 first = FALSE;
5250 else
5251 ga_concat(gap, sep);
5252
5253 if (echo)
5254 s = echo_string(&item->li_tv, &tofree, numbuf);
5255 else
5256 s = tv2string(&item->li_tv, &tofree, numbuf);
5257 if (s != NULL)
5258 ga_concat(gap, s);
5259 vim_free(tofree);
Bram Moolenaar81bf7082005-02-12 14:31:42 +00005260 if (s == NULL)
5261 return FAIL;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005262 }
Bram Moolenaar81bf7082005-02-12 14:31:42 +00005263 return OK;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005264}
5265
5266/*
Bram Moolenaar8c711452005-01-14 21:53:12 +00005267 * Allocate an empty header for a dictionary.
5268 */
Bram Moolenaar33570922005-01-25 22:26:29 +00005269 static dict_T *
Bram Moolenaar8c711452005-01-14 21:53:12 +00005270dict_alloc()
5271{
Bram Moolenaar33570922005-01-25 22:26:29 +00005272 dict_T *d;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005273
Bram Moolenaar33570922005-01-25 22:26:29 +00005274 d = (dict_T *)alloc(sizeof(dict_T));
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005275 if (d != NULL)
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00005276 {
Bram Moolenaar33570922005-01-25 22:26:29 +00005277 hash_init(&d->dv_hashtab);
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00005278 d->dv_lock = 0;
5279 d->dv_refcount = 0;
Bram Moolenaar81bf7082005-02-12 14:31:42 +00005280 d->dv_copyID = 0;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00005281 }
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005282 return d;
Bram Moolenaar8c711452005-01-14 21:53:12 +00005283}
5284
5285/*
5286 * Unreference a Dictionary: decrement the reference count and free it when it
5287 * becomes zero.
5288 */
5289 static void
5290dict_unref(d)
Bram Moolenaar33570922005-01-25 22:26:29 +00005291 dict_T *d;
Bram Moolenaar8c711452005-01-14 21:53:12 +00005292{
5293 if (d != NULL && --d->dv_refcount <= 0)
5294 dict_free(d);
5295}
5296
5297/*
5298 * Free a Dictionary, including all items it contains.
5299 * Ignores the reference count.
5300 */
5301 static void
5302dict_free(d)
Bram Moolenaar33570922005-01-25 22:26:29 +00005303 dict_T *d;
Bram Moolenaar8c711452005-01-14 21:53:12 +00005304{
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005305 int todo;
Bram Moolenaar33570922005-01-25 22:26:29 +00005306 hashitem_T *hi;
Bram Moolenaar8c711452005-01-14 21:53:12 +00005307
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005308 /* Careful: we free the dictitems while they still appear in the
Bram Moolenaar33570922005-01-25 22:26:29 +00005309 * hashtab. Must not try to resize the hashtab! */
5310 todo = d->dv_hashtab.ht_used;
5311 for (hi = d->dv_hashtab.ht_array; todo > 0; ++hi)
Bram Moolenaar8c711452005-01-14 21:53:12 +00005312 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005313 if (!HASHITEM_EMPTY(hi))
5314 {
5315 dictitem_free(HI2DI(hi));
5316 --todo;
5317 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00005318 }
Bram Moolenaar33570922005-01-25 22:26:29 +00005319 hash_clear(&d->dv_hashtab);
Bram Moolenaar8c711452005-01-14 21:53:12 +00005320 vim_free(d);
5321}
5322
5323/*
5324 * Allocate a Dictionary item.
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005325 * The "key" is copied to the new item.
5326 * Note that the value of the item "di_tv" still needs to be initialized!
5327 * Returns NULL when out of memory.
Bram Moolenaar8c711452005-01-14 21:53:12 +00005328 */
Bram Moolenaar33570922005-01-25 22:26:29 +00005329 static dictitem_T *
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005330dictitem_alloc(key)
5331 char_u *key;
Bram Moolenaar8c711452005-01-14 21:53:12 +00005332{
Bram Moolenaar33570922005-01-25 22:26:29 +00005333 dictitem_T *di;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005334
Bram Moolenaar33570922005-01-25 22:26:29 +00005335 di = (dictitem_T *)alloc(sizeof(dictitem_T) + STRLEN(key));
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005336 if (di != NULL)
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00005337 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005338 STRCPY(di->di_key, key);
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00005339 di->di_flags = 0;
5340 }
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005341 return di;
Bram Moolenaar8c711452005-01-14 21:53:12 +00005342}
5343
5344/*
Bram Moolenaare9a41262005-01-15 22:18:47 +00005345 * Make a copy of a Dictionary item.
5346 */
Bram Moolenaar33570922005-01-25 22:26:29 +00005347 static dictitem_T *
Bram Moolenaare9a41262005-01-15 22:18:47 +00005348dictitem_copy(org)
Bram Moolenaar33570922005-01-25 22:26:29 +00005349 dictitem_T *org;
Bram Moolenaare9a41262005-01-15 22:18:47 +00005350{
Bram Moolenaar33570922005-01-25 22:26:29 +00005351 dictitem_T *di;
Bram Moolenaare9a41262005-01-15 22:18:47 +00005352
Bram Moolenaar33570922005-01-25 22:26:29 +00005353 di = (dictitem_T *)alloc(sizeof(dictitem_T) + STRLEN(org->di_key));
Bram Moolenaare9a41262005-01-15 22:18:47 +00005354 if (di != NULL)
5355 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005356 STRCPY(di->di_key, org->di_key);
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00005357 di->di_flags = 0;
Bram Moolenaare9a41262005-01-15 22:18:47 +00005358 copy_tv(&org->di_tv, &di->di_tv);
5359 }
5360 return di;
5361}
5362
5363/*
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005364 * Remove item "item" from Dictionary "dict" and free it.
5365 */
5366 static void
5367dictitem_remove(dict, item)
Bram Moolenaar33570922005-01-25 22:26:29 +00005368 dict_T *dict;
5369 dictitem_T *item;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005370{
Bram Moolenaar33570922005-01-25 22:26:29 +00005371 hashitem_T *hi;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005372
Bram Moolenaar33570922005-01-25 22:26:29 +00005373 hi = hash_find(&dict->dv_hashtab, item->di_key);
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005374 if (HASHITEM_EMPTY(hi))
5375 EMSG2(_(e_intern2), "dictitem_remove()");
5376 else
Bram Moolenaar33570922005-01-25 22:26:29 +00005377 hash_remove(&dict->dv_hashtab, hi);
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005378 dictitem_free(item);
5379}
5380
5381/*
Bram Moolenaar8c711452005-01-14 21:53:12 +00005382 * Free a dict item. Also clears the value.
5383 */
5384 static void
5385dictitem_free(item)
Bram Moolenaar33570922005-01-25 22:26:29 +00005386 dictitem_T *item;
Bram Moolenaar8c711452005-01-14 21:53:12 +00005387{
Bram Moolenaar8c711452005-01-14 21:53:12 +00005388 clear_tv(&item->di_tv);
5389 vim_free(item);
5390}
5391
5392/*
Bram Moolenaare9a41262005-01-15 22:18:47 +00005393 * Make a copy of dict "d". Shallow if "deep" is FALSE.
5394 * The refcount of the new dict is set to 1.
Bram Moolenaar81bf7082005-02-12 14:31:42 +00005395 * See item_copy() for "copyID".
Bram Moolenaare9a41262005-01-15 22:18:47 +00005396 * Returns NULL when out of memory.
5397 */
Bram Moolenaar33570922005-01-25 22:26:29 +00005398 static dict_T *
Bram Moolenaar81bf7082005-02-12 14:31:42 +00005399dict_copy(orig, deep, copyID)
Bram Moolenaar33570922005-01-25 22:26:29 +00005400 dict_T *orig;
Bram Moolenaare9a41262005-01-15 22:18:47 +00005401 int deep;
Bram Moolenaar81bf7082005-02-12 14:31:42 +00005402 int copyID;
Bram Moolenaare9a41262005-01-15 22:18:47 +00005403{
Bram Moolenaar33570922005-01-25 22:26:29 +00005404 dict_T *copy;
5405 dictitem_T *di;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005406 int todo;
Bram Moolenaar33570922005-01-25 22:26:29 +00005407 hashitem_T *hi;
Bram Moolenaare9a41262005-01-15 22:18:47 +00005408
5409 if (orig == NULL)
5410 return NULL;
5411
5412 copy = dict_alloc();
5413 if (copy != NULL)
5414 {
Bram Moolenaar81bf7082005-02-12 14:31:42 +00005415 if (copyID != 0)
5416 {
5417 orig->dv_copyID = copyID;
5418 orig->dv_copydict = copy;
5419 }
Bram Moolenaar33570922005-01-25 22:26:29 +00005420 todo = orig->dv_hashtab.ht_used;
Bram Moolenaar81bf7082005-02-12 14:31:42 +00005421 for (hi = orig->dv_hashtab.ht_array; todo > 0 && !got_int; ++hi)
Bram Moolenaare9a41262005-01-15 22:18:47 +00005422 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005423 if (!HASHITEM_EMPTY(hi))
Bram Moolenaare9a41262005-01-15 22:18:47 +00005424 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005425 --todo;
5426
5427 di = dictitem_alloc(hi->hi_key);
5428 if (di == NULL)
5429 break;
5430 if (deep)
Bram Moolenaar81bf7082005-02-12 14:31:42 +00005431 {
5432 if (item_copy(&HI2DI(hi)->di_tv, &di->di_tv, deep,
5433 copyID) == FAIL)
5434 {
5435 vim_free(di);
5436 break;
5437 }
5438 }
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005439 else
5440 copy_tv(&HI2DI(hi)->di_tv, &di->di_tv);
5441 if (dict_add(copy, di) == FAIL)
5442 {
5443 dictitem_free(di);
5444 break;
5445 }
Bram Moolenaare9a41262005-01-15 22:18:47 +00005446 }
Bram Moolenaare9a41262005-01-15 22:18:47 +00005447 }
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005448
Bram Moolenaare9a41262005-01-15 22:18:47 +00005449 ++copy->dv_refcount;
Bram Moolenaar81bf7082005-02-12 14:31:42 +00005450 if (todo > 0)
5451 {
5452 dict_unref(copy);
5453 copy = NULL;
5454 }
Bram Moolenaare9a41262005-01-15 22:18:47 +00005455 }
5456
5457 return copy;
5458}
5459
5460/*
Bram Moolenaar8c711452005-01-14 21:53:12 +00005461 * Add item "item" to Dictionary "d".
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005462 * Returns FAIL when out of memory and when key already existed.
Bram Moolenaar8c711452005-01-14 21:53:12 +00005463 */
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005464 static int
Bram Moolenaar8c711452005-01-14 21:53:12 +00005465dict_add(d, item)
Bram Moolenaar33570922005-01-25 22:26:29 +00005466 dict_T *d;
5467 dictitem_T *item;
Bram Moolenaar8c711452005-01-14 21:53:12 +00005468{
Bram Moolenaar33570922005-01-25 22:26:29 +00005469 return hash_add(&d->dv_hashtab, item->di_key);
Bram Moolenaar8c711452005-01-14 21:53:12 +00005470}
5471
Bram Moolenaar8c711452005-01-14 21:53:12 +00005472/*
Bram Moolenaare9a41262005-01-15 22:18:47 +00005473 * Get the number of items in a Dictionary.
5474 */
5475 static long
5476dict_len(d)
Bram Moolenaar33570922005-01-25 22:26:29 +00005477 dict_T *d;
Bram Moolenaare9a41262005-01-15 22:18:47 +00005478{
Bram Moolenaare9a41262005-01-15 22:18:47 +00005479 if (d == NULL)
5480 return 0L;
Bram Moolenaar33570922005-01-25 22:26:29 +00005481 return d->dv_hashtab.ht_used;
Bram Moolenaare9a41262005-01-15 22:18:47 +00005482}
5483
5484/*
Bram Moolenaar8c711452005-01-14 21:53:12 +00005485 * Find item "key[len]" in Dictionary "d".
5486 * If "len" is negative use strlen(key).
5487 * Returns NULL when not found.
5488 */
Bram Moolenaar33570922005-01-25 22:26:29 +00005489 static dictitem_T *
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005490dict_find(d, key, len)
Bram Moolenaar33570922005-01-25 22:26:29 +00005491 dict_T *d;
Bram Moolenaar8c711452005-01-14 21:53:12 +00005492 char_u *key;
5493 int len;
5494{
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005495#define AKEYLEN 200
5496 char_u buf[AKEYLEN];
5497 char_u *akey;
5498 char_u *tofree = NULL;
Bram Moolenaar33570922005-01-25 22:26:29 +00005499 hashitem_T *hi;
Bram Moolenaar8c711452005-01-14 21:53:12 +00005500
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005501 if (len < 0)
5502 akey = key;
5503 else if (len >= AKEYLEN)
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00005504 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005505 tofree = akey = vim_strnsave(key, len);
5506 if (akey == NULL)
5507 return NULL;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00005508 }
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005509 else
5510 {
5511 /* Avoid a malloc/free by using buf[]. */
5512 STRNCPY(buf, key, len);
5513 buf[len] = NUL;
5514 akey = buf;
5515 }
5516
Bram Moolenaar33570922005-01-25 22:26:29 +00005517 hi = hash_find(&d->dv_hashtab, akey);
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005518 vim_free(tofree);
5519 if (HASHITEM_EMPTY(hi))
5520 return NULL;
5521 return HI2DI(hi);
Bram Moolenaar8c711452005-01-14 21:53:12 +00005522}
5523
5524/*
5525 * Return an allocated string with the string representation of a Dictionary.
5526 * May return NULL.
5527 */
5528 static char_u *
5529dict2string(tv)
Bram Moolenaar33570922005-01-25 22:26:29 +00005530 typval_T *tv;
Bram Moolenaar8c711452005-01-14 21:53:12 +00005531{
5532 garray_T ga;
5533 int first = TRUE;
5534 char_u *tofree;
5535 char_u numbuf[NUMBUFLEN];
Bram Moolenaar33570922005-01-25 22:26:29 +00005536 hashitem_T *hi;
Bram Moolenaar8c711452005-01-14 21:53:12 +00005537 char_u *s;
Bram Moolenaar33570922005-01-25 22:26:29 +00005538 dict_T *d;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005539 int todo;
Bram Moolenaar8c711452005-01-14 21:53:12 +00005540
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005541 if ((d = tv->vval.v_dict) == NULL)
Bram Moolenaar8c711452005-01-14 21:53:12 +00005542 return NULL;
5543 ga_init2(&ga, (int)sizeof(char), 80);
5544 ga_append(&ga, '{');
5545
Bram Moolenaar33570922005-01-25 22:26:29 +00005546 todo = d->dv_hashtab.ht_used;
Bram Moolenaar81bf7082005-02-12 14:31:42 +00005547 for (hi = d->dv_hashtab.ht_array; todo > 0 && !got_int; ++hi)
Bram Moolenaar8c711452005-01-14 21:53:12 +00005548 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005549 if (!HASHITEM_EMPTY(hi))
Bram Moolenaar8c711452005-01-14 21:53:12 +00005550 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005551 --todo;
5552
5553 if (first)
5554 first = FALSE;
5555 else
5556 ga_concat(&ga, (char_u *)", ");
5557
5558 tofree = string_quote(hi->hi_key, FALSE);
5559 if (tofree != NULL)
5560 {
5561 ga_concat(&ga, tofree);
5562 vim_free(tofree);
5563 }
5564 ga_concat(&ga, (char_u *)": ");
5565 s = tv2string(&HI2DI(hi)->di_tv, &tofree, numbuf);
5566 if (s != NULL)
5567 ga_concat(&ga, s);
Bram Moolenaar8c711452005-01-14 21:53:12 +00005568 vim_free(tofree);
Bram Moolenaar81bf7082005-02-12 14:31:42 +00005569 if (s == NULL)
5570 break;
Bram Moolenaar8c711452005-01-14 21:53:12 +00005571 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00005572 }
Bram Moolenaar81bf7082005-02-12 14:31:42 +00005573 if (todo > 0)
5574 {
5575 vim_free(ga.ga_data);
5576 return NULL;
5577 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00005578
5579 ga_append(&ga, '}');
5580 ga_append(&ga, NUL);
5581 return (char_u *)ga.ga_data;
5582}
5583
5584/*
5585 * Allocate a variable for a Dictionary and fill it from "*arg".
5586 * Return OK or FAIL. Returns NOTDONE for {expr}.
5587 */
5588 static int
5589get_dict_tv(arg, rettv, evaluate)
5590 char_u **arg;
Bram Moolenaar33570922005-01-25 22:26:29 +00005591 typval_T *rettv;
Bram Moolenaar8c711452005-01-14 21:53:12 +00005592 int evaluate;
5593{
Bram Moolenaar33570922005-01-25 22:26:29 +00005594 dict_T *d = NULL;
5595 typval_T tvkey;
5596 typval_T tv;
Bram Moolenaar8c711452005-01-14 21:53:12 +00005597 char_u *key;
Bram Moolenaar33570922005-01-25 22:26:29 +00005598 dictitem_T *item;
Bram Moolenaar8c711452005-01-14 21:53:12 +00005599 char_u *start = skipwhite(*arg + 1);
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005600 char_u buf[NUMBUFLEN];
Bram Moolenaar8c711452005-01-14 21:53:12 +00005601
5602 /*
5603 * First check if it's not a curly-braces thing: {expr}.
5604 * Must do this without evaluating, otherwise a function may be called
5605 * twice. Unfortunately this means we need to call eval1() twice for the
5606 * first item.
Bram Moolenaare9a41262005-01-15 22:18:47 +00005607 * But {} is an empty Dictionary.
Bram Moolenaar8c711452005-01-14 21:53:12 +00005608 */
Bram Moolenaare9a41262005-01-15 22:18:47 +00005609 if (*start != '}')
5610 {
5611 if (eval1(&start, &tv, FALSE) == FAIL) /* recursive! */
5612 return FAIL;
5613 if (*start == '}')
5614 return NOTDONE;
5615 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00005616
5617 if (evaluate)
5618 {
5619 d = dict_alloc();
5620 if (d == NULL)
5621 return FAIL;
5622 }
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005623 tvkey.v_type = VAR_UNKNOWN;
5624 tv.v_type = VAR_UNKNOWN;
Bram Moolenaar8c711452005-01-14 21:53:12 +00005625
5626 *arg = skipwhite(*arg + 1);
5627 while (**arg != '}' && **arg != NUL)
5628 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005629 if (eval1(arg, &tvkey, evaluate) == FAIL) /* recursive! */
Bram Moolenaar8c711452005-01-14 21:53:12 +00005630 goto failret;
5631 if (**arg != ':')
5632 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00005633 EMSG2(_("E720: Missing colon in Dictionary: %s"), *arg);
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005634 clear_tv(&tvkey);
Bram Moolenaar8c711452005-01-14 21:53:12 +00005635 goto failret;
5636 }
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005637 key = get_tv_string_buf(&tvkey, buf);
Bram Moolenaar8c711452005-01-14 21:53:12 +00005638 if (*key == NUL)
5639 {
5640 EMSG(_(e_emptykey));
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005641 clear_tv(&tvkey);
Bram Moolenaar8c711452005-01-14 21:53:12 +00005642 goto failret;
5643 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00005644
5645 *arg = skipwhite(*arg + 1);
5646 if (eval1(arg, &tv, evaluate) == FAIL) /* recursive! */
5647 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005648 clear_tv(&tvkey);
Bram Moolenaar8c711452005-01-14 21:53:12 +00005649 goto failret;
5650 }
5651 if (evaluate)
5652 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005653 item = dict_find(d, key, -1);
Bram Moolenaar8c711452005-01-14 21:53:12 +00005654 if (item != NULL)
5655 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00005656 EMSG(_("E721: Duplicate key in Dictionary"));
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005657 clear_tv(&tvkey);
Bram Moolenaar8c711452005-01-14 21:53:12 +00005658 clear_tv(&tv);
5659 goto failret;
5660 }
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005661 item = dictitem_alloc(key);
5662 clear_tv(&tvkey);
5663 if (item != NULL)
Bram Moolenaar8c711452005-01-14 21:53:12 +00005664 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00005665 item->di_tv = tv;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00005666 item->di_tv.v_lock = 0;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00005667 if (dict_add(d, item) == FAIL)
5668 dictitem_free(item);
Bram Moolenaar8c711452005-01-14 21:53:12 +00005669 }
5670 }
5671
5672 if (**arg == '}')
5673 break;
5674 if (**arg != ',')
5675 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00005676 EMSG2(_("E722: Missing comma in Dictionary: %s"), *arg);
Bram Moolenaar8c711452005-01-14 21:53:12 +00005677 goto failret;
5678 }
5679 *arg = skipwhite(*arg + 1);
5680 }
5681
5682 if (**arg != '}')
5683 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00005684 EMSG2(_("E723: Missing end of Dictionary '}': %s"), *arg);
Bram Moolenaar8c711452005-01-14 21:53:12 +00005685failret:
5686 if (evaluate)
5687 dict_free(d);
5688 return FAIL;
5689 }
5690
5691 *arg = skipwhite(*arg + 1);
5692 if (evaluate)
5693 {
5694 rettv->v_type = VAR_DICT;
5695 rettv->vval.v_dict = d;
5696 ++d->dv_refcount;
5697 }
5698
5699 return OK;
5700}
5701
Bram Moolenaar8c711452005-01-14 21:53:12 +00005702/*
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005703 * Return a string with the string representation of a variable.
5704 * If the memory is allocated "tofree" is set to it, otherwise NULL.
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005705 * "numbuf" is used for a number.
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005706 * Does not put quotes around strings, as ":echo" displays values.
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005707 * May return NULL;
5708 */
5709 static char_u *
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005710echo_string(tv, tofree, numbuf)
Bram Moolenaar33570922005-01-25 22:26:29 +00005711 typval_T *tv;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005712 char_u **tofree;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005713 char_u *numbuf;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005714{
Bram Moolenaare9a41262005-01-15 22:18:47 +00005715 static int recurse = 0;
5716 char_u *r = NULL;
5717
Bram Moolenaar33570922005-01-25 22:26:29 +00005718 if (recurse >= DICT_MAXNEST)
Bram Moolenaare9a41262005-01-15 22:18:47 +00005719 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00005720 EMSG(_("E724: variable nested too deep for displaying"));
Bram Moolenaare9a41262005-01-15 22:18:47 +00005721 *tofree = NULL;
5722 return NULL;
5723 }
5724 ++recurse;
5725
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005726 switch (tv->v_type)
5727 {
5728 case VAR_FUNC:
5729 *tofree = NULL;
Bram Moolenaare9a41262005-01-15 22:18:47 +00005730 r = tv->vval.v_string;
5731 break;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005732 case VAR_LIST:
5733 *tofree = list2string(tv);
Bram Moolenaare9a41262005-01-15 22:18:47 +00005734 r = *tofree;
5735 break;
Bram Moolenaar8c711452005-01-14 21:53:12 +00005736 case VAR_DICT:
5737 *tofree = dict2string(tv);
Bram Moolenaare9a41262005-01-15 22:18:47 +00005738 r = *tofree;
5739 break;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005740 case VAR_STRING:
5741 case VAR_NUMBER:
Bram Moolenaare9a41262005-01-15 22:18:47 +00005742 *tofree = NULL;
5743 r = get_tv_string_buf(tv, numbuf);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005744 break;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005745 default:
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005746 EMSG2(_(e_intern2), "echo_string()");
Bram Moolenaare9a41262005-01-15 22:18:47 +00005747 *tofree = NULL;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005748 }
Bram Moolenaare9a41262005-01-15 22:18:47 +00005749
5750 --recurse;
5751 return r;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005752}
5753
5754/*
5755 * Return a string with the string representation of a variable.
5756 * If the memory is allocated "tofree" is set to it, otherwise NULL.
5757 * "numbuf" is used for a number.
5758 * Puts quotes around strings, so that they can be parsed back by eval().
5759 * May return NULL;
5760 */
5761 static char_u *
5762tv2string(tv, tofree, numbuf)
Bram Moolenaar33570922005-01-25 22:26:29 +00005763 typval_T *tv;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005764 char_u **tofree;
5765 char_u *numbuf;
5766{
5767 switch (tv->v_type)
5768 {
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005769 case VAR_FUNC:
5770 *tofree = string_quote(tv->vval.v_string, TRUE);
5771 return *tofree;
5772 case VAR_STRING:
5773 *tofree = string_quote(tv->vval.v_string, FALSE);
5774 return *tofree;
Bram Moolenaare9a41262005-01-15 22:18:47 +00005775 case VAR_NUMBER:
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005776 case VAR_LIST:
Bram Moolenaar8c711452005-01-14 21:53:12 +00005777 case VAR_DICT:
Bram Moolenaare9a41262005-01-15 22:18:47 +00005778 break;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005779 default:
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005780 EMSG2(_(e_intern2), "tv2string()");
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005781 }
Bram Moolenaare9a41262005-01-15 22:18:47 +00005782 return echo_string(tv, tofree, numbuf);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005783}
5784
5785/*
Bram Moolenaar33570922005-01-25 22:26:29 +00005786 * Return string "str" in ' quotes, doubling ' characters.
5787 * If "str" is NULL an empty string is assumed.
Bram Moolenaar8c711452005-01-14 21:53:12 +00005788 * If "function" is TRUE make it function('string').
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005789 */
5790 static char_u *
5791string_quote(str, function)
5792 char_u *str;
5793 int function;
5794{
Bram Moolenaar33570922005-01-25 22:26:29 +00005795 unsigned len;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005796 char_u *p, *r, *s;
5797
Bram Moolenaar33570922005-01-25 22:26:29 +00005798 len = (function ? 13 : 3);
5799 if (str != NULL)
5800 {
5801 len += STRLEN(str);
5802 for (p = str; *p != NUL; mb_ptr_adv(p))
5803 if (*p == '\'')
5804 ++len;
5805 }
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005806 s = r = alloc(len);
5807 if (r != NULL)
5808 {
5809 if (function)
5810 {
Bram Moolenaar8c711452005-01-14 21:53:12 +00005811 STRCPY(r, "function('");
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005812 r += 10;
5813 }
5814 else
Bram Moolenaar8c711452005-01-14 21:53:12 +00005815 *r++ = '\'';
Bram Moolenaar33570922005-01-25 22:26:29 +00005816 if (str != NULL)
5817 for (p = str; *p != NUL; )
5818 {
5819 if (*p == '\'')
5820 *r++ = '\'';
5821 MB_COPY_CHAR(p, r);
5822 }
Bram Moolenaar8c711452005-01-14 21:53:12 +00005823 *r++ = '\'';
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005824 if (function)
5825 *r++ = ')';
5826 *r++ = NUL;
5827 }
5828 return s;
5829}
5830
5831/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00005832 * Get the value of an environment variable.
5833 * "arg" is pointing to the '$'. It is advanced to after the name.
5834 * If the environment variable was not set, silently assume it is empty.
5835 * Always return OK.
5836 */
5837 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005838get_env_tv(arg, rettv, evaluate)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005839 char_u **arg;
Bram Moolenaar33570922005-01-25 22:26:29 +00005840 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005841 int evaluate;
5842{
5843 char_u *string = NULL;
5844 int len;
5845 int cc;
5846 char_u *name;
5847
5848 ++*arg;
5849 name = *arg;
5850 len = get_env_len(arg);
5851 if (evaluate)
5852 {
5853 if (len != 0)
5854 {
5855 cc = name[len];
5856 name[len] = NUL;
5857 /* first try mch_getenv(), fast for normal environment vars */
5858 string = mch_getenv(name);
5859 if (string != NULL && *string != NUL)
5860 string = vim_strsave(string);
5861 else
5862 {
5863 /* next try expanding things like $VIM and ${HOME} */
5864 string = expand_env_save(name - 1);
5865 if (string != NULL && *string == '$')
5866 {
5867 vim_free(string);
5868 string = NULL;
5869 }
5870 }
5871 name[len] = cc;
5872 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00005873 rettv->v_type = VAR_STRING;
5874 rettv->vval.v_string = string;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005875 }
5876
5877 return OK;
5878}
5879
5880/*
5881 * Array with names and number of arguments of all internal functions
5882 * MUST BE KEPT SORTED IN strcmp() ORDER FOR BINARY SEARCH!
5883 */
5884static struct fst
5885{
5886 char *f_name; /* function name */
5887 char f_min_argc; /* minimal number of arguments */
5888 char f_max_argc; /* maximal number of arguments */
Bram Moolenaar33570922005-01-25 22:26:29 +00005889 void (*f_func) __ARGS((typval_T *args, typval_T *rvar));
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005890 /* implemenation of function */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005891} functions[] =
5892{
Bram Moolenaar0d660222005-01-07 21:51:51 +00005893 {"add", 2, 2, f_add},
Bram Moolenaar071d4272004-06-13 20:20:40 +00005894 {"append", 2, 2, f_append},
5895 {"argc", 0, 0, f_argc},
5896 {"argidx", 0, 0, f_argidx},
5897 {"argv", 1, 1, f_argv},
5898 {"browse", 4, 4, f_browse},
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00005899 {"browsedir", 2, 2, f_browsedir},
Bram Moolenaar071d4272004-06-13 20:20:40 +00005900 {"bufexists", 1, 1, f_bufexists},
5901 {"buffer_exists", 1, 1, f_bufexists}, /* obsolete */
5902 {"buffer_name", 1, 1, f_bufname}, /* obsolete */
5903 {"buffer_number", 1, 1, f_bufnr}, /* obsolete */
5904 {"buflisted", 1, 1, f_buflisted},
5905 {"bufloaded", 1, 1, f_bufloaded},
5906 {"bufname", 1, 1, f_bufname},
5907 {"bufnr", 1, 1, f_bufnr},
5908 {"bufwinnr", 1, 1, f_bufwinnr},
5909 {"byte2line", 1, 1, f_byte2line},
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00005910 {"byteidx", 2, 2, f_byteidx},
Bram Moolenaare9a41262005-01-15 22:18:47 +00005911 {"call", 2, 3, f_call},
Bram Moolenaar071d4272004-06-13 20:20:40 +00005912 {"char2nr", 1, 1, f_char2nr},
5913 {"cindent", 1, 1, f_cindent},
5914 {"col", 1, 1, f_col},
5915 {"confirm", 1, 4, f_confirm},
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005916 {"copy", 1, 1, f_copy},
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005917 {"count", 2, 4, f_count},
Bram Moolenaar071d4272004-06-13 20:20:40 +00005918 {"cscope_connection",0,3, f_cscope_connection},
5919 {"cursor", 2, 2, f_cursor},
Bram Moolenaar81bf7082005-02-12 14:31:42 +00005920 {"deepcopy", 1, 2, f_deepcopy},
Bram Moolenaar071d4272004-06-13 20:20:40 +00005921 {"delete", 1, 1, f_delete},
5922 {"did_filetype", 0, 0, f_did_filetype},
Bram Moolenaar47136d72004-10-12 20:02:24 +00005923 {"diff_filler", 1, 1, f_diff_filler},
5924 {"diff_hlID", 2, 2, f_diff_hlID},
Bram Moolenaare49b69a2005-01-08 16:11:57 +00005925 {"empty", 1, 1, f_empty},
Bram Moolenaar071d4272004-06-13 20:20:40 +00005926 {"escape", 2, 2, f_escape},
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005927 {"eval", 1, 1, f_eval},
Bram Moolenaar071d4272004-06-13 20:20:40 +00005928 {"eventhandler", 0, 0, f_eventhandler},
5929 {"executable", 1, 1, f_executable},
5930 {"exists", 1, 1, f_exists},
5931 {"expand", 1, 2, f_expand},
Bram Moolenaar8a283e52005-01-06 23:28:25 +00005932 {"extend", 2, 3, f_extend},
Bram Moolenaar071d4272004-06-13 20:20:40 +00005933 {"file_readable", 1, 1, f_filereadable}, /* obsolete */
5934 {"filereadable", 1, 1, f_filereadable},
5935 {"filewritable", 1, 1, f_filewritable},
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005936 {"filter", 2, 2, f_filter},
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00005937 {"finddir", 1, 3, f_finddir},
5938 {"findfile", 1, 3, f_findfile},
Bram Moolenaar071d4272004-06-13 20:20:40 +00005939 {"fnamemodify", 2, 2, f_fnamemodify},
5940 {"foldclosed", 1, 1, f_foldclosed},
5941 {"foldclosedend", 1, 1, f_foldclosedend},
5942 {"foldlevel", 1, 1, f_foldlevel},
5943 {"foldtext", 0, 0, f_foldtext},
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00005944 {"foldtextresult", 1, 1, f_foldtextresult},
Bram Moolenaar071d4272004-06-13 20:20:40 +00005945 {"foreground", 0, 0, f_foreground},
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005946 {"function", 1, 1, f_function},
Bram Moolenaar0d660222005-01-07 21:51:51 +00005947 {"get", 2, 3, f_get},
Bram Moolenaar071d4272004-06-13 20:20:40 +00005948 {"getbufvar", 2, 2, f_getbufvar},
5949 {"getchar", 0, 1, f_getchar},
5950 {"getcharmod", 0, 0, f_getcharmod},
5951 {"getcmdline", 0, 0, f_getcmdline},
5952 {"getcmdpos", 0, 0, f_getcmdpos},
5953 {"getcwd", 0, 0, f_getcwd},
Bram Moolenaar46c9c732004-12-12 11:37:09 +00005954 {"getfontname", 0, 1, f_getfontname},
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00005955 {"getfperm", 1, 1, f_getfperm},
Bram Moolenaar071d4272004-06-13 20:20:40 +00005956 {"getfsize", 1, 1, f_getfsize},
5957 {"getftime", 1, 1, f_getftime},
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00005958 {"getftype", 1, 1, f_getftype},
Bram Moolenaar0d660222005-01-07 21:51:51 +00005959 {"getline", 1, 2, f_getline},
Bram Moolenaar071d4272004-06-13 20:20:40 +00005960 {"getreg", 0, 1, f_getreg},
5961 {"getregtype", 0, 1, f_getregtype},
5962 {"getwinposx", 0, 0, f_getwinposx},
5963 {"getwinposy", 0, 0, f_getwinposy},
5964 {"getwinvar", 2, 2, f_getwinvar},
5965 {"glob", 1, 1, f_glob},
5966 {"globpath", 2, 2, f_globpath},
5967 {"has", 1, 1, f_has},
Bram Moolenaare9a41262005-01-15 22:18:47 +00005968 {"has_key", 2, 2, f_has_key},
Bram Moolenaar071d4272004-06-13 20:20:40 +00005969 {"hasmapto", 1, 2, f_hasmapto},
5970 {"highlightID", 1, 1, f_hlID}, /* obsolete */
5971 {"highlight_exists",1, 1, f_hlexists}, /* obsolete */
5972 {"histadd", 2, 2, f_histadd},
5973 {"histdel", 1, 2, f_histdel},
5974 {"histget", 1, 2, f_histget},
5975 {"histnr", 1, 1, f_histnr},
5976 {"hlID", 1, 1, f_hlID},
5977 {"hlexists", 1, 1, f_hlexists},
5978 {"hostname", 0, 0, f_hostname},
5979 {"iconv", 3, 3, f_iconv},
5980 {"indent", 1, 1, f_indent},
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005981 {"index", 2, 4, f_index},
Bram Moolenaar071d4272004-06-13 20:20:40 +00005982 {"input", 1, 2, f_input},
5983 {"inputdialog", 1, 3, f_inputdialog},
5984 {"inputrestore", 0, 0, f_inputrestore},
5985 {"inputsave", 0, 0, f_inputsave},
5986 {"inputsecret", 1, 2, f_inputsecret},
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005987 {"insert", 2, 3, f_insert},
Bram Moolenaar071d4272004-06-13 20:20:40 +00005988 {"isdirectory", 1, 1, f_isdirectory},
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00005989 {"islocked", 1, 1, f_islocked},
Bram Moolenaar8c711452005-01-14 21:53:12 +00005990 {"items", 1, 1, f_items},
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00005991 {"join", 1, 2, f_join},
Bram Moolenaar8c711452005-01-14 21:53:12 +00005992 {"keys", 1, 1, f_keys},
Bram Moolenaar071d4272004-06-13 20:20:40 +00005993 {"last_buffer_nr", 0, 0, f_last_buffer_nr},/* obsolete */
Bram Moolenaar49cd9572005-01-03 21:06:01 +00005994 {"len", 1, 1, f_len},
Bram Moolenaar071d4272004-06-13 20:20:40 +00005995 {"libcall", 3, 3, f_libcall},
5996 {"libcallnr", 3, 3, f_libcallnr},
5997 {"line", 1, 1, f_line},
5998 {"line2byte", 1, 1, f_line2byte},
5999 {"lispindent", 1, 1, f_lispindent},
6000 {"localtime", 0, 0, f_localtime},
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00006001 {"map", 2, 2, f_map},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006002 {"maparg", 1, 2, f_maparg},
6003 {"mapcheck", 1, 2, f_mapcheck},
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00006004 {"match", 2, 4, f_match},
6005 {"matchend", 2, 4, f_matchend},
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00006006 {"matchlist", 2, 4, f_matchlist},
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00006007 {"matchstr", 2, 4, f_matchstr},
Bram Moolenaar6cc16192005-01-08 21:49:45 +00006008 {"max", 1, 1, f_max},
6009 {"min", 1, 1, f_min},
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00006010#ifdef vim_mkdir
6011 {"mkdir", 1, 3, f_mkdir},
6012#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00006013 {"mode", 0, 0, f_mode},
6014 {"nextnonblank", 1, 1, f_nextnonblank},
6015 {"nr2char", 1, 1, f_nr2char},
6016 {"prevnonblank", 1, 1, f_prevnonblank},
Bram Moolenaar8c711452005-01-14 21:53:12 +00006017 {"range", 1, 3, f_range},
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00006018 {"readfile", 1, 3, f_readfile},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006019 {"remote_expr", 2, 3, f_remote_expr},
6020 {"remote_foreground", 1, 1, f_remote_foreground},
6021 {"remote_peek", 1, 2, f_remote_peek},
6022 {"remote_read", 1, 1, f_remote_read},
6023 {"remote_send", 2, 3, f_remote_send},
Bram Moolenaar8a283e52005-01-06 23:28:25 +00006024 {"remove", 2, 3, f_remove},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006025 {"rename", 2, 2, f_rename},
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00006026 {"repeat", 2, 2, f_repeat},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006027 {"resolve", 1, 1, f_resolve},
Bram Moolenaar0d660222005-01-07 21:51:51 +00006028 {"reverse", 1, 1, f_reverse},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006029 {"search", 1, 2, f_search},
6030 {"searchpair", 3, 5, f_searchpair},
6031 {"server2client", 2, 2, f_server2client},
6032 {"serverlist", 0, 0, f_serverlist},
6033 {"setbufvar", 3, 3, f_setbufvar},
6034 {"setcmdpos", 1, 1, f_setcmdpos},
6035 {"setline", 2, 2, f_setline},
6036 {"setreg", 2, 3, f_setreg},
6037 {"setwinvar", 3, 3, f_setwinvar},
6038 {"simplify", 1, 1, f_simplify},
Bram Moolenaar0d660222005-01-07 21:51:51 +00006039 {"sort", 1, 2, f_sort},
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00006040 {"split", 1, 2, f_split},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006041#ifdef HAVE_STRFTIME
6042 {"strftime", 1, 2, f_strftime},
6043#endif
Bram Moolenaar33570922005-01-25 22:26:29 +00006044 {"stridx", 2, 3, f_stridx},
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006045 {"string", 1, 1, f_string},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006046 {"strlen", 1, 1, f_strlen},
6047 {"strpart", 2, 3, f_strpart},
Bram Moolenaar532c7802005-01-27 14:44:31 +00006048 {"strridx", 2, 3, f_strridx},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006049 {"strtrans", 1, 1, f_strtrans},
6050 {"submatch", 1, 1, f_submatch},
6051 {"substitute", 4, 4, f_substitute},
6052 {"synID", 3, 3, f_synID},
6053 {"synIDattr", 2, 3, f_synIDattr},
6054 {"synIDtrans", 1, 1, f_synIDtrans},
Bram Moolenaarc0197e22004-09-13 20:26:32 +00006055 {"system", 1, 2, f_system},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006056 {"tempname", 0, 0, f_tempname},
6057 {"tolower", 1, 1, f_tolower},
6058 {"toupper", 1, 1, f_toupper},
Bram Moolenaar8299df92004-07-10 09:47:34 +00006059 {"tr", 3, 3, f_tr},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006060 {"type", 1, 1, f_type},
Bram Moolenaar8c711452005-01-14 21:53:12 +00006061 {"values", 1, 1, f_values},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006062 {"virtcol", 1, 1, f_virtcol},
6063 {"visualmode", 0, 1, f_visualmode},
6064 {"winbufnr", 1, 1, f_winbufnr},
6065 {"wincol", 0, 0, f_wincol},
6066 {"winheight", 1, 1, f_winheight},
6067 {"winline", 0, 0, f_winline},
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00006068 {"winnr", 0, 1, f_winnr},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006069 {"winrestcmd", 0, 0, f_winrestcmd},
6070 {"winwidth", 1, 1, f_winwidth},
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00006071 {"writefile", 2, 3, f_writefile},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006072};
6073
6074#if defined(FEAT_CMDL_COMPL) || defined(PROTO)
6075
6076/*
6077 * Function given to ExpandGeneric() to obtain the list of internal
6078 * or user defined function names.
6079 */
6080 char_u *
6081get_function_name(xp, idx)
6082 expand_T *xp;
6083 int idx;
6084{
6085 static int intidx = -1;
6086 char_u *name;
6087
6088 if (idx == 0)
6089 intidx = -1;
6090 if (intidx < 0)
6091 {
6092 name = get_user_func_name(xp, idx);
6093 if (name != NULL)
6094 return name;
6095 }
6096 if (++intidx < (int)(sizeof(functions) / sizeof(struct fst)))
6097 {
6098 STRCPY(IObuff, functions[intidx].f_name);
6099 STRCAT(IObuff, "(");
6100 if (functions[intidx].f_max_argc == 0)
6101 STRCAT(IObuff, ")");
6102 return IObuff;
6103 }
6104
6105 return NULL;
6106}
6107
6108/*
6109 * Function given to ExpandGeneric() to obtain the list of internal or
6110 * user defined variable or function names.
6111 */
6112/*ARGSUSED*/
6113 char_u *
6114get_expr_name(xp, idx)
6115 expand_T *xp;
6116 int idx;
6117{
6118 static int intidx = -1;
6119 char_u *name;
6120
6121 if (idx == 0)
6122 intidx = -1;
6123 if (intidx < 0)
6124 {
6125 name = get_function_name(xp, idx);
6126 if (name != NULL)
6127 return name;
6128 }
6129 return get_user_var_name(xp, ++intidx);
6130}
6131
6132#endif /* FEAT_CMDL_COMPL */
6133
6134/*
6135 * Find internal function in table above.
6136 * Return index, or -1 if not found
6137 */
6138 static int
6139find_internal_func(name)
6140 char_u *name; /* name of the function */
6141{
6142 int first = 0;
6143 int last = (int)(sizeof(functions) / sizeof(struct fst)) - 1;
6144 int cmp;
6145 int x;
6146
6147 /*
6148 * Find the function name in the table. Binary search.
6149 */
6150 while (first <= last)
6151 {
6152 x = first + ((unsigned)(last - first) >> 1);
6153 cmp = STRCMP(name, functions[x].f_name);
6154 if (cmp < 0)
6155 last = x - 1;
6156 else if (cmp > 0)
6157 first = x + 1;
6158 else
6159 return x;
6160 }
6161 return -1;
6162}
6163
6164/*
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006165 * Check if "name" is a variable of type VAR_FUNC. If so, return the function
6166 * name it contains, otherwise return "name".
6167 */
6168 static char_u *
6169deref_func_name(name, lenp)
6170 char_u *name;
6171 int *lenp;
6172{
Bram Moolenaar33570922005-01-25 22:26:29 +00006173 dictitem_T *v;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006174 int cc;
6175
6176 cc = name[*lenp];
6177 name[*lenp] = NUL;
Bram Moolenaara7043832005-01-21 11:56:39 +00006178 v = find_var(name, NULL);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006179 name[*lenp] = cc;
Bram Moolenaar33570922005-01-25 22:26:29 +00006180 if (v != NULL && v->di_tv.v_type == VAR_FUNC)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006181 {
Bram Moolenaar33570922005-01-25 22:26:29 +00006182 if (v->di_tv.vval.v_string == NULL)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006183 {
6184 *lenp = 0;
6185 return (char_u *)""; /* just in case */
6186 }
Bram Moolenaar33570922005-01-25 22:26:29 +00006187 *lenp = STRLEN(v->di_tv.vval.v_string);
6188 return v->di_tv.vval.v_string;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006189 }
6190
6191 return name;
6192}
6193
6194/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00006195 * Allocate a variable for the result of a function.
6196 * Return OK or FAIL.
6197 */
6198 static int
Bram Moolenaare9a41262005-01-15 22:18:47 +00006199get_func_tv(name, len, rettv, arg, firstline, lastline, doesrange,
6200 evaluate, selfdict)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006201 char_u *name; /* name of the function */
6202 int len; /* length of "name" */
Bram Moolenaar33570922005-01-25 22:26:29 +00006203 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006204 char_u **arg; /* argument, pointing to the '(' */
6205 linenr_T firstline; /* first line of range */
6206 linenr_T lastline; /* last line of range */
6207 int *doesrange; /* return: function handled range */
6208 int evaluate;
Bram Moolenaar33570922005-01-25 22:26:29 +00006209 dict_T *selfdict; /* Dictionary for "self" */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006210{
6211 char_u *argp;
6212 int ret = OK;
Bram Moolenaar33570922005-01-25 22:26:29 +00006213 typval_T argvars[MAX_FUNC_ARGS]; /* vars for arguments */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006214 int argcount = 0; /* number of arguments found */
6215
6216 /*
6217 * Get the arguments.
6218 */
6219 argp = *arg;
6220 while (argcount < MAX_FUNC_ARGS)
6221 {
6222 argp = skipwhite(argp + 1); /* skip the '(' or ',' */
6223 if (*argp == ')' || *argp == ',' || *argp == NUL)
6224 break;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006225 if (eval1(&argp, &argvars[argcount], evaluate) == FAIL)
6226 {
6227 ret = FAIL;
6228 break;
6229 }
6230 ++argcount;
6231 if (*argp != ',')
6232 break;
6233 }
6234 if (*argp == ')')
6235 ++argp;
6236 else
6237 ret = FAIL;
6238
6239 if (ret == OK)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006240 ret = call_func(name, len, rettv, argcount, argvars,
Bram Moolenaare9a41262005-01-15 22:18:47 +00006241 firstline, lastline, doesrange, evaluate, selfdict);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006242 else if (!aborting())
Bram Moolenaar33570922005-01-25 22:26:29 +00006243 {
6244 if (argcount == MAX_FUNC_ARGS)
Bram Moolenaar81bf7082005-02-12 14:31:42 +00006245 emsg_funcname("E740: Too many arguments for function %s", name);
Bram Moolenaar33570922005-01-25 22:26:29 +00006246 else
Bram Moolenaar81bf7082005-02-12 14:31:42 +00006247 emsg_funcname("E116: Invalid arguments for function %s", name);
Bram Moolenaar33570922005-01-25 22:26:29 +00006248 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00006249
6250 while (--argcount >= 0)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006251 clear_tv(&argvars[argcount]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006252
6253 *arg = skipwhite(argp);
6254 return ret;
6255}
6256
6257
6258/*
6259 * Call a function with its resolved parameters
6260 * Return OK or FAIL.
6261 */
6262 static int
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006263call_func(name, len, rettv, argcount, argvars, firstline, lastline,
Bram Moolenaare9a41262005-01-15 22:18:47 +00006264 doesrange, evaluate, selfdict)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006265 char_u *name; /* name of the function */
6266 int len; /* length of "name" */
Bram Moolenaar33570922005-01-25 22:26:29 +00006267 typval_T *rettv; /* return value goes here */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006268 int argcount; /* number of "argvars" */
Bram Moolenaar33570922005-01-25 22:26:29 +00006269 typval_T *argvars; /* vars for arguments */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006270 linenr_T firstline; /* first line of range */
6271 linenr_T lastline; /* last line of range */
6272 int *doesrange; /* return: function handled range */
6273 int evaluate;
Bram Moolenaar33570922005-01-25 22:26:29 +00006274 dict_T *selfdict; /* Dictionary for "self" */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006275{
6276 int ret = FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006277#define ERROR_UNKNOWN 0
6278#define ERROR_TOOMANY 1
6279#define ERROR_TOOFEW 2
6280#define ERROR_SCRIPT 3
Bram Moolenaare9a41262005-01-15 22:18:47 +00006281#define ERROR_DICT 4
6282#define ERROR_NONE 5
6283#define ERROR_OTHER 6
Bram Moolenaar071d4272004-06-13 20:20:40 +00006284 int error = ERROR_NONE;
6285 int i;
6286 int llen;
6287 ufunc_T *fp;
6288 int cc;
6289#define FLEN_FIXED 40
6290 char_u fname_buf[FLEN_FIXED + 1];
6291 char_u *fname;
6292
6293 /*
6294 * In a script change <SID>name() and s:name() to K_SNR 123_name().
6295 * Change <SNR>123_name() to K_SNR 123_name().
6296 * Use fname_buf[] when it fits, otherwise allocate memory (slow).
6297 */
6298 cc = name[len];
6299 name[len] = NUL;
6300 llen = eval_fname_script(name);
6301 if (llen > 0)
6302 {
6303 fname_buf[0] = K_SPECIAL;
6304 fname_buf[1] = KS_EXTRA;
6305 fname_buf[2] = (int)KE_SNR;
6306 i = 3;
6307 if (eval_fname_sid(name)) /* "<SID>" or "s:" */
6308 {
6309 if (current_SID <= 0)
6310 error = ERROR_SCRIPT;
6311 else
6312 {
6313 sprintf((char *)fname_buf + 3, "%ld_", (long)current_SID);
6314 i = (int)STRLEN(fname_buf);
6315 }
6316 }
6317 if (i + STRLEN(name + llen) < FLEN_FIXED)
6318 {
6319 STRCPY(fname_buf + i, name + llen);
6320 fname = fname_buf;
6321 }
6322 else
6323 {
6324 fname = alloc((unsigned)(i + STRLEN(name + llen) + 1));
6325 if (fname == NULL)
6326 error = ERROR_OTHER;
6327 else
6328 {
6329 mch_memmove(fname, fname_buf, (size_t)i);
6330 STRCPY(fname + i, name + llen);
6331 }
6332 }
6333 }
6334 else
6335 fname = name;
6336
6337 *doesrange = FALSE;
6338
6339
6340 /* execute the function if no errors detected and executing */
6341 if (evaluate && error == ERROR_NONE)
6342 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006343 rettv->v_type = VAR_NUMBER; /* default is number rettv */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006344 error = ERROR_UNKNOWN;
6345
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +00006346 if (!builtin_function(fname))
Bram Moolenaar071d4272004-06-13 20:20:40 +00006347 {
6348 /*
6349 * User defined function.
6350 */
6351 fp = find_func(fname);
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +00006352
Bram Moolenaar071d4272004-06-13 20:20:40 +00006353#ifdef FEAT_AUTOCMD
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +00006354 /* Trigger FuncUndefined event, may load the function. */
6355 if (fp == NULL
6356 && apply_autocmds(EVENT_FUNCUNDEFINED,
6357 fname, fname, TRUE, NULL)
6358 && !aborting())
Bram Moolenaar071d4272004-06-13 20:20:40 +00006359 {
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +00006360 /* executed an autocommand, search for the function again */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006361 fp = find_func(fname);
6362 }
6363#endif
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +00006364 /* Try loading a package. */
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00006365 if (fp == NULL && script_autoload(fname) && !aborting())
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +00006366 {
6367 /* loaded a package, search for the function again */
6368 fp = find_func(fname);
6369 }
6370
Bram Moolenaar071d4272004-06-13 20:20:40 +00006371 if (fp != NULL)
6372 {
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00006373 if (fp->uf_flags & FC_RANGE)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006374 *doesrange = TRUE;
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00006375 if (argcount < fp->uf_args.ga_len)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006376 error = ERROR_TOOFEW;
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00006377 else if (!fp->uf_varargs && argcount > fp->uf_args.ga_len)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006378 error = ERROR_TOOMANY;
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00006379 else if ((fp->uf_flags & FC_DICT) && selfdict == NULL)
Bram Moolenaare9a41262005-01-15 22:18:47 +00006380 error = ERROR_DICT;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006381 else
6382 {
6383 /*
6384 * Call the user function.
6385 * Save and restore search patterns, script variables and
6386 * redo buffer.
6387 */
6388 save_search_patterns();
6389 saveRedobuff();
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00006390 ++fp->uf_calls;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006391 call_user_func(fp, argcount, argvars, rettv,
Bram Moolenaare9a41262005-01-15 22:18:47 +00006392 firstline, lastline,
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00006393 (fp->uf_flags & FC_DICT) ? selfdict : NULL);
6394 if (--fp->uf_calls <= 0 && isdigit(*fp->uf_name)
6395 && fp->uf_refcount <= 0)
Bram Moolenaar9ef486d2005-01-17 22:23:00 +00006396 /* Function was unreferenced while being used, free it
6397 * now. */
6398 func_free(fp);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006399 restoreRedobuff();
6400 restore_search_patterns();
6401 error = ERROR_NONE;
6402 }
6403 }
6404 }
6405 else
6406 {
6407 /*
6408 * Find the function name in the table, call its implementation.
6409 */
6410 i = find_internal_func(fname);
6411 if (i >= 0)
6412 {
6413 if (argcount < functions[i].f_min_argc)
6414 error = ERROR_TOOFEW;
6415 else if (argcount > functions[i].f_max_argc)
6416 error = ERROR_TOOMANY;
6417 else
6418 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006419 argvars[argcount].v_type = VAR_UNKNOWN;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006420 functions[i].f_func(argvars, rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006421 error = ERROR_NONE;
6422 }
6423 }
6424 }
6425 /*
6426 * The function call (or "FuncUndefined" autocommand sequence) might
6427 * have been aborted by an error, an interrupt, or an explicitly thrown
6428 * exception that has not been caught so far. This situation can be
6429 * tested for by calling aborting(). For an error in an internal
6430 * function or for the "E132" error in call_user_func(), however, the
6431 * throw point at which the "force_abort" flag (temporarily reset by
6432 * emsg()) is normally updated has not been reached yet. We need to
6433 * update that flag first to make aborting() reliable.
6434 */
6435 update_force_abort();
6436 }
6437 if (error == ERROR_NONE)
6438 ret = OK;
6439
6440 /*
6441 * Report an error unless the argument evaluation or function call has been
6442 * cancelled due to an aborting error, an interrupt, or an exception.
6443 */
Bram Moolenaar8c711452005-01-14 21:53:12 +00006444 if (!aborting())
6445 {
6446 switch (error)
6447 {
6448 case ERROR_UNKNOWN:
Bram Moolenaar81bf7082005-02-12 14:31:42 +00006449 emsg_funcname("E117: Unknown function: %s", name);
Bram Moolenaar8c711452005-01-14 21:53:12 +00006450 break;
6451 case ERROR_TOOMANY:
Bram Moolenaar81bf7082005-02-12 14:31:42 +00006452 emsg_funcname(e_toomanyarg, name);
Bram Moolenaar8c711452005-01-14 21:53:12 +00006453 break;
6454 case ERROR_TOOFEW:
Bram Moolenaar81bf7082005-02-12 14:31:42 +00006455 emsg_funcname("E119: Not enough arguments for function: %s",
Bram Moolenaar8c711452005-01-14 21:53:12 +00006456 name);
6457 break;
6458 case ERROR_SCRIPT:
Bram Moolenaar81bf7082005-02-12 14:31:42 +00006459 emsg_funcname("E120: Using <SID> not in a script context: %s",
Bram Moolenaar8c711452005-01-14 21:53:12 +00006460 name);
6461 break;
Bram Moolenaare9a41262005-01-15 22:18:47 +00006462 case ERROR_DICT:
Bram Moolenaar81bf7082005-02-12 14:31:42 +00006463 emsg_funcname("E725: Calling dict function without Dictionary: %s",
Bram Moolenaare9a41262005-01-15 22:18:47 +00006464 name);
6465 break;
Bram Moolenaar8c711452005-01-14 21:53:12 +00006466 }
6467 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00006468
6469 name[len] = cc;
6470 if (fname != name && fname != fname_buf)
6471 vim_free(fname);
6472
6473 return ret;
6474}
6475
Bram Moolenaar81bf7082005-02-12 14:31:42 +00006476/*
6477 * Give an error message with a function name. Handle <SNR> things.
6478 */
6479 static void
6480emsg_funcname(msg, name)
6481 char *msg;
6482 char_u *name;
6483{
6484 char_u *p;
6485
6486 if (*name == K_SPECIAL)
6487 p = concat_str((char_u *)"<SNR>", name + 3);
6488 else
6489 p = name;
6490 EMSG2(_(msg), p);
6491 if (p != name)
6492 vim_free(p);
6493}
6494
Bram Moolenaar071d4272004-06-13 20:20:40 +00006495/*********************************************
6496 * Implementation of the built-in functions
6497 */
6498
6499/*
Bram Moolenaar0d660222005-01-07 21:51:51 +00006500 * "add(list, item)" function
Bram Moolenaar071d4272004-06-13 20:20:40 +00006501 */
6502 static void
Bram Moolenaar0d660222005-01-07 21:51:51 +00006503f_add(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00006504 typval_T *argvars;
6505 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006506{
Bram Moolenaar33570922005-01-25 22:26:29 +00006507 list_T *l;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006508
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006509 rettv->vval.v_number = 1; /* Default: Failed */
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006510 if (argvars[0].v_type == VAR_LIST)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006511 {
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00006512 if ((l = argvars[0].vval.v_list) != NULL
6513 && !tv_check_lock(l->lv_lock, (char_u *)"add()")
6514 && list_append_tv(l, &argvars[1]) == OK)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006515 copy_tv(&argvars[0], rettv);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006516 }
6517 else
Bram Moolenaar0d660222005-01-07 21:51:51 +00006518 EMSG(_(e_listreq));
6519}
6520
6521/*
6522 * "append(lnum, string/list)" function
6523 */
6524 static void
6525f_append(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00006526 typval_T *argvars;
6527 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +00006528{
6529 long lnum;
Bram Moolenaar33570922005-01-25 22:26:29 +00006530 list_T *l = NULL;
6531 listitem_T *li = NULL;
6532 typval_T *tv;
Bram Moolenaar0d660222005-01-07 21:51:51 +00006533 long added = 0;
6534
6535 rettv->vval.v_number = 1; /* Default: Failed */
6536 lnum = get_tv_lnum(argvars);
6537 if (lnum >= 0
6538 && lnum <= curbuf->b_ml.ml_line_count
6539 && u_save(lnum, lnum + 1) == OK)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006540 {
Bram Moolenaar0d660222005-01-07 21:51:51 +00006541 if (argvars[1].v_type == VAR_LIST)
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006542 {
Bram Moolenaar0d660222005-01-07 21:51:51 +00006543 l = argvars[1].vval.v_list;
6544 if (l == NULL)
6545 return;
6546 li = l->lv_first;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006547 }
Bram Moolenaar0d660222005-01-07 21:51:51 +00006548 for (;;)
6549 {
6550 if (l == NULL)
6551 tv = &argvars[1]; /* append a string */
6552 else if (li == NULL)
6553 break; /* end of list */
6554 else
6555 tv = &li->li_tv; /* append item from list */
6556 ml_append(lnum + added, get_tv_string(tv), (colnr_T)0, FALSE);
6557 ++added;
6558 if (l == NULL)
6559 break;
6560 li = li->li_next;
6561 }
6562
6563 appended_lines_mark(lnum, added);
6564 if (curwin->w_cursor.lnum > lnum)
6565 curwin->w_cursor.lnum += added;
6566 rettv->vval.v_number = 0; /* Success */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006567 }
6568}
6569
6570/*
6571 * "argc()" function
6572 */
6573/* ARGSUSED */
6574 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006575f_argc(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00006576 typval_T *argvars;
6577 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006578{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006579 rettv->vval.v_number = ARGCOUNT;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006580}
6581
6582/*
6583 * "argidx()" function
6584 */
6585/* ARGSUSED */
6586 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006587f_argidx(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00006588 typval_T *argvars;
6589 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006590{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006591 rettv->vval.v_number = curwin->w_arg_idx;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006592}
6593
6594/*
6595 * "argv(nr)" function
6596 */
6597 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006598f_argv(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00006599 typval_T *argvars;
6600 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006601{
6602 int idx;
6603
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006604 idx = get_tv_number(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006605 if (idx >= 0 && idx < ARGCOUNT)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006606 rettv->vval.v_string = vim_strsave(alist_name(&ARGLIST[idx]));
Bram Moolenaar071d4272004-06-13 20:20:40 +00006607 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006608 rettv->vval.v_string = NULL;
6609 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006610}
6611
6612/*
6613 * "browse(save, title, initdir, default)" function
6614 */
6615/* ARGSUSED */
6616 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006617f_browse(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00006618 typval_T *argvars;
6619 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006620{
6621#ifdef FEAT_BROWSE
6622 int save;
6623 char_u *title;
6624 char_u *initdir;
6625 char_u *defname;
6626 char_u buf[NUMBUFLEN];
6627 char_u buf2[NUMBUFLEN];
6628
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006629 save = get_tv_number(&argvars[0]);
6630 title = get_tv_string(&argvars[1]);
6631 initdir = get_tv_string_buf(&argvars[2], buf);
6632 defname = get_tv_string_buf(&argvars[3], buf2);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006633
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006634 rettv->vval.v_string =
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00006635 do_browse(save ? BROWSE_SAVE : 0,
6636 title, defname, NULL, initdir, NULL, curbuf);
6637#else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006638 rettv->vval.v_string = NULL;
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00006639#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006640 rettv->v_type = VAR_STRING;
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00006641}
6642
6643/*
6644 * "browsedir(title, initdir)" function
6645 */
6646/* ARGSUSED */
6647 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006648f_browsedir(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00006649 typval_T *argvars;
6650 typval_T *rettv;
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00006651{
6652#ifdef FEAT_BROWSE
6653 char_u *title;
6654 char_u *initdir;
6655 char_u buf[NUMBUFLEN];
6656
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006657 title = get_tv_string(&argvars[0]);
6658 initdir = get_tv_string_buf(&argvars[1], buf);
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00006659
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006660 rettv->vval.v_string = do_browse(BROWSE_DIR,
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00006661 title, NULL, NULL, initdir, NULL, curbuf);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006662#else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006663 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006664#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006665 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006666}
6667
Bram Moolenaar33570922005-01-25 22:26:29 +00006668static buf_T *find_buffer __ARGS((typval_T *avar));
Bram Moolenaar0d660222005-01-07 21:51:51 +00006669
Bram Moolenaar071d4272004-06-13 20:20:40 +00006670/*
6671 * Find a buffer by number or exact name.
6672 */
6673 static buf_T *
6674find_buffer(avar)
Bram Moolenaar33570922005-01-25 22:26:29 +00006675 typval_T *avar;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006676{
6677 buf_T *buf = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006678
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006679 if (avar->v_type == VAR_NUMBER)
6680 buf = buflist_findnr((int)avar->vval.v_number);
Bram Moolenaar758711c2005-02-02 23:11:38 +00006681 else if (avar->v_type == VAR_STRING && avar->vval.v_string != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006682 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006683 buf = buflist_findname_exp(avar->vval.v_string);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006684 if (buf == NULL)
6685 {
6686 /* No full path name match, try a match with a URL or a "nofile"
6687 * buffer, these don't use the full path. */
6688 for (buf = firstbuf; buf != NULL; buf = buf->b_next)
6689 if (buf->b_fname != NULL
6690 && (path_with_url(buf->b_fname)
6691#ifdef FEAT_QUICKFIX
6692 || bt_nofile(buf)
6693#endif
6694 )
Bram Moolenaar49cd9572005-01-03 21:06:01 +00006695 && STRCMP(buf->b_fname, avar->vval.v_string) == 0)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006696 break;
6697 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00006698 }
6699 return buf;
6700}
6701
6702/*
6703 * "bufexists(expr)" function
6704 */
6705 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006706f_bufexists(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00006707 typval_T *argvars;
6708 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006709{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006710 rettv->vval.v_number = (find_buffer(&argvars[0]) != NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006711}
6712
6713/*
6714 * "buflisted(expr)" function
6715 */
6716 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006717f_buflisted(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00006718 typval_T *argvars;
6719 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006720{
6721 buf_T *buf;
6722
6723 buf = find_buffer(&argvars[0]);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006724 rettv->vval.v_number = (buf != NULL && buf->b_p_bl);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006725}
6726
6727/*
6728 * "bufloaded(expr)" function
6729 */
6730 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006731f_bufloaded(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00006732 typval_T *argvars;
6733 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006734{
6735 buf_T *buf;
6736
6737 buf = find_buffer(&argvars[0]);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006738 rettv->vval.v_number = (buf != NULL && buf->b_ml.ml_mfp != NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006739}
6740
Bram Moolenaar33570922005-01-25 22:26:29 +00006741static buf_T *get_buf_tv __ARGS((typval_T *tv));
Bram Moolenaar0d660222005-01-07 21:51:51 +00006742
Bram Moolenaar071d4272004-06-13 20:20:40 +00006743/*
6744 * Get buffer by number or pattern.
6745 */
6746 static buf_T *
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006747get_buf_tv(tv)
Bram Moolenaar33570922005-01-25 22:26:29 +00006748 typval_T *tv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006749{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006750 char_u *name = tv->vval.v_string;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006751 int save_magic;
6752 char_u *save_cpo;
6753 buf_T *buf;
6754
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006755 if (tv->v_type == VAR_NUMBER)
6756 return buflist_findnr((int)tv->vval.v_number);
Bram Moolenaar758711c2005-02-02 23:11:38 +00006757 if (tv->v_type != VAR_STRING)
6758 return NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006759 if (name == NULL || *name == NUL)
6760 return curbuf;
6761 if (name[0] == '$' && name[1] == NUL)
6762 return lastbuf;
6763
6764 /* Ignore 'magic' and 'cpoptions' here to make scripts portable */
6765 save_magic = p_magic;
6766 p_magic = TRUE;
6767 save_cpo = p_cpo;
6768 p_cpo = (char_u *)"";
6769
6770 buf = buflist_findnr(buflist_findpat(name, name + STRLEN(name),
6771 TRUE, FALSE));
6772
6773 p_magic = save_magic;
6774 p_cpo = save_cpo;
6775
6776 /* If not found, try expanding the name, like done for bufexists(). */
6777 if (buf == NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006778 buf = find_buffer(tv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006779
6780 return buf;
6781}
6782
6783/*
6784 * "bufname(expr)" function
6785 */
6786 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006787f_bufname(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00006788 typval_T *argvars;
6789 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006790{
6791 buf_T *buf;
6792
6793 ++emsg_off;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006794 buf = get_buf_tv(&argvars[0]);
6795 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006796 if (buf != NULL && buf->b_fname != NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006797 rettv->vval.v_string = vim_strsave(buf->b_fname);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006798 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006799 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006800 --emsg_off;
6801}
6802
6803/*
6804 * "bufnr(expr)" function
6805 */
6806 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006807f_bufnr(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00006808 typval_T *argvars;
6809 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006810{
6811 buf_T *buf;
6812
6813 ++emsg_off;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006814 buf = get_buf_tv(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006815 if (buf != NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006816 rettv->vval.v_number = buf->b_fnum;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006817 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006818 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006819 --emsg_off;
6820}
6821
6822/*
6823 * "bufwinnr(nr)" function
6824 */
6825 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006826f_bufwinnr(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00006827 typval_T *argvars;
6828 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006829{
6830#ifdef FEAT_WINDOWS
6831 win_T *wp;
6832 int winnr = 0;
6833#endif
6834 buf_T *buf;
6835
6836 ++emsg_off;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006837 buf = get_buf_tv(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006838#ifdef FEAT_WINDOWS
6839 for (wp = firstwin; wp; wp = wp->w_next)
6840 {
6841 ++winnr;
6842 if (wp->w_buffer == buf)
6843 break;
6844 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006845 rettv->vval.v_number = (wp != NULL ? winnr : -1);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006846#else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006847 rettv->vval.v_number = (curwin->w_buffer == buf ? 1 : -1);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006848#endif
6849 --emsg_off;
6850}
6851
6852/*
6853 * "byte2line(byte)" function
6854 */
6855/*ARGSUSED*/
6856 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006857f_byte2line(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00006858 typval_T *argvars;
6859 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006860{
6861#ifndef FEAT_BYTEOFF
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006862 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006863#else
6864 long boff = 0;
6865
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006866 boff = get_tv_number(&argvars[0]) - 1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006867 if (boff < 0)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006868 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006869 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006870 rettv->vval.v_number = ml_find_line_or_offset(curbuf,
Bram Moolenaar071d4272004-06-13 20:20:40 +00006871 (linenr_T)0, &boff);
6872#endif
6873}
6874
6875/*
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00006876 * "byteidx()" function
6877 */
6878/*ARGSUSED*/
6879 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006880f_byteidx(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00006881 typval_T *argvars;
6882 typval_T *rettv;
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00006883{
6884#ifdef FEAT_MBYTE
6885 char_u *t;
6886#endif
6887 char_u *str;
6888 long idx;
6889
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006890 str = get_tv_string(&argvars[0]);
6891 idx = get_tv_number(&argvars[1]);
6892 rettv->vval.v_number = -1;
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00006893 if (idx < 0)
6894 return;
6895
6896#ifdef FEAT_MBYTE
6897 t = str;
6898 for ( ; idx > 0; idx--)
6899 {
6900 if (*t == NUL) /* EOL reached */
6901 return;
6902 t += mb_ptr2len_check(t);
6903 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006904 rettv->vval.v_number = t - str;
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00006905#else
6906 if (idx <= STRLEN(str))
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006907 rettv->vval.v_number = idx;
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00006908#endif
6909}
6910
6911/*
Bram Moolenaar8a283e52005-01-06 23:28:25 +00006912 * "call(func, arglist)" function
6913 */
6914 static void
6915f_call(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00006916 typval_T *argvars;
6917 typval_T *rettv;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00006918{
6919 char_u *func;
Bram Moolenaar33570922005-01-25 22:26:29 +00006920 typval_T argv[MAX_FUNC_ARGS];
Bram Moolenaar8a283e52005-01-06 23:28:25 +00006921 int argc = 0;
Bram Moolenaar33570922005-01-25 22:26:29 +00006922 listitem_T *item;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00006923 int dummy;
Bram Moolenaar33570922005-01-25 22:26:29 +00006924 dict_T *selfdict = NULL;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00006925
6926 rettv->vval.v_number = 0;
6927 if (argvars[1].v_type != VAR_LIST)
6928 {
6929 EMSG(_(e_listreq));
6930 return;
6931 }
6932 if (argvars[1].vval.v_list == NULL)
6933 return;
6934
6935 if (argvars[0].v_type == VAR_FUNC)
6936 func = argvars[0].vval.v_string;
6937 else
6938 func = get_tv_string(&argvars[0]);
6939
Bram Moolenaare9a41262005-01-15 22:18:47 +00006940 if (argvars[2].v_type != VAR_UNKNOWN)
6941 {
6942 if (argvars[2].v_type != VAR_DICT)
6943 {
6944 EMSG(_(e_dictreq));
6945 return;
6946 }
6947 selfdict = argvars[2].vval.v_dict;
6948 }
6949
Bram Moolenaar8a283e52005-01-06 23:28:25 +00006950 for (item = argvars[1].vval.v_list->lv_first; item != NULL;
6951 item = item->li_next)
6952 {
6953 if (argc == MAX_FUNC_ARGS)
6954 {
Bram Moolenaare49b69a2005-01-08 16:11:57 +00006955 EMSG(_("E699: Too many arguments"));
Bram Moolenaar8a283e52005-01-06 23:28:25 +00006956 break;
6957 }
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00006958 /* Make a copy of each argument. This is needed to be able to set
6959 * v_lock to VAR_FIXED in the copy without changing the original list.
6960 */
Bram Moolenaar8a283e52005-01-06 23:28:25 +00006961 copy_tv(&item->li_tv, &argv[argc++]);
6962 }
6963
6964 if (item == NULL)
6965 (void)call_func(func, STRLEN(func), rettv, argc, argv,
Bram Moolenaare9a41262005-01-15 22:18:47 +00006966 curwin->w_cursor.lnum, curwin->w_cursor.lnum,
6967 &dummy, TRUE, selfdict);
Bram Moolenaar8a283e52005-01-06 23:28:25 +00006968
6969 /* Free the arguments. */
6970 while (argc > 0)
6971 clear_tv(&argv[--argc]);
6972}
6973
6974/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00006975 * "char2nr(string)" function
6976 */
6977 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006978f_char2nr(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00006979 typval_T *argvars;
6980 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006981{
6982#ifdef FEAT_MBYTE
6983 if (has_mbyte)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006984 rettv->vval.v_number =
6985 (*mb_ptr2char)(get_tv_string(&argvars[0]));
Bram Moolenaar071d4272004-06-13 20:20:40 +00006986 else
6987#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006988 rettv->vval.v_number = get_tv_string(&argvars[0])[0];
Bram Moolenaar071d4272004-06-13 20:20:40 +00006989}
6990
6991/*
6992 * "cindent(lnum)" function
6993 */
6994 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00006995f_cindent(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00006996 typval_T *argvars;
6997 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006998{
6999#ifdef FEAT_CINDENT
7000 pos_T pos;
7001 linenr_T lnum;
7002
7003 pos = curwin->w_cursor;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007004 lnum = get_tv_lnum(argvars);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007005 if (lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count)
7006 {
7007 curwin->w_cursor.lnum = lnum;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007008 rettv->vval.v_number = get_c_indent();
Bram Moolenaar071d4272004-06-13 20:20:40 +00007009 curwin->w_cursor = pos;
7010 }
7011 else
7012#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007013 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007014}
7015
7016/*
7017 * "col(string)" function
7018 */
7019 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007020f_col(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007021 typval_T *argvars;
7022 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007023{
7024 colnr_T col = 0;
7025 pos_T *fp;
7026
7027 fp = var2fpos(&argvars[0], FALSE);
7028 if (fp != NULL)
7029 {
7030 if (fp->col == MAXCOL)
7031 {
7032 /* '> can be MAXCOL, get the length of the line then */
7033 if (fp->lnum <= curbuf->b_ml.ml_line_count)
7034 col = STRLEN(ml_get(fp->lnum)) + 1;
7035 else
7036 col = MAXCOL;
7037 }
7038 else
7039 {
7040 col = fp->col + 1;
7041#ifdef FEAT_VIRTUALEDIT
7042 /* col(".") when the cursor is on the NUL at the end of the line
7043 * because of "coladd" can be seen as an extra column. */
7044 if (virtual_active() && fp == &curwin->w_cursor)
7045 {
7046 char_u *p = ml_get_cursor();
7047
7048 if (curwin->w_cursor.coladd >= (colnr_T)chartabsize(p,
7049 curwin->w_virtcol - curwin->w_cursor.coladd))
7050 {
7051# ifdef FEAT_MBYTE
7052 int l;
7053
7054 if (*p != NUL && p[(l = (*mb_ptr2len_check)(p))] == NUL)
7055 col += l;
7056# else
7057 if (*p != NUL && p[1] == NUL)
7058 ++col;
7059# endif
7060 }
7061 }
7062#endif
7063 }
7064 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007065 rettv->vval.v_number = col;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007066}
7067
7068/*
7069 * "confirm(message, buttons[, default [, type]])" function
7070 */
7071/*ARGSUSED*/
7072 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007073f_confirm(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007074 typval_T *argvars;
7075 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007076{
7077#if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
7078 char_u *message;
7079 char_u *buttons = NULL;
7080 char_u buf[NUMBUFLEN];
7081 char_u buf2[NUMBUFLEN];
7082 int def = 1;
7083 int type = VIM_GENERIC;
7084 int c;
7085
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007086 message = get_tv_string(&argvars[0]);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007087 if (argvars[1].v_type != VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007088 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007089 buttons = get_tv_string_buf(&argvars[1], buf);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007090 if (argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007091 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007092 def = get_tv_number(&argvars[2]);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007093 if (argvars[3].v_type != VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007094 {
Bram Moolenaara7043832005-01-21 11:56:39 +00007095 /* avoid that TOUPPER_ASC calls get_tv_string_buf() twice */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007096 c = *get_tv_string_buf(&argvars[3], buf2);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007097 switch (TOUPPER_ASC(c))
7098 {
7099 case 'E': type = VIM_ERROR; break;
7100 case 'Q': type = VIM_QUESTION; break;
7101 case 'I': type = VIM_INFO; break;
7102 case 'W': type = VIM_WARNING; break;
7103 case 'G': type = VIM_GENERIC; break;
7104 }
7105 }
7106 }
7107 }
7108
7109 if (buttons == NULL || *buttons == NUL)
7110 buttons = (char_u *)_("&Ok");
7111
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007112 rettv->vval.v_number = do_dialog(type, NULL, message, buttons,
Bram Moolenaar071d4272004-06-13 20:20:40 +00007113 def, NULL);
7114#else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007115 rettv->vval.v_number = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007116#endif
7117}
7118
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007119/*
7120 * "copy()" function
7121 */
7122 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007123f_copy(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007124 typval_T *argvars;
7125 typval_T *rettv;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007126{
Bram Moolenaar81bf7082005-02-12 14:31:42 +00007127 item_copy(&argvars[0], rettv, FALSE, 0);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007128}
Bram Moolenaar071d4272004-06-13 20:20:40 +00007129
7130/*
Bram Moolenaar8a283e52005-01-06 23:28:25 +00007131 * "count()" function
7132 */
7133 static void
7134f_count(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007135 typval_T *argvars;
7136 typval_T *rettv;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00007137{
Bram Moolenaar8a283e52005-01-06 23:28:25 +00007138 long n = 0;
7139 int ic = FALSE;
7140
Bram Moolenaare9a41262005-01-15 22:18:47 +00007141 if (argvars[0].v_type == VAR_LIST)
Bram Moolenaar8a283e52005-01-06 23:28:25 +00007142 {
Bram Moolenaar33570922005-01-25 22:26:29 +00007143 listitem_T *li;
7144 list_T *l;
Bram Moolenaare9a41262005-01-15 22:18:47 +00007145 long idx;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00007146
Bram Moolenaare9a41262005-01-15 22:18:47 +00007147 if ((l = argvars[0].vval.v_list) != NULL)
7148 {
7149 li = l->lv_first;
7150 if (argvars[2].v_type != VAR_UNKNOWN)
7151 {
7152 ic = get_tv_number(&argvars[2]);
7153 if (argvars[3].v_type != VAR_UNKNOWN)
7154 {
7155 idx = get_tv_number(&argvars[3]);
7156 li = list_find(l, idx);
7157 if (li == NULL)
7158 EMSGN(_(e_listidx), idx);
7159 }
7160 }
7161
7162 for ( ; li != NULL; li = li->li_next)
7163 if (tv_equal(&li->li_tv, &argvars[1], ic))
7164 ++n;
7165 }
Bram Moolenaar8a283e52005-01-06 23:28:25 +00007166 }
Bram Moolenaare9a41262005-01-15 22:18:47 +00007167 else if (argvars[0].v_type == VAR_DICT)
7168 {
Bram Moolenaar33570922005-01-25 22:26:29 +00007169 int todo;
7170 dict_T *d;
7171 hashitem_T *hi;
Bram Moolenaare9a41262005-01-15 22:18:47 +00007172
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00007173 if ((d = argvars[0].vval.v_dict) != NULL)
7174 {
Bram Moolenaare9a41262005-01-15 22:18:47 +00007175 if (argvars[2].v_type != VAR_UNKNOWN)
7176 {
7177 ic = get_tv_number(&argvars[2]);
7178 if (argvars[3].v_type != VAR_UNKNOWN)
7179 EMSG(_(e_invarg));
7180 }
7181
Bram Moolenaar33570922005-01-25 22:26:29 +00007182 todo = d->dv_hashtab.ht_used;
7183 for (hi = d->dv_hashtab.ht_array; todo > 0; ++hi)
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00007184 {
7185 if (!HASHITEM_EMPTY(hi))
7186 {
7187 --todo;
7188 if (tv_equal(&HI2DI(hi)->di_tv, &argvars[1], ic))
7189 ++n;
7190 }
7191 }
Bram Moolenaare9a41262005-01-15 22:18:47 +00007192 }
7193 }
7194 else
7195 EMSG2(_(e_listdictarg), "count()");
Bram Moolenaar8a283e52005-01-06 23:28:25 +00007196 rettv->vval.v_number = n;
7197}
7198
7199/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00007200 * "cscope_connection([{num} , {dbpath} [, {prepend}]])" function
7201 *
7202 * Checks the existence of a cscope connection.
7203 */
7204/*ARGSUSED*/
7205 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007206f_cscope_connection(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007207 typval_T *argvars;
7208 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007209{
7210#ifdef FEAT_CSCOPE
7211 int num = 0;
7212 char_u *dbpath = NULL;
7213 char_u *prepend = NULL;
7214 char_u buf[NUMBUFLEN];
7215
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007216 if (argvars[0].v_type != VAR_UNKNOWN
7217 && argvars[1].v_type != VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007218 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007219 num = (int)get_tv_number(&argvars[0]);
7220 dbpath = get_tv_string(&argvars[1]);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007221 if (argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007222 prepend = get_tv_string_buf(&argvars[2], buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007223 }
7224
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007225 rettv->vval.v_number = cs_connection(num, dbpath, prepend);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007226#else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007227 rettv->vval.v_number = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007228#endif
7229}
7230
7231/*
7232 * "cursor(lnum, col)" function
7233 *
7234 * Moves the cursor to the specified line and column
7235 */
7236/*ARGSUSED*/
7237 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007238f_cursor(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007239 typval_T *argvars;
7240 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007241{
7242 long line, col;
7243
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007244 line = get_tv_lnum(argvars);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007245 if (line > 0)
7246 curwin->w_cursor.lnum = line;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007247 col = get_tv_number(&argvars[1]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007248 if (col > 0)
7249 curwin->w_cursor.col = col - 1;
7250#ifdef FEAT_VIRTUALEDIT
7251 curwin->w_cursor.coladd = 0;
7252#endif
7253
7254 /* Make sure the cursor is in a valid position. */
7255 check_cursor();
7256#ifdef FEAT_MBYTE
7257 /* Correct cursor for multi-byte character. */
7258 if (has_mbyte)
7259 mb_adjust_cursor();
7260#endif
Bram Moolenaarf4b8e572004-06-24 15:53:16 +00007261
7262 curwin->w_set_curswant = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007263}
7264
7265/*
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007266 * "deepcopy()" function
Bram Moolenaar071d4272004-06-13 20:20:40 +00007267 */
7268 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007269f_deepcopy(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007270 typval_T *argvars;
7271 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007272{
Bram Moolenaar81bf7082005-02-12 14:31:42 +00007273 static int copyID = 0;
7274 int noref = 0;
7275
7276 if (argvars[1].v_type != VAR_UNKNOWN)
7277 noref = get_tv_number(&argvars[1]);
7278 if (noref < 0 || noref > 1)
7279 EMSG(_(e_invarg));
7280 else
7281 item_copy(&argvars[0], rettv, TRUE, noref == 0 ? ++copyID : 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007282}
7283
7284/*
7285 * "delete()" function
7286 */
7287 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007288f_delete(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007289 typval_T *argvars;
7290 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007291{
7292 if (check_restricted() || check_secure())
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007293 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007294 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007295 rettv->vval.v_number = mch_remove(get_tv_string(&argvars[0]));
Bram Moolenaar071d4272004-06-13 20:20:40 +00007296}
7297
7298/*
7299 * "did_filetype()" function
7300 */
7301/*ARGSUSED*/
7302 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007303f_did_filetype(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007304 typval_T *argvars;
7305 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007306{
7307#ifdef FEAT_AUTOCMD
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007308 rettv->vval.v_number = did_filetype;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007309#else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007310 rettv->vval.v_number = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007311#endif
7312}
7313
7314/*
Bram Moolenaar47136d72004-10-12 20:02:24 +00007315 * "diff_filler()" function
7316 */
7317/*ARGSUSED*/
7318 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007319f_diff_filler(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007320 typval_T *argvars;
7321 typval_T *rettv;
Bram Moolenaar47136d72004-10-12 20:02:24 +00007322{
7323#ifdef FEAT_DIFF
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007324 rettv->vval.v_number = diff_check_fill(curwin, get_tv_lnum(argvars));
Bram Moolenaar47136d72004-10-12 20:02:24 +00007325#endif
7326}
7327
7328/*
7329 * "diff_hlID()" function
7330 */
7331/*ARGSUSED*/
7332 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007333f_diff_hlID(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007334 typval_T *argvars;
7335 typval_T *rettv;
Bram Moolenaar47136d72004-10-12 20:02:24 +00007336{
7337#ifdef FEAT_DIFF
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007338 linenr_T lnum = get_tv_lnum(argvars);
Bram Moolenaar47136d72004-10-12 20:02:24 +00007339 static linenr_T prev_lnum = 0;
7340 static int changedtick = 0;
7341 static int fnum = 0;
7342 static int change_start = 0;
7343 static int change_end = 0;
7344 static enum hlf_value hlID = 0;
7345 int filler_lines;
7346 int col;
7347
7348 if (lnum != prev_lnum
7349 || changedtick != curbuf->b_changedtick
7350 || fnum != curbuf->b_fnum)
7351 {
7352 /* New line, buffer, change: need to get the values. */
7353 filler_lines = diff_check(curwin, lnum);
7354 if (filler_lines < 0)
7355 {
7356 if (filler_lines == -1)
7357 {
7358 change_start = MAXCOL;
7359 change_end = -1;
7360 if (diff_find_change(curwin, lnum, &change_start, &change_end))
7361 hlID = HLF_ADD; /* added line */
7362 else
7363 hlID = HLF_CHD; /* changed line */
7364 }
7365 else
7366 hlID = HLF_ADD; /* added line */
7367 }
7368 else
7369 hlID = (enum hlf_value)0;
7370 prev_lnum = lnum;
7371 changedtick = curbuf->b_changedtick;
7372 fnum = curbuf->b_fnum;
7373 }
7374
7375 if (hlID == HLF_CHD || hlID == HLF_TXD)
7376 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007377 col = get_tv_number(&argvars[1]) - 1;
Bram Moolenaar47136d72004-10-12 20:02:24 +00007378 if (col >= change_start && col <= change_end)
7379 hlID = HLF_TXD; /* changed text */
7380 else
7381 hlID = HLF_CHD; /* changed line */
7382 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007383 rettv->vval.v_number = hlID == (enum hlf_value)0 ? 0 : (int)hlID;
Bram Moolenaar47136d72004-10-12 20:02:24 +00007384#endif
7385}
7386
7387/*
Bram Moolenaare49b69a2005-01-08 16:11:57 +00007388 * "empty({expr})" function
7389 */
7390 static void
7391f_empty(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007392 typval_T *argvars;
7393 typval_T *rettv;
Bram Moolenaare49b69a2005-01-08 16:11:57 +00007394{
7395 int n;
7396
7397 switch (argvars[0].v_type)
7398 {
7399 case VAR_STRING:
7400 case VAR_FUNC:
7401 n = argvars[0].vval.v_string == NULL
7402 || *argvars[0].vval.v_string == NUL;
7403 break;
7404 case VAR_NUMBER:
7405 n = argvars[0].vval.v_number == 0;
7406 break;
7407 case VAR_LIST:
7408 n = argvars[0].vval.v_list == NULL
7409 || argvars[0].vval.v_list->lv_first == NULL;
7410 break;
Bram Moolenaare9a41262005-01-15 22:18:47 +00007411 case VAR_DICT:
7412 n = argvars[0].vval.v_dict == NULL
Bram Moolenaar33570922005-01-25 22:26:29 +00007413 || argvars[0].vval.v_dict->dv_hashtab.ht_used == 0;
Bram Moolenaare9a41262005-01-15 22:18:47 +00007414 break;
Bram Moolenaare49b69a2005-01-08 16:11:57 +00007415 default:
7416 EMSG2(_(e_intern2), "f_empty()");
7417 n = 0;
7418 }
7419
7420 rettv->vval.v_number = n;
7421}
7422
7423/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00007424 * "escape({string}, {chars})" function
7425 */
7426 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007427f_escape(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007428 typval_T *argvars;
7429 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007430{
7431 char_u buf[NUMBUFLEN];
7432
Bram Moolenaar758711c2005-02-02 23:11:38 +00007433 rettv->vval.v_string = vim_strsave_escaped(get_tv_string(&argvars[0]),
7434 get_tv_string_buf(&argvars[1], buf));
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007435 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007436}
7437
7438/*
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00007439 * "eval()" function
7440 */
7441/*ARGSUSED*/
7442 static void
7443f_eval(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007444 typval_T *argvars;
7445 typval_T *rettv;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00007446{
7447 char_u *s;
7448
7449 s = get_tv_string(&argvars[0]);
7450 s = skipwhite(s);
7451
7452 if (eval1(&s, rettv, TRUE) == FAIL)
7453 rettv->vval.v_number = 0;
7454 else if (*s != NUL)
7455 EMSG(_(e_trailing));
7456}
7457
7458/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00007459 * "eventhandler()" function
7460 */
7461/*ARGSUSED*/
7462 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007463f_eventhandler(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007464 typval_T *argvars;
7465 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007466{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007467 rettv->vval.v_number = vgetc_busy;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007468}
7469
7470/*
7471 * "executable()" function
7472 */
7473 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007474f_executable(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007475 typval_T *argvars;
7476 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007477{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007478 rettv->vval.v_number = mch_can_exe(get_tv_string(&argvars[0]));
Bram Moolenaar071d4272004-06-13 20:20:40 +00007479}
7480
7481/*
7482 * "exists()" function
7483 */
7484 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007485f_exists(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007486 typval_T *argvars;
7487 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007488{
7489 char_u *p;
7490 char_u *name;
7491 int n = FALSE;
7492 int len = 0;
7493
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007494 p = get_tv_string(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007495 if (*p == '$') /* environment variable */
7496 {
7497 /* first try "normal" environment variables (fast) */
7498 if (mch_getenv(p + 1) != NULL)
7499 n = TRUE;
7500 else
7501 {
7502 /* try expanding things like $VIM and ${HOME} */
7503 p = expand_env_save(p);
7504 if (p != NULL && *p != '$')
7505 n = TRUE;
7506 vim_free(p);
7507 }
7508 }
7509 else if (*p == '&' || *p == '+') /* option */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007510 n = (get_option_tv(&p, NULL, TRUE) == OK);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007511 else if (*p == '*') /* internal or user defined function */
7512 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007513 n = function_exists(p + 1);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007514 }
7515 else if (*p == ':')
7516 {
7517 n = cmd_exists(p + 1);
7518 }
7519 else if (*p == '#')
7520 {
7521#ifdef FEAT_AUTOCMD
7522 name = p + 1;
7523 p = vim_strchr(name, '#');
7524 if (p != NULL)
7525 n = au_exists(name, p, p + 1);
7526 else
7527 n = au_exists(name, name + STRLEN(name), NULL);
7528#endif
7529 }
7530 else /* internal variable */
7531 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00007532 char_u *tofree;
7533 typval_T tv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007534
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00007535 /* get_name_len() takes care of expanding curly braces */
7536 name = p;
7537 len = get_name_len(&p, &tofree, TRUE, FALSE);
7538 if (len > 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007539 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00007540 if (tofree != NULL)
7541 name = tofree;
7542 n = (get_var_tv(name, len, &tv, FALSE) == OK);
7543 if (n)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007544 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00007545 /* handle d.key, l[idx], f(expr) */
7546 n = (handle_subscript(&p, &tv, TRUE, FALSE) == OK);
7547 if (n)
7548 clear_tv(&tv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007549 }
7550 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00007551
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00007552 vim_free(tofree);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007553 }
7554
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007555 rettv->vval.v_number = n;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007556}
7557
7558/*
7559 * "expand()" function
7560 */
7561 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007562f_expand(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007563 typval_T *argvars;
7564 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007565{
7566 char_u *s;
7567 int len;
7568 char_u *errormsg;
7569 int flags = WILD_SILENT|WILD_USE_NL|WILD_LIST_NOTFOUND;
7570 expand_T xpc;
7571
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007572 rettv->v_type = VAR_STRING;
7573 s = get_tv_string(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007574 if (*s == '%' || *s == '#' || *s == '<')
7575 {
7576 ++emsg_off;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007577 rettv->vval.v_string = eval_vars(s, &len, NULL, &errormsg, s);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007578 --emsg_off;
7579 }
7580 else
7581 {
7582 /* When the optional second argument is non-zero, don't remove matches
7583 * for 'suffixes' and 'wildignore' */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007584 if (argvars[1].v_type != VAR_UNKNOWN && get_tv_number(&argvars[1]))
Bram Moolenaar071d4272004-06-13 20:20:40 +00007585 flags |= WILD_KEEP_ALL;
7586 ExpandInit(&xpc);
7587 xpc.xp_context = EXPAND_FILES;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007588 rettv->vval.v_string = ExpandOne(&xpc, s, NULL, flags, WILD_ALL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007589 ExpandCleanup(&xpc);
7590 }
7591}
7592
7593/*
Bram Moolenaar8a283e52005-01-06 23:28:25 +00007594 * "extend(list, list [, idx])" function
Bram Moolenaare9a41262005-01-15 22:18:47 +00007595 * "extend(dict, dict [, action])" function
Bram Moolenaar8a283e52005-01-06 23:28:25 +00007596 */
7597 static void
7598f_extend(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007599 typval_T *argvars;
7600 typval_T *rettv;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00007601{
Bram Moolenaar8a283e52005-01-06 23:28:25 +00007602 rettv->vval.v_number = 0;
Bram Moolenaare9a41262005-01-15 22:18:47 +00007603 if (argvars[0].v_type == VAR_LIST && argvars[1].v_type == VAR_LIST)
Bram Moolenaar8a283e52005-01-06 23:28:25 +00007604 {
Bram Moolenaar33570922005-01-25 22:26:29 +00007605 list_T *l1, *l2;
7606 listitem_T *item;
Bram Moolenaare9a41262005-01-15 22:18:47 +00007607 long before;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00007608
Bram Moolenaare9a41262005-01-15 22:18:47 +00007609 l1 = argvars[0].vval.v_list;
7610 l2 = argvars[1].vval.v_list;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00007611 if (l1 != NULL && !tv_check_lock(l1->lv_lock, (char_u *)"extend()")
7612 && l2 != NULL)
Bram Moolenaare9a41262005-01-15 22:18:47 +00007613 {
7614 if (argvars[2].v_type != VAR_UNKNOWN)
7615 {
Bram Moolenaar758711c2005-02-02 23:11:38 +00007616 before = get_tv_number(&argvars[2]);
7617 if (before == l1->lv_len)
7618 item = NULL;
7619 else
Bram Moolenaare9a41262005-01-15 22:18:47 +00007620 {
Bram Moolenaar758711c2005-02-02 23:11:38 +00007621 item = list_find(l1, before);
7622 if (item == NULL)
7623 {
7624 EMSGN(_(e_listidx), before);
7625 return;
7626 }
Bram Moolenaare9a41262005-01-15 22:18:47 +00007627 }
7628 }
7629 else
7630 item = NULL;
7631 list_extend(l1, l2, item);
7632
7633 ++l1->lv_refcount;
7634 copy_tv(&argvars[0], rettv);
7635 }
Bram Moolenaar8a283e52005-01-06 23:28:25 +00007636 }
Bram Moolenaare9a41262005-01-15 22:18:47 +00007637 else if (argvars[0].v_type == VAR_DICT && argvars[1].v_type == VAR_DICT)
7638 {
Bram Moolenaar33570922005-01-25 22:26:29 +00007639 dict_T *d1, *d2;
7640 dictitem_T *di1;
Bram Moolenaare9a41262005-01-15 22:18:47 +00007641 char_u *action;
7642 int i;
Bram Moolenaar33570922005-01-25 22:26:29 +00007643 hashitem_T *hi2;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00007644 int todo;
Bram Moolenaare9a41262005-01-15 22:18:47 +00007645
7646 d1 = argvars[0].vval.v_dict;
7647 d2 = argvars[1].vval.v_dict;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00007648 if (d1 != NULL && !tv_check_lock(d1->dv_lock, (char_u *)"extend()")
7649 && d2 != NULL)
Bram Moolenaare9a41262005-01-15 22:18:47 +00007650 {
7651 /* Check the third argument. */
7652 if (argvars[2].v_type != VAR_UNKNOWN)
7653 {
7654 static char *(av[]) = {"keep", "force", "error"};
7655
7656 action = get_tv_string(&argvars[2]);
7657 for (i = 0; i < 3; ++i)
7658 if (STRCMP(action, av[i]) == 0)
7659 break;
7660 if (i == 3)
7661 {
7662 EMSGN(_(e_invarg2), action);
7663 return;
7664 }
7665 }
7666 else
7667 action = (char_u *)"force";
7668
7669 /* Go over all entries in the second dict and add them to the
7670 * first dict. */
Bram Moolenaar33570922005-01-25 22:26:29 +00007671 todo = d2->dv_hashtab.ht_used;
7672 for (hi2 = d2->dv_hashtab.ht_array; todo > 0; ++hi2)
Bram Moolenaare9a41262005-01-15 22:18:47 +00007673 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00007674 if (!HASHITEM_EMPTY(hi2))
Bram Moolenaare9a41262005-01-15 22:18:47 +00007675 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00007676 --todo;
7677 di1 = dict_find(d1, hi2->hi_key, -1);
7678 if (di1 == NULL)
7679 {
7680 di1 = dictitem_copy(HI2DI(hi2));
7681 if (di1 != NULL && dict_add(d1, di1) == FAIL)
7682 dictitem_free(di1);
7683 }
7684 else if (*action == 'e')
7685 {
7686 EMSG2(_("E737: Key already exists: %s"), hi2->hi_key);
7687 break;
7688 }
7689 else if (*action == 'f')
7690 {
7691 clear_tv(&di1->di_tv);
7692 copy_tv(&HI2DI(hi2)->di_tv, &di1->di_tv);
7693 }
Bram Moolenaare9a41262005-01-15 22:18:47 +00007694 }
7695 }
7696
7697 ++d1->dv_refcount;
7698 copy_tv(&argvars[0], rettv);
7699 }
7700 }
7701 else
7702 EMSG2(_(e_listdictarg), "extend()");
Bram Moolenaar8a283e52005-01-06 23:28:25 +00007703}
7704
7705/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00007706 * "filereadable()" function
7707 */
7708 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007709f_filereadable(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007710 typval_T *argvars;
7711 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007712{
7713 FILE *fd;
7714 char_u *p;
7715 int n;
7716
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007717 p = get_tv_string(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007718 if (*p && !mch_isdir(p) && (fd = mch_fopen((char *)p, "r")) != NULL)
7719 {
7720 n = TRUE;
7721 fclose(fd);
7722 }
7723 else
7724 n = FALSE;
7725
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007726 rettv->vval.v_number = n;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007727}
7728
7729/*
7730 * return 0 for not writable, 1 for writable file, 2 for a dir which we have
7731 * rights to write into.
7732 */
7733 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007734f_filewritable(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007735 typval_T *argvars;
7736 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007737{
7738 char_u *p;
7739 int retval = 0;
7740#if defined(UNIX) || defined(VMS)
7741 int perm = 0;
7742#endif
7743
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007744 p = get_tv_string(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007745#if defined(UNIX) || defined(VMS)
7746 perm = mch_getperm(p);
7747#endif
7748#ifndef MACOS_CLASSIC /* TODO: get either mch_writable or mch_access */
7749 if (
7750# ifdef WIN3264
7751 mch_writable(p) &&
7752# else
7753# if defined(UNIX) || defined(VMS)
7754 (perm & 0222) &&
7755# endif
7756# endif
7757 mch_access((char *)p, W_OK) == 0
7758 )
7759#endif
7760 {
7761 ++retval;
7762 if (mch_isdir(p))
7763 ++retval;
7764 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007765 rettv->vval.v_number = retval;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007766}
7767
Bram Moolenaar33570922005-01-25 22:26:29 +00007768static void findfilendir __ARGS((typval_T *argvars, typval_T *rettv, int dir));
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00007769
7770 static void
Bram Moolenaar0d660222005-01-07 21:51:51 +00007771findfilendir(argvars, rettv, dir)
Bram Moolenaar33570922005-01-25 22:26:29 +00007772 typval_T *argvars;
7773 typval_T *rettv;
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00007774 int dir;
7775{
7776#ifdef FEAT_SEARCHPATH
7777 char_u *fname;
7778 char_u *fresult = NULL;
7779 char_u *path = *curbuf->b_p_path == NUL ? p_path : curbuf->b_p_path;
7780 char_u *p;
7781 char_u pathbuf[NUMBUFLEN];
7782 int count = 1;
7783 int first = TRUE;
7784
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007785 fname = get_tv_string(&argvars[0]);
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00007786
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007787 if (argvars[1].v_type != VAR_UNKNOWN)
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00007788 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007789 p = get_tv_string_buf(&argvars[1], pathbuf);
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00007790 if (*p != NUL)
7791 path = p;
7792
Bram Moolenaar49cd9572005-01-03 21:06:01 +00007793 if (argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007794 count = get_tv_number(&argvars[2]);
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00007795 }
7796
7797 do
7798 {
7799 vim_free(fresult);
7800 fresult = find_file_in_path_option(first ? fname : NULL,
7801 first ? (int)STRLEN(fname) : 0,
7802 0, first, path, dir, NULL);
7803 first = FALSE;
7804 } while (--count > 0 && fresult != NULL);
7805
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007806 rettv->vval.v_string = fresult;
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00007807#else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007808 rettv->vval.v_string = NULL;
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00007809#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +00007810 rettv->v_type = VAR_STRING;
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00007811}
7812
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00007813static void prepare_vimvar __ARGS((int idx, typval_T *save_tv));
7814static void restore_vimvar __ARGS((int idx, typval_T *save_tv));
Bram Moolenaar33570922005-01-25 22:26:29 +00007815static void filter_map __ARGS((typval_T *argvars, typval_T *rettv, int map));
7816static int filter_map_one __ARGS((typval_T *tv, char_u *expr, int map, int *remp));
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00007817
7818/*
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00007819 * Prepare v: variable "idx" to be used.
7820 * Save the current typeval in "save_tv".
7821 * When not used yet add the variable to the v: hashtable.
7822 */
7823 static void
7824prepare_vimvar(idx, save_tv)
7825 int idx;
7826 typval_T *save_tv;
7827{
7828 *save_tv = vimvars[idx].vv_tv;
7829 if (vimvars[idx].vv_type == VAR_UNKNOWN)
7830 hash_add(&vimvarht, vimvars[idx].vv_di.di_key);
7831}
7832
7833/*
7834 * Restore v: variable "idx" to typeval "save_tv".
7835 * When no longer defined, remove the variable from the v: hashtable.
7836 */
7837 static void
7838restore_vimvar(idx, save_tv)
7839 int idx;
7840 typval_T *save_tv;
7841{
7842 hashitem_T *hi;
7843
7844 clear_tv(&vimvars[idx].vv_tv);
7845 vimvars[idx].vv_tv = *save_tv;
7846 if (vimvars[idx].vv_type == VAR_UNKNOWN)
7847 {
7848 hi = hash_find(&vimvarht, vimvars[idx].vv_di.di_key);
7849 if (HASHITEM_EMPTY(hi))
7850 EMSG2(_(e_intern2), "restore_vimvar()");
7851 else
7852 hash_remove(&vimvarht, hi);
7853 }
7854}
7855
7856/*
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00007857 * Implementation of map() and filter().
7858 */
7859 static void
7860filter_map(argvars, rettv, map)
Bram Moolenaar33570922005-01-25 22:26:29 +00007861 typval_T *argvars;
7862 typval_T *rettv;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00007863 int map;
7864{
7865 char_u buf[NUMBUFLEN];
Bram Moolenaare9a41262005-01-15 22:18:47 +00007866 char_u *expr;
Bram Moolenaar33570922005-01-25 22:26:29 +00007867 listitem_T *li, *nli;
7868 list_T *l = NULL;
7869 dictitem_T *di;
7870 hashtab_T *ht;
7871 hashitem_T *hi;
7872 dict_T *d = NULL;
7873 typval_T save_val;
7874 typval_T save_key;
Bram Moolenaare9a41262005-01-15 22:18:47 +00007875 int rem;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00007876 int todo;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00007877 char_u *msg = map ? (char_u *)"map()" : (char_u *)"filter()";
7878
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00007879
7880 rettv->vval.v_number = 0;
Bram Moolenaare9a41262005-01-15 22:18:47 +00007881 if (argvars[0].v_type == VAR_LIST)
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00007882 {
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00007883 if ((l = argvars[0].vval.v_list) == NULL
7884 || (map && tv_check_lock(l->lv_lock, msg)))
Bram Moolenaare9a41262005-01-15 22:18:47 +00007885 return;
7886 }
7887 else if (argvars[0].v_type == VAR_DICT)
7888 {
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00007889 if ((d = argvars[0].vval.v_dict) == NULL
7890 || (map && tv_check_lock(d->dv_lock, msg)))
Bram Moolenaare9a41262005-01-15 22:18:47 +00007891 return;
7892 }
7893 else
7894 {
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00007895 EMSG2(_(e_listdictarg), msg);
Bram Moolenaare9a41262005-01-15 22:18:47 +00007896 return;
7897 }
7898
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00007899 prepare_vimvar(VV_VAL, &save_val);
Bram Moolenaare9a41262005-01-15 22:18:47 +00007900 expr = skipwhite(get_tv_string_buf(&argvars[1], buf));
Bram Moolenaare9a41262005-01-15 22:18:47 +00007901
7902 if (argvars[0].v_type == VAR_DICT)
7903 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00007904 prepare_vimvar(VV_KEY, &save_key);
Bram Moolenaar33570922005-01-25 22:26:29 +00007905 vimvars[VV_KEY].vv_type = VAR_STRING;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00007906
Bram Moolenaar33570922005-01-25 22:26:29 +00007907 ht = &d->dv_hashtab;
Bram Moolenaara7043832005-01-21 11:56:39 +00007908 hash_lock(ht);
7909 todo = ht->ht_used;
7910 for (hi = ht->ht_array; todo > 0; ++hi)
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00007911 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00007912 if (!HASHITEM_EMPTY(hi))
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00007913 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00007914 --todo;
7915 di = HI2DI(hi);
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00007916 if (tv_check_lock(di->di_tv.v_lock, msg))
7917 break;
Bram Moolenaar33570922005-01-25 22:26:29 +00007918 vimvars[VV_KEY].vv_str = vim_strsave(di->di_key);
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00007919 if (filter_map_one(&di->di_tv, expr, map, &rem) == FAIL)
7920 break;
7921 if (!map && rem)
7922 dictitem_remove(d, di);
Bram Moolenaar33570922005-01-25 22:26:29 +00007923 clear_tv(&vimvars[VV_KEY].vv_tv);
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00007924 }
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00007925 }
Bram Moolenaara7043832005-01-21 11:56:39 +00007926 hash_unlock(ht);
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00007927
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00007928 restore_vimvar(VV_KEY, &save_key);
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00007929 }
Bram Moolenaare9a41262005-01-15 22:18:47 +00007930 else
7931 {
7932 for (li = l->lv_first; li != NULL; li = nli)
7933 {
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00007934 if (tv_check_lock(li->li_tv.v_lock, msg))
7935 break;
Bram Moolenaare9a41262005-01-15 22:18:47 +00007936 nli = li->li_next;
7937 if (filter_map_one(&li->li_tv, expr, map, &rem) == FAIL)
7938 break;
7939 if (!map && rem)
Bram Moolenaar7480b5c2005-01-16 22:07:38 +00007940 listitem_remove(l, li);
Bram Moolenaare9a41262005-01-15 22:18:47 +00007941 }
7942 }
7943
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +00007944 restore_vimvar(VV_VAL, &save_val);
Bram Moolenaare9a41262005-01-15 22:18:47 +00007945
7946 copy_tv(&argvars[0], rettv);
7947}
7948
7949 static int
7950filter_map_one(tv, expr, map, remp)
Bram Moolenaar33570922005-01-25 22:26:29 +00007951 typval_T *tv;
Bram Moolenaare9a41262005-01-15 22:18:47 +00007952 char_u *expr;
7953 int map;
7954 int *remp;
7955{
Bram Moolenaar33570922005-01-25 22:26:29 +00007956 typval_T rettv;
Bram Moolenaare9a41262005-01-15 22:18:47 +00007957 char_u *s;
7958
Bram Moolenaar33570922005-01-25 22:26:29 +00007959 copy_tv(tv, &vimvars[VV_VAL].vv_tv);
Bram Moolenaare9a41262005-01-15 22:18:47 +00007960 s = expr;
7961 if (eval1(&s, &rettv, TRUE) == FAIL)
7962 return FAIL;
7963 if (*s != NUL) /* check for trailing chars after expr */
7964 {
7965 EMSG2(_(e_invexpr2), s);
7966 return FAIL;
7967 }
7968 if (map)
7969 {
7970 /* map(): replace the list item value */
7971 clear_tv(tv);
7972 *tv = rettv;
7973 }
7974 else
7975 {
7976 /* filter(): when expr is zero remove the item */
7977 *remp = (get_tv_number(&rettv) == 0);
7978 clear_tv(&rettv);
7979 }
Bram Moolenaar33570922005-01-25 22:26:29 +00007980 clear_tv(&vimvars[VV_VAL].vv_tv);
Bram Moolenaare9a41262005-01-15 22:18:47 +00007981 return OK;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00007982}
7983
7984/*
7985 * "filter()" function
7986 */
7987 static void
7988f_filter(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00007989 typval_T *argvars;
7990 typval_T *rettv;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00007991{
7992 filter_map(argvars, rettv, FALSE);
7993}
7994
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00007995/*
Bram Moolenaar0d660222005-01-07 21:51:51 +00007996 * "finddir({fname}[, {path}[, {count}]])" function
7997 */
7998 static void
7999f_finddir(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008000 typval_T *argvars;
8001 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +00008002{
8003 findfilendir(argvars, rettv, TRUE);
8004}
8005
8006/*
8007 * "findfile({fname}[, {path}[, {count}]])" function
8008 */
8009 static void
8010f_findfile(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008011 typval_T *argvars;
8012 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +00008013{
8014 findfilendir(argvars, rettv, FALSE);
8015}
8016
8017/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00008018 * "fnamemodify({fname}, {mods})" function
8019 */
8020 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008021f_fnamemodify(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008022 typval_T *argvars;
8023 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008024{
8025 char_u *fname;
8026 char_u *mods;
8027 int usedlen = 0;
8028 int len;
8029 char_u *fbuf = NULL;
8030 char_u buf[NUMBUFLEN];
8031
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008032 fname = get_tv_string(&argvars[0]);
8033 mods = get_tv_string_buf(&argvars[1], buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008034 len = (int)STRLEN(fname);
8035
8036 (void)modify_fname(mods, &usedlen, &fname, &fbuf, &len);
8037
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008038 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008039 if (fname == NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008040 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008041 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008042 rettv->vval.v_string = vim_strnsave(fname, len);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008043 vim_free(fbuf);
8044}
8045
Bram Moolenaar33570922005-01-25 22:26:29 +00008046static void foldclosed_both __ARGS((typval_T *argvars, typval_T *rettv, int end));
Bram Moolenaar071d4272004-06-13 20:20:40 +00008047
8048/*
8049 * "foldclosed()" function
8050 */
8051 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008052foldclosed_both(argvars, rettv, end)
Bram Moolenaar33570922005-01-25 22:26:29 +00008053 typval_T *argvars;
8054 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008055 int end;
8056{
8057#ifdef FEAT_FOLDING
8058 linenr_T lnum;
8059 linenr_T first, last;
8060
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008061 lnum = get_tv_lnum(argvars);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008062 if (lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count)
8063 {
8064 if (hasFoldingWin(curwin, lnum, &first, &last, FALSE, NULL))
8065 {
8066 if (end)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008067 rettv->vval.v_number = (varnumber_T)last;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008068 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008069 rettv->vval.v_number = (varnumber_T)first;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008070 return;
8071 }
8072 }
8073#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008074 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008075}
8076
8077/*
Bram Moolenaar0d660222005-01-07 21:51:51 +00008078 * "foldclosed()" function
8079 */
8080 static void
8081f_foldclosed(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008082 typval_T *argvars;
8083 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +00008084{
8085 foldclosed_both(argvars, rettv, FALSE);
8086}
8087
8088/*
8089 * "foldclosedend()" function
8090 */
8091 static void
8092f_foldclosedend(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008093 typval_T *argvars;
8094 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +00008095{
8096 foldclosed_both(argvars, rettv, TRUE);
8097}
8098
8099/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00008100 * "foldlevel()" function
8101 */
8102 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008103f_foldlevel(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008104 typval_T *argvars;
8105 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008106{
8107#ifdef FEAT_FOLDING
8108 linenr_T lnum;
8109
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008110 lnum = get_tv_lnum(argvars);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008111 if (lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008112 rettv->vval.v_number = foldLevel(lnum);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008113 else
8114#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008115 rettv->vval.v_number = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008116}
8117
8118/*
8119 * "foldtext()" function
8120 */
8121/*ARGSUSED*/
8122 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008123f_foldtext(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008124 typval_T *argvars;
8125 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008126{
8127#ifdef FEAT_FOLDING
8128 linenr_T lnum;
8129 char_u *s;
8130 char_u *r;
8131 int len;
8132 char *txt;
8133#endif
8134
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008135 rettv->v_type = VAR_STRING;
8136 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008137#ifdef FEAT_FOLDING
Bram Moolenaare9a41262005-01-15 22:18:47 +00008138 if ((linenr_T)vimvars[VV_FOLDSTART].vv_nr > 0
8139 && (linenr_T)vimvars[VV_FOLDEND].vv_nr
8140 <= curbuf->b_ml.ml_line_count
8141 && vimvars[VV_FOLDDASHES].vv_str != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008142 {
8143 /* Find first non-empty line in the fold. */
Bram Moolenaare9a41262005-01-15 22:18:47 +00008144 lnum = (linenr_T)vimvars[VV_FOLDSTART].vv_nr;
8145 while (lnum < (linenr_T)vimvars[VV_FOLDEND].vv_nr)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008146 {
8147 if (!linewhite(lnum))
8148 break;
8149 ++lnum;
8150 }
8151
8152 /* Find interesting text in this line. */
8153 s = skipwhite(ml_get(lnum));
8154 /* skip C comment-start */
8155 if (s[0] == '/' && (s[1] == '*' || s[1] == '/'))
Bram Moolenaar293ee4d2004-12-09 21:34:53 +00008156 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00008157 s = skipwhite(s + 2);
Bram Moolenaar293ee4d2004-12-09 21:34:53 +00008158 if (*skipwhite(s) == NUL
Bram Moolenaare9a41262005-01-15 22:18:47 +00008159 && lnum + 1 < (linenr_T)vimvars[VV_FOLDEND].vv_nr)
Bram Moolenaar293ee4d2004-12-09 21:34:53 +00008160 {
8161 s = skipwhite(ml_get(lnum + 1));
8162 if (*s == '*')
8163 s = skipwhite(s + 1);
8164 }
8165 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00008166 txt = _("+-%s%3ld lines: ");
8167 r = alloc((unsigned)(STRLEN(txt)
Bram Moolenaare9a41262005-01-15 22:18:47 +00008168 + STRLEN(vimvars[VV_FOLDDASHES].vv_str) /* for %s */
Bram Moolenaar071d4272004-06-13 20:20:40 +00008169 + 20 /* for %3ld */
8170 + STRLEN(s))); /* concatenated */
8171 if (r != NULL)
8172 {
Bram Moolenaare9a41262005-01-15 22:18:47 +00008173 sprintf((char *)r, txt, vimvars[VV_FOLDDASHES].vv_str,
8174 (long)((linenr_T)vimvars[VV_FOLDEND].vv_nr
8175 - (linenr_T)vimvars[VV_FOLDSTART].vv_nr + 1));
Bram Moolenaar071d4272004-06-13 20:20:40 +00008176 len = (int)STRLEN(r);
8177 STRCAT(r, s);
8178 /* remove 'foldmarker' and 'commentstring' */
8179 foldtext_cleanup(r + len);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008180 rettv->vval.v_string = r;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008181 }
8182 }
8183#endif
8184}
8185
8186/*
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00008187 * "foldtextresult(lnum)" function
8188 */
8189/*ARGSUSED*/
8190 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008191f_foldtextresult(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008192 typval_T *argvars;
8193 typval_T *rettv;
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00008194{
8195#ifdef FEAT_FOLDING
8196 linenr_T lnum;
8197 char_u *text;
8198 char_u buf[51];
8199 foldinfo_T foldinfo;
8200 int fold_count;
8201#endif
8202
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008203 rettv->v_type = VAR_STRING;
8204 rettv->vval.v_string = NULL;
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00008205#ifdef FEAT_FOLDING
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008206 lnum = get_tv_lnum(argvars);
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00008207 fold_count = foldedCount(curwin, lnum, &foldinfo);
8208 if (fold_count > 0)
8209 {
8210 text = get_foldtext(curwin, lnum, lnum + fold_count - 1,
8211 &foldinfo, buf);
8212 if (text == buf)
8213 text = vim_strsave(text);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008214 rettv->vval.v_string = text;
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00008215 }
8216#endif
8217}
8218
8219/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00008220 * "foreground()" function
8221 */
8222/*ARGSUSED*/
8223 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008224f_foreground(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008225 typval_T *argvars;
8226 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008227{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008228 rettv->vval.v_number = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008229#ifdef FEAT_GUI
8230 if (gui.in_use)
8231 gui_mch_set_foreground();
8232#else
8233# ifdef WIN32
8234 win32_set_foreground();
8235# endif
8236#endif
8237}
8238
8239/*
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008240 * "function()" function
8241 */
8242/*ARGSUSED*/
8243 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008244f_function(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008245 typval_T *argvars;
8246 typval_T *rettv;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008247{
8248 char_u *s;
8249
Bram Moolenaara7043832005-01-21 11:56:39 +00008250 rettv->vval.v_number = 0;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008251 s = get_tv_string(&argvars[0]);
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00008252 if (s == NULL || *s == NUL || VIM_ISDIGIT(*s))
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008253 EMSG2(_(e_invarg2), s);
8254 else if (!function_exists(s))
Bram Moolenaare49b69a2005-01-08 16:11:57 +00008255 EMSG2(_("E700: Unknown function: %s"), s);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008256 else
8257 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008258 rettv->vval.v_string = vim_strsave(s);
8259 rettv->v_type = VAR_FUNC;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008260 }
8261}
8262
8263/*
Bram Moolenaar0d660222005-01-07 21:51:51 +00008264 * "get()" function
8265 */
8266 static void
8267f_get(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008268 typval_T *argvars;
8269 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +00008270{
Bram Moolenaar33570922005-01-25 22:26:29 +00008271 listitem_T *li;
8272 list_T *l;
8273 dictitem_T *di;
8274 dict_T *d;
8275 typval_T *tv = NULL;
Bram Moolenaar0d660222005-01-07 21:51:51 +00008276
Bram Moolenaare9a41262005-01-15 22:18:47 +00008277 if (argvars[0].v_type == VAR_LIST)
Bram Moolenaar0d660222005-01-07 21:51:51 +00008278 {
Bram Moolenaare9a41262005-01-15 22:18:47 +00008279 if ((l = argvars[0].vval.v_list) != NULL)
Bram Moolenaar0d660222005-01-07 21:51:51 +00008280 {
Bram Moolenaare9a41262005-01-15 22:18:47 +00008281 li = list_find(l, get_tv_number(&argvars[1]));
8282 if (li != NULL)
8283 tv = &li->li_tv;
Bram Moolenaar0d660222005-01-07 21:51:51 +00008284 }
Bram Moolenaar0d660222005-01-07 21:51:51 +00008285 }
Bram Moolenaare9a41262005-01-15 22:18:47 +00008286 else if (argvars[0].v_type == VAR_DICT)
8287 {
8288 if ((d = argvars[0].vval.v_dict) != NULL)
8289 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00008290 di = dict_find(d, get_tv_string(&argvars[1]), -1);
Bram Moolenaare9a41262005-01-15 22:18:47 +00008291 if (di != NULL)
8292 tv = &di->di_tv;
8293 }
8294 }
8295 else
8296 EMSG2(_(e_listdictarg), "get()");
8297
8298 if (tv == NULL)
8299 {
8300 if (argvars[2].v_type == VAR_UNKNOWN)
8301 rettv->vval.v_number = 0;
8302 else
8303 copy_tv(&argvars[2], rettv);
8304 }
8305 else
8306 copy_tv(tv, rettv);
Bram Moolenaar0d660222005-01-07 21:51:51 +00008307}
8308
8309/*
8310 * "getbufvar()" function
8311 */
8312 static void
8313f_getbufvar(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008314 typval_T *argvars;
8315 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +00008316{
8317 buf_T *buf;
8318 buf_T *save_curbuf;
8319 char_u *varname;
Bram Moolenaar33570922005-01-25 22:26:29 +00008320 dictitem_T *v;
Bram Moolenaar0d660222005-01-07 21:51:51 +00008321
8322 ++emsg_off;
8323 buf = get_buf_tv(&argvars[0]);
8324 varname = get_tv_string(&argvars[1]);
8325
8326 rettv->v_type = VAR_STRING;
8327 rettv->vval.v_string = NULL;
8328
8329 if (buf != NULL && varname != NULL)
8330 {
8331 if (*varname == '&') /* buffer-local-option */
8332 {
8333 /* set curbuf to be our buf, temporarily */
8334 save_curbuf = curbuf;
8335 curbuf = buf;
8336
8337 get_option_tv(&varname, rettv, TRUE);
8338
8339 /* restore previous notion of curbuf */
8340 curbuf = save_curbuf;
8341 }
8342 else
8343 {
8344 /* look up the variable */
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00008345 v = find_var_in_ht(&buf->b_vars.dv_hashtab, varname, FALSE);
Bram Moolenaar0d660222005-01-07 21:51:51 +00008346 if (v != NULL)
Bram Moolenaar33570922005-01-25 22:26:29 +00008347 copy_tv(&v->di_tv, rettv);
Bram Moolenaar0d660222005-01-07 21:51:51 +00008348 }
8349 }
8350
8351 --emsg_off;
8352}
8353
8354/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00008355 * "getchar()" function
8356 */
8357 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008358f_getchar(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008359 typval_T *argvars;
8360 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008361{
8362 varnumber_T n;
8363
8364 ++no_mapping;
8365 ++allow_keys;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008366 if (argvars[0].v_type == VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008367 /* getchar(): blocking wait. */
8368 n = safe_vgetc();
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008369 else if (get_tv_number(&argvars[0]) == 1)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008370 /* getchar(1): only check if char avail */
8371 n = vpeekc();
8372 else if (vpeekc() == NUL)
8373 /* getchar(0) and no char avail: return zero */
8374 n = 0;
8375 else
8376 /* getchar(0) and char avail: return char */
8377 n = safe_vgetc();
8378 --no_mapping;
8379 --allow_keys;
8380
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008381 rettv->vval.v_number = n;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008382 if (IS_SPECIAL(n) || mod_mask != 0)
8383 {
8384 char_u temp[10]; /* modifier: 3, mbyte-char: 6, NUL: 1 */
8385 int i = 0;
8386
8387 /* Turn a special key into three bytes, plus modifier. */
8388 if (mod_mask != 0)
8389 {
8390 temp[i++] = K_SPECIAL;
8391 temp[i++] = KS_MODIFIER;
8392 temp[i++] = mod_mask;
8393 }
8394 if (IS_SPECIAL(n))
8395 {
8396 temp[i++] = K_SPECIAL;
8397 temp[i++] = K_SECOND(n);
8398 temp[i++] = K_THIRD(n);
8399 }
8400#ifdef FEAT_MBYTE
8401 else if (has_mbyte)
8402 i += (*mb_char2bytes)(n, temp + i);
8403#endif
8404 else
8405 temp[i++] = n;
8406 temp[i++] = NUL;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008407 rettv->v_type = VAR_STRING;
8408 rettv->vval.v_string = vim_strsave(temp);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008409 }
8410}
8411
8412/*
8413 * "getcharmod()" function
8414 */
8415/*ARGSUSED*/
8416 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008417f_getcharmod(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008418 typval_T *argvars;
8419 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008420{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008421 rettv->vval.v_number = mod_mask;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008422}
8423
8424/*
8425 * "getcmdline()" function
8426 */
8427/*ARGSUSED*/
8428 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008429f_getcmdline(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008430 typval_T *argvars;
8431 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008432{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008433 rettv->v_type = VAR_STRING;
8434 rettv->vval.v_string = get_cmdline_str();
Bram Moolenaar071d4272004-06-13 20:20:40 +00008435}
8436
8437/*
8438 * "getcmdpos()" function
8439 */
8440/*ARGSUSED*/
8441 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008442f_getcmdpos(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008443 typval_T *argvars;
8444 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008445{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008446 rettv->vval.v_number = get_cmdline_pos() + 1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008447}
8448
8449/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00008450 * "getcwd()" function
8451 */
8452/*ARGSUSED*/
8453 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008454f_getcwd(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008455 typval_T *argvars;
8456 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008457{
8458 char_u cwd[MAXPATHL];
8459
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008460 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008461 if (mch_dirname(cwd, MAXPATHL) == FAIL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008462 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008463 else
8464 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008465 rettv->vval.v_string = vim_strsave(cwd);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008466#ifdef BACKSLASH_IN_FILENAME
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008467 slash_adjust(rettv->vval.v_string);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008468#endif
8469 }
8470}
8471
8472/*
Bram Moolenaar46c9c732004-12-12 11:37:09 +00008473 * "getfontname()" function
8474 */
Bram Moolenaar1cd871b2004-12-19 22:46:22 +00008475/*ARGSUSED*/
Bram Moolenaar46c9c732004-12-12 11:37:09 +00008476 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008477f_getfontname(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008478 typval_T *argvars;
8479 typval_T *rettv;
Bram Moolenaar46c9c732004-12-12 11:37:09 +00008480{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008481 rettv->v_type = VAR_STRING;
8482 rettv->vval.v_string = NULL;
Bram Moolenaar46c9c732004-12-12 11:37:09 +00008483#ifdef FEAT_GUI
8484 if (gui.in_use)
8485 {
8486 GuiFont font;
8487 char_u *name = NULL;
8488
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008489 if (argvars[0].v_type == VAR_UNKNOWN)
Bram Moolenaar46c9c732004-12-12 11:37:09 +00008490 {
8491 /* Get the "Normal" font. Either the name saved by
8492 * hl_set_font_name() or from the font ID. */
8493 font = gui.norm_font;
8494 name = hl_get_font_name();
8495 }
8496 else
8497 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008498 name = get_tv_string(&argvars[0]);
Bram Moolenaar46c9c732004-12-12 11:37:09 +00008499 if (STRCMP(name, "*") == 0) /* don't use font dialog */
8500 return;
8501 font = gui_mch_get_font(name, FALSE);
8502 if (font == NOFONT)
8503 return; /* Invalid font name, return empty string. */
8504 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008505 rettv->vval.v_string = gui_mch_get_fontname(font, name);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008506 if (argvars[0].v_type != VAR_UNKNOWN)
Bram Moolenaar46c9c732004-12-12 11:37:09 +00008507 gui_mch_free_font(font);
8508 }
8509#endif
8510}
8511
8512/*
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00008513 * "getfperm({fname})" function
8514 */
8515 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008516f_getfperm(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008517 typval_T *argvars;
8518 typval_T *rettv;
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00008519{
8520 char_u *fname;
8521 struct stat st;
8522 char_u *perm = NULL;
8523 char_u flags[] = "rwx";
8524 int i;
8525
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008526 fname = get_tv_string(&argvars[0]);
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00008527
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008528 rettv->v_type = VAR_STRING;
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00008529 if (mch_stat((char *)fname, &st) >= 0)
8530 {
8531 perm = vim_strsave((char_u *)"---------");
8532 if (perm != NULL)
8533 {
8534 for (i = 0; i < 9; i++)
8535 {
8536 if (st.st_mode & (1 << (8 - i)))
8537 perm[i] = flags[i % 3];
8538 }
8539 }
8540 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008541 rettv->vval.v_string = perm;
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00008542}
8543
8544/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00008545 * "getfsize({fname})" function
8546 */
8547 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008548f_getfsize(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008549 typval_T *argvars;
8550 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008551{
8552 char_u *fname;
8553 struct stat st;
8554
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008555 fname = get_tv_string(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008556
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008557 rettv->v_type = VAR_NUMBER;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008558
8559 if (mch_stat((char *)fname, &st) >= 0)
8560 {
8561 if (mch_isdir(fname))
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008562 rettv->vval.v_number = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008563 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008564 rettv->vval.v_number = (varnumber_T)st.st_size;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008565 }
8566 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008567 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008568}
8569
8570/*
8571 * "getftime({fname})" function
8572 */
8573 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008574f_getftime(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008575 typval_T *argvars;
8576 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008577{
8578 char_u *fname;
8579 struct stat st;
8580
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008581 fname = get_tv_string(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008582
8583 if (mch_stat((char *)fname, &st) >= 0)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008584 rettv->vval.v_number = (varnumber_T)st.st_mtime;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008585 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008586 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008587}
8588
8589/*
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00008590 * "getftype({fname})" function
8591 */
8592 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008593f_getftype(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008594 typval_T *argvars;
8595 typval_T *rettv;
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00008596{
8597 char_u *fname;
8598 struct stat st;
8599 char_u *type = NULL;
8600 char *t;
8601
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008602 fname = get_tv_string(&argvars[0]);
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00008603
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008604 rettv->v_type = VAR_STRING;
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00008605 if (mch_lstat((char *)fname, &st) >= 0)
8606 {
8607#ifdef S_ISREG
8608 if (S_ISREG(st.st_mode))
8609 t = "file";
8610 else if (S_ISDIR(st.st_mode))
8611 t = "dir";
8612# ifdef S_ISLNK
8613 else if (S_ISLNK(st.st_mode))
8614 t = "link";
8615# endif
8616# ifdef S_ISBLK
8617 else if (S_ISBLK(st.st_mode))
8618 t = "bdev";
8619# endif
8620# ifdef S_ISCHR
8621 else if (S_ISCHR(st.st_mode))
8622 t = "cdev";
8623# endif
8624# ifdef S_ISFIFO
8625 else if (S_ISFIFO(st.st_mode))
8626 t = "fifo";
8627# endif
8628# ifdef S_ISSOCK
8629 else if (S_ISSOCK(st.st_mode))
8630 t = "fifo";
8631# endif
8632 else
8633 t = "other";
8634#else
8635# ifdef S_IFMT
8636 switch (st.st_mode & S_IFMT)
8637 {
8638 case S_IFREG: t = "file"; break;
8639 case S_IFDIR: t = "dir"; break;
8640# ifdef S_IFLNK
8641 case S_IFLNK: t = "link"; break;
8642# endif
8643# ifdef S_IFBLK
8644 case S_IFBLK: t = "bdev"; break;
8645# endif
8646# ifdef S_IFCHR
8647 case S_IFCHR: t = "cdev"; break;
8648# endif
8649# ifdef S_IFIFO
8650 case S_IFIFO: t = "fifo"; break;
8651# endif
8652# ifdef S_IFSOCK
8653 case S_IFSOCK: t = "socket"; break;
8654# endif
8655 default: t = "other";
8656 }
8657# else
8658 if (mch_isdir(fname))
8659 t = "dir";
8660 else
8661 t = "file";
8662# endif
8663#endif
8664 type = vim_strsave((char_u *)t);
8665 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008666 rettv->vval.v_string = type;
Bram Moolenaar5eb86f92004-07-26 12:53:41 +00008667}
8668
8669/*
Bram Moolenaar0d660222005-01-07 21:51:51 +00008670 * "getline(lnum)" function
8671 */
8672 static void
8673f_getline(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008674 typval_T *argvars;
8675 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +00008676{
8677 linenr_T lnum;
8678 linenr_T end;
8679 char_u *p;
Bram Moolenaar33570922005-01-25 22:26:29 +00008680 list_T *l;
8681 listitem_T *li;
Bram Moolenaar0d660222005-01-07 21:51:51 +00008682
8683 lnum = get_tv_lnum(argvars);
8684
8685 if (argvars[1].v_type == VAR_UNKNOWN)
8686 {
8687 if (lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count)
8688 p = ml_get(lnum);
8689 else
8690 p = (char_u *)"";
8691
8692 rettv->v_type = VAR_STRING;
8693 rettv->vval.v_string = vim_strsave(p);
8694 }
8695 else
8696 {
8697 end = get_tv_lnum(&argvars[1]);
8698 if (end < lnum)
8699 {
8700 EMSG(_(e_invrange));
8701 rettv->vval.v_number = 0;
8702 }
8703 else
8704 {
8705 l = list_alloc();
8706 if (l != NULL)
8707 {
8708 if (lnum < 1)
8709 lnum = 1;
8710 if (end > curbuf->b_ml.ml_line_count)
8711 end = curbuf->b_ml.ml_line_count;
8712 while (lnum <= end)
8713 {
8714 li = listitem_alloc();
8715 if (li == NULL)
8716 break;
8717 list_append(l, li);
8718 li->li_tv.v_type = VAR_STRING;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00008719 li->li_tv.v_lock = 0;
Bram Moolenaar0d660222005-01-07 21:51:51 +00008720 li->li_tv.vval.v_string = vim_strsave(ml_get(lnum++));
8721 }
8722 rettv->vval.v_list = l;
8723 rettv->v_type = VAR_LIST;
8724 ++l->lv_refcount;
8725 }
8726 }
8727 }
8728}
8729
8730/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00008731 * "getreg()" function
8732 */
8733 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008734f_getreg(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008735 typval_T *argvars;
8736 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008737{
8738 char_u *strregname;
8739 int regname;
8740
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008741 if (argvars[0].v_type != VAR_UNKNOWN)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008742 strregname = get_tv_string(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008743 else
Bram Moolenaare9a41262005-01-15 22:18:47 +00008744 strregname = vimvars[VV_REG].vv_str;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008745 regname = (strregname == NULL ? '"' : *strregname);
8746 if (regname == 0)
8747 regname = '"';
8748
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008749 rettv->v_type = VAR_STRING;
8750 rettv->vval.v_string = get_reg_contents(regname, TRUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008751}
8752
8753/*
8754 * "getregtype()" function
8755 */
8756 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008757f_getregtype(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008758 typval_T *argvars;
8759 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008760{
8761 char_u *strregname;
8762 int regname;
8763 char_u buf[NUMBUFLEN + 2];
8764 long reglen = 0;
8765
Bram Moolenaar49cd9572005-01-03 21:06:01 +00008766 if (argvars[0].v_type != VAR_UNKNOWN)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008767 strregname = get_tv_string(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008768 else
8769 /* Default to v:register */
Bram Moolenaare9a41262005-01-15 22:18:47 +00008770 strregname = vimvars[VV_REG].vv_str;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008771
8772 regname = (strregname == NULL ? '"' : *strregname);
8773 if (regname == 0)
8774 regname = '"';
8775
8776 buf[0] = NUL;
8777 buf[1] = NUL;
8778 switch (get_reg_type(regname, &reglen))
8779 {
8780 case MLINE: buf[0] = 'V'; break;
8781 case MCHAR: buf[0] = 'v'; break;
8782#ifdef FEAT_VISUAL
8783 case MBLOCK:
8784 buf[0] = Ctrl_V;
8785 sprintf((char *)buf + 1, "%ld", reglen + 1);
8786 break;
8787#endif
8788 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008789 rettv->v_type = VAR_STRING;
8790 rettv->vval.v_string = vim_strsave(buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008791}
8792
8793/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00008794 * "getwinposx()" function
8795 */
8796/*ARGSUSED*/
8797 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008798f_getwinposx(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008799 typval_T *argvars;
8800 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008801{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008802 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008803#ifdef FEAT_GUI
8804 if (gui.in_use)
8805 {
8806 int x, y;
8807
8808 if (gui_mch_get_winpos(&x, &y) == OK)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008809 rettv->vval.v_number = x;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008810 }
8811#endif
8812}
8813
8814/*
8815 * "getwinposy()" function
8816 */
8817/*ARGSUSED*/
8818 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008819f_getwinposy(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008820 typval_T *argvars;
8821 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008822{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008823 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008824#ifdef FEAT_GUI
8825 if (gui.in_use)
8826 {
8827 int x, y;
8828
8829 if (gui_mch_get_winpos(&x, &y) == OK)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008830 rettv->vval.v_number = y;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008831 }
8832#endif
8833}
8834
8835/*
8836 * "getwinvar()" function
8837 */
8838 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008839f_getwinvar(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008840 typval_T *argvars;
8841 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008842{
8843 win_T *win, *oldcurwin;
8844 char_u *varname;
Bram Moolenaar33570922005-01-25 22:26:29 +00008845 dictitem_T *v;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008846
8847 ++emsg_off;
8848 win = find_win_by_nr(&argvars[0]);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008849 varname = get_tv_string(&argvars[1]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008850
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008851 rettv->v_type = VAR_STRING;
8852 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008853
8854 if (win != NULL && varname != NULL)
8855 {
8856 if (*varname == '&') /* window-local-option */
8857 {
8858 /* set curwin to be our win, temporarily */
8859 oldcurwin = curwin;
8860 curwin = win;
8861
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008862 get_option_tv(&varname, rettv, 1);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008863
8864 /* restore previous notion of curwin */
8865 curwin = oldcurwin;
8866 }
8867 else
8868 {
8869 /* look up the variable */
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00008870 v = find_var_in_ht(&win->w_vars.dv_hashtab, varname, FALSE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008871 if (v != NULL)
Bram Moolenaar33570922005-01-25 22:26:29 +00008872 copy_tv(&v->di_tv, rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008873 }
8874 }
8875
8876 --emsg_off;
8877}
8878
8879/*
8880 * "glob()" function
8881 */
8882 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008883f_glob(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008884 typval_T *argvars;
8885 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008886{
8887 expand_T xpc;
8888
8889 ExpandInit(&xpc);
8890 xpc.xp_context = EXPAND_FILES;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008891 rettv->v_type = VAR_STRING;
8892 rettv->vval.v_string = ExpandOne(&xpc, get_tv_string(&argvars[0]),
Bram Moolenaar071d4272004-06-13 20:20:40 +00008893 NULL, WILD_USE_NL|WILD_SILENT, WILD_ALL);
8894 ExpandCleanup(&xpc);
8895}
8896
8897/*
8898 * "globpath()" function
8899 */
8900 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008901f_globpath(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008902 typval_T *argvars;
8903 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008904{
8905 char_u buf1[NUMBUFLEN];
8906
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008907 rettv->v_type = VAR_STRING;
8908 rettv->vval.v_string = globpath(get_tv_string(&argvars[0]),
8909 get_tv_string_buf(&argvars[1], buf1));
Bram Moolenaar071d4272004-06-13 20:20:40 +00008910}
8911
8912/*
8913 * "has()" function
8914 */
8915 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00008916f_has(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00008917 typval_T *argvars;
8918 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008919{
8920 int i;
8921 char_u *name;
8922 int n = FALSE;
8923 static char *(has_list[]) =
8924 {
8925#ifdef AMIGA
8926 "amiga",
8927# ifdef FEAT_ARP
8928 "arp",
8929# endif
8930#endif
8931#ifdef __BEOS__
8932 "beos",
8933#endif
8934#ifdef MSDOS
8935# ifdef DJGPP
8936 "dos32",
8937# else
8938 "dos16",
8939# endif
8940#endif
8941#ifdef MACOS /* TODO: Should we add MACOS_CLASSIC, MACOS_X? (Dany) */
8942 "mac",
8943#endif
8944#if defined(MACOS_X_UNIX)
8945 "macunix",
8946#endif
8947#ifdef OS2
8948 "os2",
8949#endif
8950#ifdef __QNX__
8951 "qnx",
8952#endif
8953#ifdef RISCOS
8954 "riscos",
8955#endif
8956#ifdef UNIX
8957 "unix",
8958#endif
8959#ifdef VMS
8960 "vms",
8961#endif
8962#ifdef WIN16
8963 "win16",
8964#endif
8965#ifdef WIN32
8966 "win32",
8967#endif
8968#if defined(UNIX) && (defined(__CYGWIN32__) || defined(__CYGWIN__))
8969 "win32unix",
8970#endif
8971#ifdef WIN64
8972 "win64",
8973#endif
8974#ifdef EBCDIC
8975 "ebcdic",
8976#endif
8977#ifndef CASE_INSENSITIVE_FILENAME
8978 "fname_case",
8979#endif
8980#ifdef FEAT_ARABIC
8981 "arabic",
8982#endif
8983#ifdef FEAT_AUTOCMD
8984 "autocmd",
8985#endif
8986#ifdef FEAT_BEVAL
8987 "balloon_eval",
8988#endif
8989#if defined(SOME_BUILTIN_TCAPS) || defined(ALL_BUILTIN_TCAPS)
8990 "builtin_terms",
8991# ifdef ALL_BUILTIN_TCAPS
8992 "all_builtin_terms",
8993# endif
8994#endif
8995#ifdef FEAT_BYTEOFF
8996 "byte_offset",
8997#endif
8998#ifdef FEAT_CINDENT
8999 "cindent",
9000#endif
9001#ifdef FEAT_CLIENTSERVER
9002 "clientserver",
9003#endif
9004#ifdef FEAT_CLIPBOARD
9005 "clipboard",
9006#endif
9007#ifdef FEAT_CMDL_COMPL
9008 "cmdline_compl",
9009#endif
9010#ifdef FEAT_CMDHIST
9011 "cmdline_hist",
9012#endif
9013#ifdef FEAT_COMMENTS
9014 "comments",
9015#endif
9016#ifdef FEAT_CRYPT
9017 "cryptv",
9018#endif
9019#ifdef FEAT_CSCOPE
9020 "cscope",
9021#endif
9022#ifdef DEBUG
9023 "debug",
9024#endif
9025#ifdef FEAT_CON_DIALOG
9026 "dialog_con",
9027#endif
9028#ifdef FEAT_GUI_DIALOG
9029 "dialog_gui",
9030#endif
9031#ifdef FEAT_DIFF
9032 "diff",
9033#endif
9034#ifdef FEAT_DIGRAPHS
9035 "digraphs",
9036#endif
9037#ifdef FEAT_DND
9038 "dnd",
9039#endif
9040#ifdef FEAT_EMACS_TAGS
9041 "emacs_tags",
9042#endif
9043 "eval", /* always present, of course! */
9044#ifdef FEAT_EX_EXTRA
9045 "ex_extra",
9046#endif
9047#ifdef FEAT_SEARCH_EXTRA
9048 "extra_search",
9049#endif
9050#ifdef FEAT_FKMAP
9051 "farsi",
9052#endif
9053#ifdef FEAT_SEARCHPATH
9054 "file_in_path",
9055#endif
Bram Moolenaar5313dcb2005-02-22 08:56:13 +00009056#if defined(UNIX) && !defined(USE_SYSTEM)
9057 "filterpipe",
9058#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00009059#ifdef FEAT_FIND_ID
9060 "find_in_path",
9061#endif
9062#ifdef FEAT_FOLDING
9063 "folding",
9064#endif
9065#ifdef FEAT_FOOTER
9066 "footer",
9067#endif
9068#if !defined(USE_SYSTEM) && defined(UNIX)
9069 "fork",
9070#endif
9071#ifdef FEAT_GETTEXT
9072 "gettext",
9073#endif
9074#ifdef FEAT_GUI
9075 "gui",
9076#endif
9077#ifdef FEAT_GUI_ATHENA
9078# ifdef FEAT_GUI_NEXTAW
9079 "gui_neXtaw",
9080# else
9081 "gui_athena",
9082# endif
9083#endif
Bram Moolenaar843ee412004-06-30 16:16:41 +00009084#ifdef FEAT_GUI_KDE
9085 "gui_kde",
9086#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00009087#ifdef FEAT_GUI_GTK
9088 "gui_gtk",
9089# ifdef HAVE_GTK2
9090 "gui_gtk2",
9091# endif
9092#endif
9093#ifdef FEAT_GUI_MAC
9094 "gui_mac",
9095#endif
9096#ifdef FEAT_GUI_MOTIF
9097 "gui_motif",
9098#endif
9099#ifdef FEAT_GUI_PHOTON
9100 "gui_photon",
9101#endif
9102#ifdef FEAT_GUI_W16
9103 "gui_win16",
9104#endif
9105#ifdef FEAT_GUI_W32
9106 "gui_win32",
9107#endif
9108#ifdef FEAT_HANGULIN
9109 "hangul_input",
9110#endif
9111#if defined(HAVE_ICONV_H) && defined(USE_ICONV)
9112 "iconv",
9113#endif
9114#ifdef FEAT_INS_EXPAND
9115 "insert_expand",
9116#endif
9117#ifdef FEAT_JUMPLIST
9118 "jumplist",
9119#endif
9120#ifdef FEAT_KEYMAP
9121 "keymap",
9122#endif
9123#ifdef FEAT_LANGMAP
9124 "langmap",
9125#endif
9126#ifdef FEAT_LIBCALL
9127 "libcall",
9128#endif
9129#ifdef FEAT_LINEBREAK
9130 "linebreak",
9131#endif
9132#ifdef FEAT_LISP
9133 "lispindent",
9134#endif
9135#ifdef FEAT_LISTCMDS
9136 "listcmds",
9137#endif
9138#ifdef FEAT_LOCALMAP
9139 "localmap",
9140#endif
9141#ifdef FEAT_MENU
9142 "menu",
9143#endif
9144#ifdef FEAT_SESSION
9145 "mksession",
9146#endif
9147#ifdef FEAT_MODIFY_FNAME
9148 "modify_fname",
9149#endif
9150#ifdef FEAT_MOUSE
9151 "mouse",
9152#endif
9153#ifdef FEAT_MOUSESHAPE
9154 "mouseshape",
9155#endif
9156#if defined(UNIX) || defined(VMS)
9157# ifdef FEAT_MOUSE_DEC
9158 "mouse_dec",
9159# endif
9160# ifdef FEAT_MOUSE_GPM
9161 "mouse_gpm",
9162# endif
9163# ifdef FEAT_MOUSE_JSB
9164 "mouse_jsbterm",
9165# endif
9166# ifdef FEAT_MOUSE_NET
9167 "mouse_netterm",
9168# endif
9169# ifdef FEAT_MOUSE_PTERM
9170 "mouse_pterm",
9171# endif
9172# ifdef FEAT_MOUSE_XTERM
9173 "mouse_xterm",
9174# endif
9175#endif
9176#ifdef FEAT_MBYTE
9177 "multi_byte",
9178#endif
9179#ifdef FEAT_MBYTE_IME
9180 "multi_byte_ime",
9181#endif
9182#ifdef FEAT_MULTI_LANG
9183 "multi_lang",
9184#endif
Bram Moolenaar325b7a22004-07-05 15:58:32 +00009185#ifdef FEAT_MZSCHEME
Bram Moolenaar33570922005-01-25 22:26:29 +00009186#ifndef DYNAMIC_MZSCHEME
Bram Moolenaar325b7a22004-07-05 15:58:32 +00009187 "mzscheme",
9188#endif
Bram Moolenaar33570922005-01-25 22:26:29 +00009189#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00009190#ifdef FEAT_OLE
9191 "ole",
9192#endif
9193#ifdef FEAT_OSFILETYPE
9194 "osfiletype",
9195#endif
9196#ifdef FEAT_PATH_EXTRA
9197 "path_extra",
9198#endif
9199#ifdef FEAT_PERL
9200#ifndef DYNAMIC_PERL
9201 "perl",
9202#endif
9203#endif
9204#ifdef FEAT_PYTHON
9205#ifndef DYNAMIC_PYTHON
9206 "python",
9207#endif
9208#endif
9209#ifdef FEAT_POSTSCRIPT
9210 "postscript",
9211#endif
9212#ifdef FEAT_PRINTER
9213 "printer",
9214#endif
9215#ifdef FEAT_QUICKFIX
9216 "quickfix",
9217#endif
9218#ifdef FEAT_RIGHTLEFT
9219 "rightleft",
9220#endif
9221#if defined(FEAT_RUBY) && !defined(DYNAMIC_RUBY)
9222 "ruby",
9223#endif
9224#ifdef FEAT_SCROLLBIND
9225 "scrollbind",
9226#endif
9227#ifdef FEAT_CMDL_INFO
9228 "showcmd",
9229 "cmdline_info",
9230#endif
9231#ifdef FEAT_SIGNS
9232 "signs",
9233#endif
9234#ifdef FEAT_SMARTINDENT
9235 "smartindent",
9236#endif
9237#ifdef FEAT_SNIFF
9238 "sniff",
9239#endif
9240#ifdef FEAT_STL_OPT
9241 "statusline",
9242#endif
9243#ifdef FEAT_SUN_WORKSHOP
9244 "sun_workshop",
9245#endif
9246#ifdef FEAT_NETBEANS_INTG
9247 "netbeans_intg",
9248#endif
9249#ifdef FEAT_SYN_HL
9250 "syntax",
9251#endif
9252#if defined(USE_SYSTEM) || !defined(UNIX)
9253 "system",
9254#endif
9255#ifdef FEAT_TAG_BINS
9256 "tag_binary",
9257#endif
9258#ifdef FEAT_TAG_OLDSTATIC
9259 "tag_old_static",
9260#endif
9261#ifdef FEAT_TAG_ANYWHITE
9262 "tag_any_white",
9263#endif
9264#ifdef FEAT_TCL
9265# ifndef DYNAMIC_TCL
9266 "tcl",
9267# endif
9268#endif
9269#ifdef TERMINFO
9270 "terminfo",
9271#endif
9272#ifdef FEAT_TERMRESPONSE
9273 "termresponse",
9274#endif
9275#ifdef FEAT_TEXTOBJ
9276 "textobjects",
9277#endif
9278#ifdef HAVE_TGETENT
9279 "tgetent",
9280#endif
9281#ifdef FEAT_TITLE
9282 "title",
9283#endif
9284#ifdef FEAT_TOOLBAR
9285 "toolbar",
9286#endif
9287#ifdef FEAT_USR_CMDS
9288 "user-commands", /* was accidentally included in 5.4 */
9289 "user_commands",
9290#endif
9291#ifdef FEAT_VIMINFO
9292 "viminfo",
9293#endif
9294#ifdef FEAT_VERTSPLIT
9295 "vertsplit",
9296#endif
9297#ifdef FEAT_VIRTUALEDIT
9298 "virtualedit",
9299#endif
9300#ifdef FEAT_VISUAL
9301 "visual",
9302#endif
9303#ifdef FEAT_VISUALEXTRA
9304 "visualextra",
9305#endif
9306#ifdef FEAT_VREPLACE
9307 "vreplace",
9308#endif
9309#ifdef FEAT_WILDIGN
9310 "wildignore",
9311#endif
9312#ifdef FEAT_WILDMENU
9313 "wildmenu",
9314#endif
9315#ifdef FEAT_WINDOWS
9316 "windows",
9317#endif
9318#ifdef FEAT_WAK
9319 "winaltkeys",
9320#endif
9321#ifdef FEAT_WRITEBACKUP
9322 "writebackup",
9323#endif
9324#ifdef FEAT_XIM
9325 "xim",
9326#endif
9327#ifdef FEAT_XFONTSET
9328 "xfontset",
9329#endif
9330#ifdef USE_XSMP
9331 "xsmp",
9332#endif
9333#ifdef USE_XSMP_INTERACT
9334 "xsmp_interact",
9335#endif
9336#ifdef FEAT_XCLIPBOARD
9337 "xterm_clipboard",
9338#endif
9339#ifdef FEAT_XTERM_SAVE
9340 "xterm_save",
9341#endif
9342#if defined(UNIX) && defined(FEAT_X11)
9343 "X11",
9344#endif
9345 NULL
9346 };
9347
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009348 name = get_tv_string(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009349 for (i = 0; has_list[i] != NULL; ++i)
9350 if (STRICMP(name, has_list[i]) == 0)
9351 {
9352 n = TRUE;
9353 break;
9354 }
9355
9356 if (n == FALSE)
9357 {
9358 if (STRNICMP(name, "patch", 5) == 0)
9359 n = has_patch(atoi((char *)name + 5));
9360 else if (STRICMP(name, "vim_starting") == 0)
9361 n = (starting != 0);
9362#ifdef DYNAMIC_TCL
9363 else if (STRICMP(name, "tcl") == 0)
9364 n = tcl_enabled(FALSE);
9365#endif
9366#if defined(USE_ICONV) && defined(DYNAMIC_ICONV)
9367 else if (STRICMP(name, "iconv") == 0)
9368 n = iconv_enabled(FALSE);
9369#endif
Bram Moolenaar33570922005-01-25 22:26:29 +00009370#ifdef DYNAMIC_MZSCHEME
9371 else if (STRICMP(name, "mzscheme") == 0)
9372 n = mzscheme_enabled(FALSE);
9373#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00009374#ifdef DYNAMIC_RUBY
9375 else if (STRICMP(name, "ruby") == 0)
9376 n = ruby_enabled(FALSE);
9377#endif
9378#ifdef DYNAMIC_PYTHON
9379 else if (STRICMP(name, "python") == 0)
9380 n = python_enabled(FALSE);
9381#endif
9382#ifdef DYNAMIC_PERL
9383 else if (STRICMP(name, "perl") == 0)
9384 n = perl_enabled(FALSE);
9385#endif
9386#ifdef FEAT_GUI
9387 else if (STRICMP(name, "gui_running") == 0)
9388 n = (gui.in_use || gui.starting);
9389# ifdef FEAT_GUI_W32
9390 else if (STRICMP(name, "gui_win32s") == 0)
9391 n = gui_is_win32s();
9392# endif
9393# ifdef FEAT_BROWSE
9394 else if (STRICMP(name, "browse") == 0)
9395 n = gui.in_use; /* gui_mch_browse() works when GUI is running */
9396# endif
9397#endif
9398#ifdef FEAT_SYN_HL
9399 else if (STRICMP(name, "syntax_items") == 0)
9400 n = syntax_present(curbuf);
9401#endif
9402#if defined(WIN3264)
9403 else if (STRICMP(name, "win95") == 0)
9404 n = mch_windows95();
9405#endif
Bram Moolenaar35a9aaa2004-10-24 19:23:07 +00009406#ifdef FEAT_NETBEANS_INTG
9407 else if (STRICMP(name, "netbeans_enabled") == 0)
9408 n = usingNetbeans;
9409#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00009410 }
9411
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009412 rettv->vval.v_number = n;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009413}
9414
9415/*
Bram Moolenaare9a41262005-01-15 22:18:47 +00009416 * "has_key()" function
9417 */
9418 static void
9419f_has_key(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00009420 typval_T *argvars;
9421 typval_T *rettv;
Bram Moolenaare9a41262005-01-15 22:18:47 +00009422{
9423 rettv->vval.v_number = 0;
9424 if (argvars[0].v_type != VAR_DICT)
9425 {
9426 EMSG(_(e_dictreq));
9427 return;
9428 }
9429 if (argvars[0].vval.v_dict == NULL)
9430 return;
9431
9432 rettv->vval.v_number = dict_find(argvars[0].vval.v_dict,
Bram Moolenaarce5e58e2005-01-19 22:24:34 +00009433 get_tv_string(&argvars[1]), -1) != NULL;
Bram Moolenaare9a41262005-01-15 22:18:47 +00009434}
9435
9436/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00009437 * "hasmapto()" function
9438 */
9439 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009440f_hasmapto(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00009441 typval_T *argvars;
9442 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009443{
9444 char_u *name;
9445 char_u *mode;
9446 char_u buf[NUMBUFLEN];
9447
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009448 name = get_tv_string(&argvars[0]);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009449 if (argvars[1].v_type == VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009450 mode = (char_u *)"nvo";
9451 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009452 mode = get_tv_string_buf(&argvars[1], buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009453
9454 if (map_to_exists(name, mode))
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009455 rettv->vval.v_number = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009456 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009457 rettv->vval.v_number = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009458}
9459
9460/*
9461 * "histadd()" function
9462 */
9463/*ARGSUSED*/
9464 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009465f_histadd(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00009466 typval_T *argvars;
9467 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009468{
9469#ifdef FEAT_CMDHIST
9470 int histype;
9471 char_u *str;
9472 char_u buf[NUMBUFLEN];
9473#endif
9474
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009475 rettv->vval.v_number = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009476 if (check_restricted() || check_secure())
9477 return;
9478#ifdef FEAT_CMDHIST
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009479 histype = get_histtype(get_tv_string(&argvars[0]));
Bram Moolenaar071d4272004-06-13 20:20:40 +00009480 if (histype >= 0)
9481 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009482 str = get_tv_string_buf(&argvars[1], buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009483 if (*str != NUL)
9484 {
9485 add_to_history(histype, str, FALSE, NUL);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009486 rettv->vval.v_number = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009487 return;
9488 }
9489 }
9490#endif
9491}
9492
9493/*
9494 * "histdel()" function
9495 */
9496/*ARGSUSED*/
9497 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009498f_histdel(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00009499 typval_T *argvars;
9500 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009501{
9502#ifdef FEAT_CMDHIST
9503 int n;
9504 char_u buf[NUMBUFLEN];
9505
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009506 if (argvars[1].v_type == VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009507 /* only one argument: clear entire history */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009508 n = clr_history(get_histtype(get_tv_string(&argvars[0])));
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009509 else if (argvars[1].v_type == VAR_NUMBER)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009510 /* index given: remove that entry */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009511 n = del_history_idx(get_histtype(get_tv_string(&argvars[0])),
9512 (int)get_tv_number(&argvars[1]));
Bram Moolenaar071d4272004-06-13 20:20:40 +00009513 else
9514 /* string given: remove all matching entries */
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009515 n = del_history_entry(get_histtype(get_tv_string(&argvars[0])),
9516 get_tv_string_buf(&argvars[1], buf));
9517 rettv->vval.v_number = n;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009518#else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009519 rettv->vval.v_number = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009520#endif
9521}
9522
9523/*
9524 * "histget()" function
9525 */
9526/*ARGSUSED*/
9527 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009528f_histget(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00009529 typval_T *argvars;
9530 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009531{
9532#ifdef FEAT_CMDHIST
9533 int type;
9534 int idx;
9535
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009536 type = get_histtype(get_tv_string(&argvars[0]));
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009537 if (argvars[1].v_type == VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009538 idx = get_history_idx(type);
9539 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009540 idx = (int)get_tv_number(&argvars[1]);
9541 rettv->vval.v_string = vim_strsave(get_history_entry(type, idx));
Bram Moolenaar071d4272004-06-13 20:20:40 +00009542#else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009543 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009544#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009545 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009546}
9547
9548/*
9549 * "histnr()" function
9550 */
9551/*ARGSUSED*/
9552 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009553f_histnr(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00009554 typval_T *argvars;
9555 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009556{
9557 int i;
9558
9559#ifdef FEAT_CMDHIST
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009560 i = get_histtype(get_tv_string(&argvars[0]));
Bram Moolenaar071d4272004-06-13 20:20:40 +00009561 if (i >= HIST_CMD && i < HIST_COUNT)
9562 i = get_history_idx(i);
9563 else
9564#endif
9565 i = -1;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009566 rettv->vval.v_number = i;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009567}
9568
9569/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00009570 * "highlightID(name)" function
9571 */
9572 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009573f_hlID(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00009574 typval_T *argvars;
9575 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009576{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009577 rettv->vval.v_number = syn_name2id(get_tv_string(&argvars[0]));
Bram Moolenaar071d4272004-06-13 20:20:40 +00009578}
9579
9580/*
Bram Moolenaar0d660222005-01-07 21:51:51 +00009581 * "highlight_exists()" function
9582 */
9583 static void
9584f_hlexists(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00009585 typval_T *argvars;
9586 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +00009587{
9588 rettv->vval.v_number = highlight_exists(get_tv_string(&argvars[0]));
9589}
9590
9591/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00009592 * "hostname()" function
9593 */
9594/*ARGSUSED*/
9595 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009596f_hostname(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00009597 typval_T *argvars;
9598 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009599{
9600 char_u hostname[256];
9601
9602 mch_get_host_name(hostname, 256);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009603 rettv->v_type = VAR_STRING;
9604 rettv->vval.v_string = vim_strsave(hostname);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009605}
9606
9607/*
9608 * iconv() function
9609 */
9610/*ARGSUSED*/
9611 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009612f_iconv(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00009613 typval_T *argvars;
9614 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009615{
9616#ifdef FEAT_MBYTE
9617 char_u buf1[NUMBUFLEN];
9618 char_u buf2[NUMBUFLEN];
9619 char_u *from, *to, *str;
9620 vimconv_T vimconv;
9621#endif
9622
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009623 rettv->v_type = VAR_STRING;
9624 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009625
9626#ifdef FEAT_MBYTE
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009627 str = get_tv_string(&argvars[0]);
9628 from = enc_canonize(enc_skip(get_tv_string_buf(&argvars[1], buf1)));
9629 to = enc_canonize(enc_skip(get_tv_string_buf(&argvars[2], buf2)));
Bram Moolenaar071d4272004-06-13 20:20:40 +00009630 vimconv.vc_type = CONV_NONE;
9631 convert_setup(&vimconv, from, to);
9632
9633 /* If the encodings are equal, no conversion needed. */
9634 if (vimconv.vc_type == CONV_NONE)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009635 rettv->vval.v_string = vim_strsave(str);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009636 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009637 rettv->vval.v_string = string_convert(&vimconv, str, NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009638
9639 convert_setup(&vimconv, NULL, NULL);
9640 vim_free(from);
9641 vim_free(to);
9642#endif
9643}
9644
9645/*
9646 * "indent()" function
9647 */
9648 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009649f_indent(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00009650 typval_T *argvars;
9651 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009652{
9653 linenr_T lnum;
9654
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009655 lnum = get_tv_lnum(argvars);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009656 if (lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009657 rettv->vval.v_number = get_indent_lnum(lnum);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009658 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009659 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009660}
9661
Bram Moolenaar8a283e52005-01-06 23:28:25 +00009662/*
9663 * "index()" function
9664 */
9665 static void
9666f_index(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00009667 typval_T *argvars;
9668 typval_T *rettv;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00009669{
Bram Moolenaar33570922005-01-25 22:26:29 +00009670 list_T *l;
9671 listitem_T *item;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00009672 long idx = 0;
9673 int ic = FALSE;
9674
9675 rettv->vval.v_number = -1;
9676 if (argvars[0].v_type != VAR_LIST)
9677 {
9678 EMSG(_(e_listreq));
9679 return;
9680 }
9681 l = argvars[0].vval.v_list;
9682 if (l != NULL)
9683 {
Bram Moolenaar758711c2005-02-02 23:11:38 +00009684 item = l->lv_first;
Bram Moolenaar8a283e52005-01-06 23:28:25 +00009685 if (argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00009686 {
Bram Moolenaar758711c2005-02-02 23:11:38 +00009687 /* Start at specified item. Use the cached index that list_find()
9688 * sets, so that a negative number also works. */
9689 item = list_find(l, get_tv_number(&argvars[2]));
9690 idx = l->lv_idx;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +00009691 if (argvars[3].v_type != VAR_UNKNOWN)
9692 ic = get_tv_number(&argvars[3]);
9693 }
Bram Moolenaar8a283e52005-01-06 23:28:25 +00009694
Bram Moolenaar758711c2005-02-02 23:11:38 +00009695 for ( ; item != NULL; item = item->li_next, ++idx)
9696 if (tv_equal(&item->li_tv, &argvars[1], ic))
Bram Moolenaar8a283e52005-01-06 23:28:25 +00009697 {
9698 rettv->vval.v_number = idx;
9699 break;
9700 }
9701 }
9702}
9703
Bram Moolenaar071d4272004-06-13 20:20:40 +00009704static int inputsecret_flag = 0;
9705
9706/*
9707 * "input()" function
9708 * Also handles inputsecret() when inputsecret is set.
9709 */
9710 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009711f_input(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00009712 typval_T *argvars;
9713 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009714{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009715 char_u *prompt = get_tv_string(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009716 char_u *p = NULL;
9717 int c;
9718 char_u buf[NUMBUFLEN];
9719 int cmd_silent_save = cmd_silent;
9720
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009721 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009722
9723#ifdef NO_CONSOLE_INPUT
9724 /* While starting up, there is no place to enter text. */
9725 if (no_console_input())
9726 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009727 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009728 return;
9729 }
9730#endif
9731
9732 cmd_silent = FALSE; /* Want to see the prompt. */
9733 if (prompt != NULL)
9734 {
9735 /* Only the part of the message after the last NL is considered as
9736 * prompt for the command line */
9737 p = vim_strrchr(prompt, '\n');
9738 if (p == NULL)
9739 p = prompt;
9740 else
9741 {
9742 ++p;
9743 c = *p;
9744 *p = NUL;
9745 msg_start();
9746 msg_clr_eos();
9747 msg_puts_attr(prompt, echo_attr);
9748 msg_didout = FALSE;
9749 msg_starthere();
9750 *p = c;
9751 }
9752 cmdline_row = msg_row;
9753 }
9754
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009755 if (argvars[1].v_type != VAR_UNKNOWN)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009756 stuffReadbuffSpec(get_tv_string_buf(&argvars[1], buf));
Bram Moolenaar071d4272004-06-13 20:20:40 +00009757
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009758 rettv->vval.v_string =
Bram Moolenaar071d4272004-06-13 20:20:40 +00009759 getcmdline_prompt(inputsecret_flag ? NUL : '@', p, echo_attr);
9760
9761 /* since the user typed this, no need to wait for return */
9762 need_wait_return = FALSE;
9763 msg_didout = FALSE;
9764 cmd_silent = cmd_silent_save;
9765}
9766
9767/*
9768 * "inputdialog()" function
9769 */
9770 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009771f_inputdialog(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00009772 typval_T *argvars;
9773 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009774{
9775#if defined(FEAT_GUI_TEXTDIALOG)
9776 /* Use a GUI dialog if the GUI is running and 'c' is not in 'guioptions' */
9777 if (gui.in_use && vim_strchr(p_go, GO_CONDIALOG) == NULL)
9778 {
9779 char_u *message;
9780 char_u buf[NUMBUFLEN];
9781
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009782 message = get_tv_string(&argvars[0]);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009783 if (argvars[1].v_type != VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +00009784 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009785 STRNCPY(IObuff, get_tv_string_buf(&argvars[1], buf), IOSIZE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009786 IObuff[IOSIZE - 1] = NUL;
9787 }
9788 else
9789 IObuff[0] = NUL;
9790 if (do_dialog(VIM_QUESTION, NULL, message, (char_u *)_("&OK\n&Cancel"),
9791 1, IObuff) == 1)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009792 rettv->vval.v_string = vim_strsave(IObuff);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009793 else
9794 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009795 if (argvars[1].v_type != VAR_UNKNOWN
9796 && argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009797 rettv->vval.v_string = vim_strsave(
9798 get_tv_string_buf(&argvars[2], buf));
Bram Moolenaar071d4272004-06-13 20:20:40 +00009799 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009800 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009801 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009802 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009803 }
9804 else
9805#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009806 f_input(argvars, rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009807}
9808
9809static garray_T ga_userinput = {0, 0, sizeof(tasave_T), 4, NULL};
9810
9811/*
9812 * "inputrestore()" function
9813 */
9814/*ARGSUSED*/
9815 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009816f_inputrestore(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00009817 typval_T *argvars;
9818 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009819{
9820 if (ga_userinput.ga_len > 0)
9821 {
9822 --ga_userinput.ga_len;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009823 restore_typeahead((tasave_T *)(ga_userinput.ga_data)
9824 + ga_userinput.ga_len);
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009825 rettv->vval.v_number = 0; /* OK */
Bram Moolenaar071d4272004-06-13 20:20:40 +00009826 }
9827 else if (p_verbose > 1)
9828 {
9829 msg((char_u *)_("called inputrestore() more often than inputsave()"));
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009830 rettv->vval.v_number = 1; /* Failed */
Bram Moolenaar071d4272004-06-13 20:20:40 +00009831 }
9832}
9833
9834/*
9835 * "inputsave()" function
9836 */
9837/*ARGSUSED*/
9838 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009839f_inputsave(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00009840 typval_T *argvars;
9841 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009842{
9843 /* Add an entry to the stack of typehead storage. */
9844 if (ga_grow(&ga_userinput, 1) == OK)
9845 {
9846 save_typeahead((tasave_T *)(ga_userinput.ga_data)
9847 + ga_userinput.ga_len);
9848 ++ga_userinput.ga_len;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009849 rettv->vval.v_number = 0; /* OK */
Bram Moolenaar071d4272004-06-13 20:20:40 +00009850 }
9851 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009852 rettv->vval.v_number = 1; /* Failed */
Bram Moolenaar071d4272004-06-13 20:20:40 +00009853}
9854
9855/*
9856 * "inputsecret()" function
9857 */
9858 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009859f_inputsecret(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00009860 typval_T *argvars;
9861 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009862{
9863 ++cmdline_star;
9864 ++inputsecret_flag;
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009865 f_input(argvars, rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +00009866 --cmdline_star;
9867 --inputsecret_flag;
9868}
9869
9870/*
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009871 * "insert()" function
9872 */
9873 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009874f_insert(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00009875 typval_T *argvars;
9876 typval_T *rettv;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009877{
9878 long before = 0;
Bram Moolenaar33570922005-01-25 22:26:29 +00009879 listitem_T *item;
9880 list_T *l;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009881
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00009882 rettv->vval.v_number = 0;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009883 if (argvars[0].v_type != VAR_LIST)
Bram Moolenaar0d660222005-01-07 21:51:51 +00009884 EMSG2(_(e_listarg), "insert()");
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00009885 else if ((l = argvars[0].vval.v_list) != NULL
9886 && !tv_check_lock(l->lv_lock, (char_u *)"insert()"))
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009887 {
9888 if (argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009889 before = get_tv_number(&argvars[2]);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009890
Bram Moolenaar758711c2005-02-02 23:11:38 +00009891 if (before == l->lv_len)
9892 item = NULL;
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009893 else
9894 {
Bram Moolenaar758711c2005-02-02 23:11:38 +00009895 item = list_find(l, before);
9896 if (item == NULL)
9897 {
9898 EMSGN(_(e_listidx), before);
9899 l = NULL;
9900 }
9901 }
9902 if (l != NULL)
9903 {
Bram Moolenaar8a283e52005-01-06 23:28:25 +00009904 list_insert_tv(l, &argvars[1], item);
9905 ++l->lv_refcount;
9906 copy_tv(&argvars[0], rettv);
Bram Moolenaar49cd9572005-01-03 21:06:01 +00009907 }
9908 }
9909}
9910
9911/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00009912 * "isdirectory()" function
9913 */
9914 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009915f_isdirectory(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +00009916 typval_T *argvars;
9917 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00009918{
Bram Moolenaarc70646c2005-01-04 21:52:38 +00009919 rettv->vval.v_number = mch_isdir(get_tv_string(&argvars[0]));
Bram Moolenaar071d4272004-06-13 20:20:40 +00009920}
9921
Bram Moolenaar2e6aff32005-01-31 19:25:36 +00009922/*
9923 * Return TRUE if typeval "tv" is locked: Either tha value is locked itself or
9924 * it refers to a List or Dictionary that is locked.
9925 */
9926 static int
9927tv_islocked(tv)
9928 typval_T *tv;
9929{
9930 return (tv->v_lock & VAR_LOCKED)
9931 || (tv->v_type == VAR_LIST
9932 && tv->vval.v_list != NULL
9933 && (tv->vval.v_list->lv_lock & VAR_LOCKED))
9934 || (tv->v_type == VAR_DICT
9935 && tv->vval.v_dict != NULL
9936 && (tv->vval.v_dict->dv_lock & VAR_LOCKED));
9937}
9938
9939/*
9940 * "islocked()" function
9941 */
9942 static void
9943f_islocked(argvars, rettv)
9944 typval_T *argvars;
9945 typval_T *rettv;
9946{
9947 lval_T lv;
9948 char_u *end;
9949 dictitem_T *di;
9950
9951 rettv->vval.v_number = -1;
9952 end = get_lval(get_tv_string(&argvars[0]), NULL, &lv, FALSE, FALSE, FALSE);
9953 if (end != NULL && lv.ll_name != NULL)
9954 {
9955 if (*end != NUL)
9956 EMSG(_(e_trailing));
9957 else
9958 {
9959 if (lv.ll_tv == NULL)
9960 {
9961 if (check_changedtick(lv.ll_name))
9962 rettv->vval.v_number = 1; /* always locked */
9963 else
9964 {
9965 di = find_var(lv.ll_name, NULL);
9966 if (di != NULL)
9967 {
9968 /* Consider a variable locked when:
9969 * 1. the variable itself is locked
9970 * 2. the value of the variable is locked.
9971 * 3. the List or Dict value is locked.
9972 */
9973 rettv->vval.v_number = ((di->di_flags & DI_FLAGS_LOCK)
9974 || tv_islocked(&di->di_tv));
9975 }
9976 }
9977 }
9978 else if (lv.ll_range)
9979 EMSG(_("E745: Range not allowed"));
9980 else if (lv.ll_newkey != NULL)
9981 EMSG2(_(e_dictkey), lv.ll_newkey);
9982 else if (lv.ll_list != NULL)
9983 /* List item. */
9984 rettv->vval.v_number = tv_islocked(&lv.ll_li->li_tv);
9985 else
9986 /* Dictionary item. */
9987 rettv->vval.v_number = tv_islocked(&lv.ll_di->di_tv);
9988 }
9989 }
9990
9991 clear_lval(&lv);
9992}
9993
Bram Moolenaar33570922005-01-25 22:26:29 +00009994static void dict_list __ARGS((typval_T *argvars, typval_T *rettv, int what));
Bram Moolenaar8c711452005-01-14 21:53:12 +00009995
9996/*
9997 * Turn a dict into a list:
9998 * "what" == 0: list of keys
9999 * "what" == 1: list of values
10000 * "what" == 2: list of items
10001 */
10002 static void
10003dict_list(argvars, rettv, what)
Bram Moolenaar33570922005-01-25 22:26:29 +000010004 typval_T *argvars;
10005 typval_T *rettv;
Bram Moolenaar8c711452005-01-14 21:53:12 +000010006 int what;
10007{
Bram Moolenaar33570922005-01-25 22:26:29 +000010008 list_T *l;
10009 list_T *l2;
10010 dictitem_T *di;
10011 hashitem_T *hi;
10012 listitem_T *li;
10013 listitem_T *li2;
10014 dict_T *d;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000010015 int todo;
Bram Moolenaar8c711452005-01-14 21:53:12 +000010016
10017 rettv->vval.v_number = 0;
10018 if (argvars[0].v_type != VAR_DICT)
10019 {
10020 EMSG(_(e_dictreq));
10021 return;
10022 }
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000010023 if ((d = argvars[0].vval.v_dict) == NULL)
Bram Moolenaar8c711452005-01-14 21:53:12 +000010024 return;
10025
10026 l = list_alloc();
10027 if (l == NULL)
10028 return;
10029 rettv->v_type = VAR_LIST;
10030 rettv->vval.v_list = l;
10031 ++l->lv_refcount;
10032
Bram Moolenaar33570922005-01-25 22:26:29 +000010033 todo = d->dv_hashtab.ht_used;
10034 for (hi = d->dv_hashtab.ht_array; todo > 0; ++hi)
Bram Moolenaar8c711452005-01-14 21:53:12 +000010035 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000010036 if (!HASHITEM_EMPTY(hi))
Bram Moolenaar8c711452005-01-14 21:53:12 +000010037 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000010038 --todo;
10039 di = HI2DI(hi);
Bram Moolenaar8c711452005-01-14 21:53:12 +000010040
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000010041 li = listitem_alloc();
10042 if (li == NULL)
Bram Moolenaar8c711452005-01-14 21:53:12 +000010043 break;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000010044 list_append(l, li);
Bram Moolenaar8c711452005-01-14 21:53:12 +000010045
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000010046 if (what == 0)
10047 {
10048 /* keys() */
10049 li->li_tv.v_type = VAR_STRING;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000010050 li->li_tv.v_lock = 0;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000010051 li->li_tv.vval.v_string = vim_strsave(di->di_key);
10052 }
10053 else if (what == 1)
10054 {
10055 /* values() */
10056 copy_tv(&di->di_tv, &li->li_tv);
10057 }
10058 else
10059 {
10060 /* items() */
10061 l2 = list_alloc();
10062 li->li_tv.v_type = VAR_LIST;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000010063 li->li_tv.v_lock = 0;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000010064 li->li_tv.vval.v_list = l2;
10065 if (l2 == NULL)
10066 break;
10067 ++l2->lv_refcount;
10068
10069 li2 = listitem_alloc();
10070 if (li2 == NULL)
10071 break;
10072 list_append(l2, li2);
10073 li2->li_tv.v_type = VAR_STRING;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000010074 li2->li_tv.v_lock = 0;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000010075 li2->li_tv.vval.v_string = vim_strsave(di->di_key);
10076
10077 li2 = listitem_alloc();
10078 if (li2 == NULL)
10079 break;
10080 list_append(l2, li2);
10081 copy_tv(&di->di_tv, &li2->li_tv);
10082 }
Bram Moolenaar8c711452005-01-14 21:53:12 +000010083 }
10084 }
10085}
10086
10087/*
10088 * "items(dict)" function
10089 */
10090 static void
10091f_items(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010092 typval_T *argvars;
10093 typval_T *rettv;
Bram Moolenaar8c711452005-01-14 21:53:12 +000010094{
10095 dict_list(argvars, rettv, 2);
10096}
10097
Bram Moolenaar071d4272004-06-13 20:20:40 +000010098/*
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000010099 * "join()" function
10100 */
10101 static void
10102f_join(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010103 typval_T *argvars;
10104 typval_T *rettv;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000010105{
10106 garray_T ga;
10107 char_u *sep;
10108
10109 rettv->vval.v_number = 0;
10110 if (argvars[0].v_type != VAR_LIST)
10111 {
10112 EMSG(_(e_listreq));
10113 return;
10114 }
10115 if (argvars[0].vval.v_list == NULL)
10116 return;
10117 if (argvars[1].v_type == VAR_UNKNOWN)
10118 sep = (char_u *)" ";
10119 else
10120 sep = get_tv_string(&argvars[1]);
10121
10122 ga_init2(&ga, (int)sizeof(char), 80);
10123 list_join(&ga, argvars[0].vval.v_list, sep, TRUE);
10124 ga_append(&ga, NUL);
10125
10126 rettv->v_type = VAR_STRING;
10127 rettv->vval.v_string = (char_u *)ga.ga_data;
10128}
10129
10130/*
Bram Moolenaar8c711452005-01-14 21:53:12 +000010131 * "keys()" function
10132 */
10133 static void
10134f_keys(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010135 typval_T *argvars;
10136 typval_T *rettv;
Bram Moolenaar8c711452005-01-14 21:53:12 +000010137{
10138 dict_list(argvars, rettv, 0);
10139}
10140
10141/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000010142 * "last_buffer_nr()" function.
10143 */
10144/*ARGSUSED*/
10145 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010146f_last_buffer_nr(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010147 typval_T *argvars;
10148 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010149{
10150 int n = 0;
10151 buf_T *buf;
10152
10153 for (buf = firstbuf; buf != NULL; buf = buf->b_next)
10154 if (n < buf->b_fnum)
10155 n = buf->b_fnum;
10156
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010157 rettv->vval.v_number = n;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010158}
10159
10160/*
10161 * "len()" function
10162 */
10163 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010164f_len(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010165 typval_T *argvars;
10166 typval_T *rettv;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010167{
10168 switch (argvars[0].v_type)
10169 {
10170 case VAR_STRING:
10171 case VAR_NUMBER:
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010172 rettv->vval.v_number = (varnumber_T)STRLEN(
10173 get_tv_string(&argvars[0]));
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010174 break;
10175 case VAR_LIST:
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010176 rettv->vval.v_number = list_len(argvars[0].vval.v_list);
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010177 break;
Bram Moolenaare9a41262005-01-15 22:18:47 +000010178 case VAR_DICT:
10179 rettv->vval.v_number = dict_len(argvars[0].vval.v_dict);
10180 break;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010181 default:
Bram Moolenaare49b69a2005-01-08 16:11:57 +000010182 EMSG(_("E701: Invalid type for len()"));
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010183 break;
10184 }
10185}
10186
Bram Moolenaar33570922005-01-25 22:26:29 +000010187static void libcall_common __ARGS((typval_T *argvars, typval_T *rettv, int type));
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010188
10189 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010190libcall_common(argvars, rettv, type)
Bram Moolenaar33570922005-01-25 22:26:29 +000010191 typval_T *argvars;
10192 typval_T *rettv;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010193 int type;
10194{
10195#ifdef FEAT_LIBCALL
10196 char_u *string_in;
10197 char_u **string_result;
10198 int nr_result;
10199#endif
10200
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010201 rettv->v_type = type;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010202 if (type == VAR_NUMBER)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010203 rettv->vval.v_number = 0;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010204 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010205 rettv->vval.v_string = NULL;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010206
10207 if (check_restricted() || check_secure())
10208 return;
10209
10210#ifdef FEAT_LIBCALL
10211 /* The first two args must be strings, otherwise its meaningless */
10212 if (argvars[0].v_type == VAR_STRING && argvars[1].v_type == VAR_STRING)
10213 {
Bram Moolenaar758711c2005-02-02 23:11:38 +000010214 string_in = NULL;
10215 if (argvars[2].v_type == VAR_STRING)
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010216 string_in = argvars[2].vval.v_string;
10217 if (type == VAR_NUMBER)
10218 string_result = NULL;
10219 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010220 string_result = &rettv->vval.v_string;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010221 if (mch_libcall(argvars[0].vval.v_string,
10222 argvars[1].vval.v_string,
10223 string_in,
10224 argvars[2].vval.v_number,
10225 string_result,
10226 &nr_result) == OK
10227 && type == VAR_NUMBER)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010228 rettv->vval.v_number = nr_result;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010229 }
10230#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000010231}
10232
10233/*
Bram Moolenaar0d660222005-01-07 21:51:51 +000010234 * "libcall()" function
10235 */
10236 static void
10237f_libcall(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010238 typval_T *argvars;
10239 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000010240{
10241 libcall_common(argvars, rettv, VAR_STRING);
10242}
10243
10244/*
10245 * "libcallnr()" function
10246 */
10247 static void
10248f_libcallnr(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010249 typval_T *argvars;
10250 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000010251{
10252 libcall_common(argvars, rettv, VAR_NUMBER);
10253}
10254
10255/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000010256 * "line(string)" function
10257 */
10258 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010259f_line(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010260 typval_T *argvars;
10261 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010262{
10263 linenr_T lnum = 0;
10264 pos_T *fp;
10265
10266 fp = var2fpos(&argvars[0], TRUE);
10267 if (fp != NULL)
10268 lnum = fp->lnum;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010269 rettv->vval.v_number = lnum;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010270}
10271
10272/*
10273 * "line2byte(lnum)" function
10274 */
10275/*ARGSUSED*/
10276 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010277f_line2byte(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010278 typval_T *argvars;
10279 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010280{
10281#ifndef FEAT_BYTEOFF
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010282 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010283#else
10284 linenr_T lnum;
10285
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010286 lnum = get_tv_lnum(argvars);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010287 if (lnum < 1 || lnum > curbuf->b_ml.ml_line_count + 1)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010288 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010289 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010290 rettv->vval.v_number = ml_find_line_or_offset(curbuf, lnum, NULL);
10291 if (rettv->vval.v_number >= 0)
10292 ++rettv->vval.v_number;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010293#endif
10294}
10295
10296/*
10297 * "lispindent(lnum)" function
10298 */
10299 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010300f_lispindent(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010301 typval_T *argvars;
10302 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010303{
10304#ifdef FEAT_LISP
10305 pos_T pos;
10306 linenr_T lnum;
10307
10308 pos = curwin->w_cursor;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010309 lnum = get_tv_lnum(argvars);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010310 if (lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count)
10311 {
10312 curwin->w_cursor.lnum = lnum;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010313 rettv->vval.v_number = get_lisp_indent();
Bram Moolenaar071d4272004-06-13 20:20:40 +000010314 curwin->w_cursor = pos;
10315 }
10316 else
10317#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010318 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010319}
10320
10321/*
10322 * "localtime()" function
10323 */
10324/*ARGSUSED*/
10325 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010326f_localtime(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010327 typval_T *argvars;
10328 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010329{
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010330 rettv->vval.v_number = (varnumber_T)time(NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010331}
10332
Bram Moolenaar33570922005-01-25 22:26:29 +000010333static void get_maparg __ARGS((typval_T *argvars, typval_T *rettv, int exact));
Bram Moolenaar071d4272004-06-13 20:20:40 +000010334
10335 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010336get_maparg(argvars, rettv, exact)
Bram Moolenaar33570922005-01-25 22:26:29 +000010337 typval_T *argvars;
10338 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010339 int exact;
10340{
10341 char_u *keys;
10342 char_u *which;
10343 char_u buf[NUMBUFLEN];
10344 char_u *keys_buf = NULL;
10345 char_u *rhs;
10346 int mode;
10347 garray_T ga;
10348
10349 /* return empty string for failure */
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010350 rettv->v_type = VAR_STRING;
10351 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010352
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010353 keys = get_tv_string(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010354 if (*keys == NUL)
10355 return;
10356
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010357 if (argvars[1].v_type != VAR_UNKNOWN)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010358 which = get_tv_string_buf(&argvars[1], buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010359 else
10360 which = (char_u *)"";
10361 mode = get_map_mode(&which, 0);
10362
10363 keys = replace_termcodes(keys, &keys_buf, TRUE, TRUE);
10364 rhs = check_map(keys, mode, exact);
10365 vim_free(keys_buf);
10366 if (rhs != NULL)
10367 {
10368 ga_init(&ga);
10369 ga.ga_itemsize = 1;
10370 ga.ga_growsize = 40;
10371
10372 while (*rhs != NUL)
10373 ga_concat(&ga, str2special(&rhs, FALSE));
10374
10375 ga_append(&ga, NUL);
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010376 rettv->vval.v_string = (char_u *)ga.ga_data;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010377 }
10378}
10379
10380/*
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000010381 * "map()" function
10382 */
10383 static void
10384f_map(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010385 typval_T *argvars;
10386 typval_T *rettv;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000010387{
10388 filter_map(argvars, rettv, TRUE);
10389}
10390
10391/*
Bram Moolenaar0d660222005-01-07 21:51:51 +000010392 * "maparg()" function
Bram Moolenaar071d4272004-06-13 20:20:40 +000010393 */
10394 static void
Bram Moolenaar0d660222005-01-07 21:51:51 +000010395f_maparg(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010396 typval_T *argvars;
10397 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010398{
Bram Moolenaar0d660222005-01-07 21:51:51 +000010399 get_maparg(argvars, rettv, TRUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010400}
10401
10402/*
Bram Moolenaar0d660222005-01-07 21:51:51 +000010403 * "mapcheck()" function
Bram Moolenaar071d4272004-06-13 20:20:40 +000010404 */
10405 static void
Bram Moolenaar0d660222005-01-07 21:51:51 +000010406f_mapcheck(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010407 typval_T *argvars;
10408 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010409{
Bram Moolenaar0d660222005-01-07 21:51:51 +000010410 get_maparg(argvars, rettv, FALSE);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010411}
10412
Bram Moolenaar33570922005-01-25 22:26:29 +000010413static void find_some_match __ARGS((typval_T *argvars, typval_T *rettv, int start));
Bram Moolenaar071d4272004-06-13 20:20:40 +000010414
10415 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010416find_some_match(argvars, rettv, type)
Bram Moolenaar33570922005-01-25 22:26:29 +000010417 typval_T *argvars;
10418 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010419 int type;
10420{
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000010421 char_u *str = NULL;
10422 char_u *expr = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010423 char_u *pat;
10424 regmatch_T regmatch;
10425 char_u patbuf[NUMBUFLEN];
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000010426 char_u strbuf[NUMBUFLEN];
Bram Moolenaar071d4272004-06-13 20:20:40 +000010427 char_u *save_cpo;
10428 long start = 0;
Bram Moolenaar89cb5e02004-07-19 20:55:54 +000010429 long nth = 1;
Bram Moolenaar81bf7082005-02-12 14:31:42 +000010430 int match = 0;
Bram Moolenaar33570922005-01-25 22:26:29 +000010431 list_T *l = NULL;
10432 listitem_T *li = NULL;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000010433 long idx = 0;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000010434 char_u *tofree = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010435
10436 /* Make 'cpoptions' empty, the 'l' flag should not be used here. */
10437 save_cpo = p_cpo;
10438 p_cpo = (char_u *)"";
10439
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000010440 rettv->vval.v_number = -1;
10441 if (type == 3)
10442 {
10443 /* return empty list when there are no matches */
10444 if ((rettv->vval.v_list = list_alloc()) == NULL)
10445 goto theend;
10446 rettv->v_type = VAR_LIST;
10447 ++rettv->vval.v_list->lv_refcount;
10448 }
10449 else if (type == 2)
Bram Moolenaar071d4272004-06-13 20:20:40 +000010450 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010451 rettv->v_type = VAR_STRING;
10452 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010453 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000010454
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000010455 if (argvars[0].v_type == VAR_LIST)
10456 {
10457 if ((l = argvars[0].vval.v_list) == NULL)
10458 goto theend;
10459 li = l->lv_first;
10460 }
10461 else
10462 expr = str = get_tv_string(&argvars[0]);
10463
10464 pat = get_tv_string_buf(&argvars[1], patbuf);
10465
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010466 if (argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +000010467 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010468 start = get_tv_number(&argvars[2]);
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000010469 if (l != NULL)
10470 {
10471 li = list_find(l, start);
10472 if (li == NULL)
10473 goto theend;
Bram Moolenaar758711c2005-02-02 23:11:38 +000010474 idx = l->lv_idx; /* use the cached index */
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000010475 }
10476 else
10477 {
10478 if (start < 0)
10479 start = 0;
10480 if (start > (long)STRLEN(str))
10481 goto theend;
10482 str += start;
10483 }
Bram Moolenaar89cb5e02004-07-19 20:55:54 +000010484
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010485 if (argvars[3].v_type != VAR_UNKNOWN)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010486 nth = get_tv_number(&argvars[3]);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010487 }
10488
10489 regmatch.regprog = vim_regcomp(pat, RE_MAGIC + RE_STRING);
10490 if (regmatch.regprog != NULL)
10491 {
10492 regmatch.rm_ic = p_ic;
Bram Moolenaar89cb5e02004-07-19 20:55:54 +000010493
10494 while (1)
10495 {
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000010496 if (l != NULL)
10497 {
10498 if (li == NULL)
10499 {
10500 match = FALSE;
10501 break;
10502 }
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000010503 vim_free(tofree);
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000010504 str = echo_string(&li->li_tv, &tofree, strbuf);
Bram Moolenaar81bf7082005-02-12 14:31:42 +000010505 if (str == NULL)
10506 break;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000010507 }
10508
Bram Moolenaar89cb5e02004-07-19 20:55:54 +000010509 match = vim_regexec_nl(&regmatch, str, (colnr_T)0);
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000010510
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000010511 if (match && --nth <= 0)
Bram Moolenaar89cb5e02004-07-19 20:55:54 +000010512 break;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000010513 if (l == NULL && !match)
10514 break;
10515
Bram Moolenaar89cb5e02004-07-19 20:55:54 +000010516 /* Advance to just after the match. */
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000010517 if (l != NULL)
10518 {
10519 li = li->li_next;
10520 ++idx;
10521 }
10522 else
10523 {
Bram Moolenaar89cb5e02004-07-19 20:55:54 +000010524#ifdef FEAT_MBYTE
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000010525 str = regmatch.startp[0] + mb_ptr2len_check(regmatch.startp[0]);
Bram Moolenaar89cb5e02004-07-19 20:55:54 +000010526#else
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000010527 str = regmatch.startp[0] + 1;
Bram Moolenaar89cb5e02004-07-19 20:55:54 +000010528#endif
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000010529 }
Bram Moolenaar89cb5e02004-07-19 20:55:54 +000010530 }
10531
10532 if (match)
Bram Moolenaar071d4272004-06-13 20:20:40 +000010533 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000010534 if (type == 3)
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000010535 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000010536 int i;
10537
10538 /* return list with matched string and submatches */
10539 for (i = 0; i < NSUBEXP; ++i)
10540 {
10541 if (regmatch.endp[i] == NULL)
10542 break;
10543 li = listitem_alloc();
10544 if (li == NULL)
10545 break;
10546 li->li_tv.v_type = VAR_STRING;
10547 li->li_tv.v_lock = 0;
10548 li->li_tv.vval.v_string = vim_strnsave(regmatch.startp[i],
10549 (int)(regmatch.endp[i] - regmatch.startp[i]));
10550 list_append(rettv->vval.v_list, li);
10551 }
10552 }
10553 else if (type == 2)
10554 {
10555 /* return matched string */
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000010556 if (l != NULL)
10557 copy_tv(&li->li_tv, rettv);
10558 else
10559 rettv->vval.v_string = vim_strnsave(regmatch.startp[0],
Bram Moolenaar071d4272004-06-13 20:20:40 +000010560 (int)(regmatch.endp[0] - regmatch.startp[0]));
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000010561 }
10562 else if (l != NULL)
10563 rettv->vval.v_number = idx;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010564 else
10565 {
10566 if (type != 0)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010567 rettv->vval.v_number =
Bram Moolenaar071d4272004-06-13 20:20:40 +000010568 (varnumber_T)(regmatch.startp[0] - str);
10569 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010570 rettv->vval.v_number =
Bram Moolenaar071d4272004-06-13 20:20:40 +000010571 (varnumber_T)(regmatch.endp[0] - str);
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010572 rettv->vval.v_number += str - expr;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010573 }
10574 }
10575 vim_free(regmatch.regprog);
10576 }
10577
10578theend:
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000010579 vim_free(tofree);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010580 p_cpo = save_cpo;
10581}
10582
10583/*
Bram Moolenaar0d660222005-01-07 21:51:51 +000010584 * "match()" function
10585 */
10586 static void
10587f_match(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010588 typval_T *argvars;
10589 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000010590{
10591 find_some_match(argvars, rettv, 1);
10592}
10593
10594/*
10595 * "matchend()" function
10596 */
10597 static void
10598f_matchend(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010599 typval_T *argvars;
10600 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000010601{
10602 find_some_match(argvars, rettv, 0);
10603}
10604
10605/*
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000010606 * "matchlist()" function
10607 */
10608 static void
10609f_matchlist(argvars, rettv)
10610 typval_T *argvars;
10611 typval_T *rettv;
10612{
10613 find_some_match(argvars, rettv, 3);
10614}
10615
10616/*
Bram Moolenaar0d660222005-01-07 21:51:51 +000010617 * "matchstr()" function
10618 */
10619 static void
10620f_matchstr(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010621 typval_T *argvars;
10622 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000010623{
10624 find_some_match(argvars, rettv, 2);
10625}
10626
Bram Moolenaar33570922005-01-25 22:26:29 +000010627static void max_min __ARGS((typval_T *argvars, typval_T *rettv, int domax));
Bram Moolenaar6cc16192005-01-08 21:49:45 +000010628
10629 static void
10630max_min(argvars, rettv, domax)
Bram Moolenaar33570922005-01-25 22:26:29 +000010631 typval_T *argvars;
10632 typval_T *rettv;
Bram Moolenaar6cc16192005-01-08 21:49:45 +000010633 int domax;
10634{
Bram Moolenaar6cc16192005-01-08 21:49:45 +000010635 long n = 0;
10636 long i;
10637
10638 if (argvars[0].v_type == VAR_LIST)
10639 {
Bram Moolenaar33570922005-01-25 22:26:29 +000010640 list_T *l;
10641 listitem_T *li;
Bram Moolenaare9a41262005-01-15 22:18:47 +000010642
Bram Moolenaar6cc16192005-01-08 21:49:45 +000010643 l = argvars[0].vval.v_list;
10644 if (l != NULL)
10645 {
10646 li = l->lv_first;
10647 if (li != NULL)
10648 {
10649 n = get_tv_number(&li->li_tv);
10650 while (1)
10651 {
10652 li = li->li_next;
10653 if (li == NULL)
10654 break;
10655 i = get_tv_number(&li->li_tv);
10656 if (domax ? i > n : i < n)
10657 n = i;
10658 }
10659 }
10660 }
10661 }
Bram Moolenaare9a41262005-01-15 22:18:47 +000010662 else if (argvars[0].v_type == VAR_DICT)
10663 {
Bram Moolenaar33570922005-01-25 22:26:29 +000010664 dict_T *d;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000010665 int first = TRUE;
Bram Moolenaar33570922005-01-25 22:26:29 +000010666 hashitem_T *hi;
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000010667 int todo;
Bram Moolenaare9a41262005-01-15 22:18:47 +000010668
10669 d = argvars[0].vval.v_dict;
10670 if (d != NULL)
10671 {
Bram Moolenaar33570922005-01-25 22:26:29 +000010672 todo = d->dv_hashtab.ht_used;
10673 for (hi = d->dv_hashtab.ht_array; todo > 0; ++hi)
Bram Moolenaare9a41262005-01-15 22:18:47 +000010674 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000010675 if (!HASHITEM_EMPTY(hi))
Bram Moolenaare9a41262005-01-15 22:18:47 +000010676 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000010677 --todo;
10678 i = get_tv_number(&HI2DI(hi)->di_tv);
10679 if (first)
10680 {
10681 n = i;
10682 first = FALSE;
10683 }
10684 else if (domax ? i > n : i < n)
Bram Moolenaare9a41262005-01-15 22:18:47 +000010685 n = i;
10686 }
10687 }
10688 }
10689 }
Bram Moolenaar6cc16192005-01-08 21:49:45 +000010690 else
Bram Moolenaar758711c2005-02-02 23:11:38 +000010691 EMSG(_(e_listdictarg));
Bram Moolenaar6cc16192005-01-08 21:49:45 +000010692 rettv->vval.v_number = n;
10693}
10694
10695/*
10696 * "max()" function
10697 */
10698 static void
10699f_max(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010700 typval_T *argvars;
10701 typval_T *rettv;
Bram Moolenaar6cc16192005-01-08 21:49:45 +000010702{
10703 max_min(argvars, rettv, TRUE);
10704}
10705
10706/*
10707 * "min()" function
10708 */
10709 static void
10710f_min(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010711 typval_T *argvars;
10712 typval_T *rettv;
Bram Moolenaar6cc16192005-01-08 21:49:45 +000010713{
10714 max_min(argvars, rettv, FALSE);
10715}
10716
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000010717static int mkdir_recurse __ARGS((char_u *dir, int prot));
10718
10719/*
10720 * Create the directory in which "dir" is located, and higher levels when
10721 * needed.
10722 */
10723 static int
10724mkdir_recurse(dir, prot)
10725 char_u *dir;
10726 int prot;
10727{
10728 char_u *p;
10729 char_u *updir;
10730 int r = FAIL;
10731
10732 /* Get end of directory name in "dir".
10733 * We're done when it's "/" or "c:/". */
10734 p = gettail_sep(dir);
10735 if (p <= get_past_head(dir))
10736 return OK;
10737
10738 /* If the directory exists we're done. Otherwise: create it.*/
10739 updir = vim_strnsave(dir, (int)(p - dir));
10740 if (updir == NULL)
10741 return FAIL;
10742 if (mch_isdir(updir))
10743 r = OK;
10744 else if (mkdir_recurse(updir, prot) == OK)
10745 r = vim_mkdir_emsg(updir, prot);
10746 vim_free(updir);
10747 return r;
10748}
10749
10750#ifdef vim_mkdir
10751/*
10752 * "mkdir()" function
10753 */
10754 static void
10755f_mkdir(argvars, rettv)
10756 typval_T *argvars;
10757 typval_T *rettv;
10758{
10759 char_u *dir;
10760 char_u buf[NUMBUFLEN];
10761 int prot = 0755;
10762
10763 rettv->vval.v_number = FAIL;
10764 if (check_restricted() || check_secure())
10765 return;
10766
10767 dir = get_tv_string_buf(&argvars[0], buf);
10768 if (argvars[1].v_type != VAR_UNKNOWN)
10769 {
10770 if (argvars[2].v_type != VAR_UNKNOWN)
10771 prot = get_tv_number(&argvars[2]);
10772 if (STRCMP(get_tv_string(&argvars[1]), "p") == 0)
10773 mkdir_recurse(dir, prot);
10774 }
10775 rettv->vval.v_number = vim_mkdir_emsg(dir, prot);
10776}
10777#endif
10778
Bram Moolenaar0d660222005-01-07 21:51:51 +000010779/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000010780 * "mode()" function
10781 */
10782/*ARGSUSED*/
10783 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010784f_mode(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010785 typval_T *argvars;
10786 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010787{
10788 char_u buf[2];
10789
10790#ifdef FEAT_VISUAL
10791 if (VIsual_active)
10792 {
10793 if (VIsual_select)
10794 buf[0] = VIsual_mode + 's' - 'v';
10795 else
10796 buf[0] = VIsual_mode;
10797 }
10798 else
10799#endif
10800 if (State == HITRETURN || State == ASKMORE || State == SETWSIZE)
10801 buf[0] = 'r';
10802 else if (State & INSERT)
10803 {
10804 if (State & REPLACE_FLAG)
10805 buf[0] = 'R';
10806 else
10807 buf[0] = 'i';
10808 }
10809 else if (State & CMDLINE)
10810 buf[0] = 'c';
10811 else
10812 buf[0] = 'n';
10813
10814 buf[1] = NUL;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010815 rettv->vval.v_string = vim_strsave(buf);
10816 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010817}
10818
10819/*
Bram Moolenaar0d660222005-01-07 21:51:51 +000010820 * "nextnonblank()" function
10821 */
10822 static void
10823f_nextnonblank(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010824 typval_T *argvars;
10825 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000010826{
10827 linenr_T lnum;
10828
10829 for (lnum = get_tv_lnum(argvars); ; ++lnum)
10830 {
10831 if (lnum > curbuf->b_ml.ml_line_count)
10832 {
10833 lnum = 0;
10834 break;
10835 }
10836 if (*skipwhite(ml_get(lnum)) != NUL)
10837 break;
10838 }
10839 rettv->vval.v_number = lnum;
10840}
10841
10842/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000010843 * "nr2char()" function
10844 */
10845 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010846f_nr2char(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010847 typval_T *argvars;
10848 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010849{
10850 char_u buf[NUMBUFLEN];
10851
10852#ifdef FEAT_MBYTE
10853 if (has_mbyte)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010854 buf[(*mb_char2bytes)((int)get_tv_number(&argvars[0]), buf)] = NUL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000010855 else
10856#endif
10857 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010858 buf[0] = (char_u)get_tv_number(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +000010859 buf[1] = NUL;
10860 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +000010861 rettv->v_type = VAR_STRING;
10862 rettv->vval.v_string = vim_strsave(buf);
Bram Moolenaar49cd9572005-01-03 21:06:01 +000010863}
10864
10865/*
Bram Moolenaar0d660222005-01-07 21:51:51 +000010866 * "prevnonblank()" function
10867 */
10868 static void
10869f_prevnonblank(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010870 typval_T *argvars;
10871 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000010872{
10873 linenr_T lnum;
10874
10875 lnum = get_tv_lnum(argvars);
10876 if (lnum < 1 || lnum > curbuf->b_ml.ml_line_count)
10877 lnum = 0;
10878 else
10879 while (lnum >= 1 && *skipwhite(ml_get(lnum)) == NUL)
10880 --lnum;
10881 rettv->vval.v_number = lnum;
10882}
10883
Bram Moolenaar8c711452005-01-14 21:53:12 +000010884/*
10885 * "range()" function
10886 */
10887 static void
10888f_range(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000010889 typval_T *argvars;
10890 typval_T *rettv;
Bram Moolenaar8c711452005-01-14 21:53:12 +000010891{
10892 long start;
10893 long end;
10894 long stride = 1;
10895 long i;
Bram Moolenaar33570922005-01-25 22:26:29 +000010896 list_T *l;
10897 listitem_T *li;
Bram Moolenaar8c711452005-01-14 21:53:12 +000010898
10899 start = get_tv_number(&argvars[0]);
10900 if (argvars[1].v_type == VAR_UNKNOWN)
10901 {
10902 end = start - 1;
10903 start = 0;
10904 }
10905 else
10906 {
10907 end = get_tv_number(&argvars[1]);
10908 if (argvars[2].v_type != VAR_UNKNOWN)
10909 stride = get_tv_number(&argvars[2]);
10910 }
10911
10912 rettv->vval.v_number = 0;
10913 if (stride == 0)
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000010914 EMSG(_("E726: Stride is zero"));
Bram Moolenaar8c711452005-01-14 21:53:12 +000010915 else if (stride > 0 ? end < start : end > start)
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000010916 EMSG(_("E727: Start past end"));
Bram Moolenaar8c711452005-01-14 21:53:12 +000010917 else
10918 {
10919 l = list_alloc();
10920 if (l != NULL)
10921 {
10922 rettv->v_type = VAR_LIST;
10923 rettv->vval.v_list = l;
10924 ++l->lv_refcount;
10925
10926 for (i = start; stride > 0 ? i <= end : i >= end; i += stride)
10927 {
10928 li = listitem_alloc();
10929 if (li == NULL)
10930 break;
10931 li->li_tv.v_type = VAR_NUMBER;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000010932 li->li_tv.v_lock = 0;
Bram Moolenaar8c711452005-01-14 21:53:12 +000010933 li->li_tv.vval.v_number = i;
10934 list_append(l, li);
10935 }
10936 }
10937 }
10938}
10939
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000010940/*
10941 * "readfile()" function
10942 */
10943 static void
10944f_readfile(argvars, rettv)
10945 typval_T *argvars;
10946 typval_T *rettv;
10947{
10948 int binary = FALSE;
10949 char_u *fname;
10950 FILE *fd;
10951 list_T *l;
10952 listitem_T *li;
10953#define FREAD_SIZE 200 /* optimized for text lines */
10954 char_u buf[FREAD_SIZE];
10955 int readlen; /* size of last fread() */
10956 int buflen; /* nr of valid chars in buf[] */
10957 int filtd; /* how much in buf[] was NUL -> '\n' filtered */
10958 int tolist; /* first byte in buf[] still to be put in list */
10959 int chop; /* how many CR to chop off */
10960 char_u *prev = NULL; /* previously read bytes, if any */
10961 int prevlen = 0; /* length of "prev" if not NULL */
10962 char_u *s;
10963 int len;
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000010964 long maxline = MAXLNUM;
10965 long cnt = 0;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000010966
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000010967 if (argvars[1].v_type != VAR_UNKNOWN)
10968 {
10969 if (STRCMP(get_tv_string(&argvars[1]), "b") == 0)
10970 binary = TRUE;
10971 if (argvars[2].v_type != VAR_UNKNOWN)
10972 maxline = get_tv_number(&argvars[2]);
10973 }
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000010974
10975 l = list_alloc();
10976 if (l == NULL)
10977 return;
10978 rettv->v_type = VAR_LIST;
10979 rettv->vval.v_list = l;
10980 l->lv_refcount = 1;
10981
10982 /* Always open the file in binary mode, library functions have a mind of
10983 * their own about CR-LF conversion. */
10984 fname = get_tv_string(&argvars[0]);
10985 if (*fname == NUL || (fd = mch_fopen((char *)fname, READBIN)) == NULL)
10986 {
10987 EMSG2(_(e_notopen), *fname == NUL ? (char_u *)_("<empty>") : fname);
10988 return;
10989 }
10990
10991 filtd = 0;
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000010992 while (cnt < maxline)
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000010993 {
10994 readlen = fread(buf + filtd, 1, FREAD_SIZE - filtd, fd);
10995 buflen = filtd + readlen;
10996 tolist = 0;
10997 for ( ; filtd < buflen || readlen <= 0; ++filtd)
10998 {
10999 if (buf[filtd] == '\n' || readlen <= 0)
11000 {
11001 /* Only when in binary mode add an empty list item when the
11002 * last line ends in a '\n'. */
11003 if (!binary && readlen == 0 && filtd == 0)
11004 break;
11005
11006 /* Found end-of-line or end-of-file: add a text line to the
11007 * list. */
11008 chop = 0;
11009 if (!binary)
11010 while (filtd - chop - 1 >= tolist
11011 && buf[filtd - chop - 1] == '\r')
11012 ++chop;
11013 len = filtd - tolist - chop;
11014 if (prev == NULL)
11015 s = vim_strnsave(buf + tolist, len);
11016 else
11017 {
11018 s = alloc((unsigned)(prevlen + len + 1));
11019 if (s != NULL)
11020 {
11021 mch_memmove(s, prev, prevlen);
11022 vim_free(prev);
11023 prev = NULL;
11024 mch_memmove(s + prevlen, buf + tolist, len);
11025 s[prevlen + len] = NUL;
11026 }
11027 }
11028 tolist = filtd + 1;
11029
11030 li = listitem_alloc();
11031 if (li == NULL)
11032 {
11033 vim_free(s);
11034 break;
11035 }
11036 li->li_tv.v_type = VAR_STRING;
11037 li->li_tv.v_lock = 0;
11038 li->li_tv.vval.v_string = s;
11039 list_append(l, li);
11040
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000011041 if (++cnt >= maxline)
11042 break;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000011043 if (readlen <= 0)
11044 break;
11045 }
11046 else if (buf[filtd] == NUL)
11047 buf[filtd] = '\n';
11048 }
11049 if (readlen <= 0)
11050 break;
11051
11052 if (tolist == 0)
11053 {
11054 /* "buf" is full, need to move text to an allocated buffer */
11055 if (prev == NULL)
11056 {
11057 prev = vim_strnsave(buf, buflen);
11058 prevlen = buflen;
11059 }
11060 else
11061 {
11062 s = alloc((unsigned)(prevlen + buflen));
11063 if (s != NULL)
11064 {
11065 mch_memmove(s, prev, prevlen);
11066 mch_memmove(s + prevlen, buf, buflen);
11067 vim_free(prev);
11068 prev = s;
11069 prevlen += buflen;
11070 }
11071 }
11072 filtd = 0;
11073 }
11074 else
11075 {
11076 mch_memmove(buf, buf + tolist, buflen - tolist);
11077 filtd -= tolist;
11078 }
11079 }
11080
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000011081 vim_free(prev);
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000011082 fclose(fd);
11083}
11084
11085
Bram Moolenaar0d660222005-01-07 21:51:51 +000011086#if defined(FEAT_CLIENTSERVER) && defined(FEAT_X11)
11087static void make_connection __ARGS((void));
11088static int check_connection __ARGS((void));
11089
11090 static void
11091make_connection()
11092{
11093 if (X_DISPLAY == NULL
11094# ifdef FEAT_GUI
11095 && !gui.in_use
11096# endif
11097 )
11098 {
11099 x_force_connect = TRUE;
11100 setup_term_clip();
11101 x_force_connect = FALSE;
11102 }
11103}
11104
11105 static int
11106check_connection()
11107{
11108 make_connection();
11109 if (X_DISPLAY == NULL)
11110 {
11111 EMSG(_("E240: No connection to Vim server"));
11112 return FAIL;
11113 }
11114 return OK;
11115}
11116#endif
11117
11118#ifdef FEAT_CLIENTSERVER
Bram Moolenaar33570922005-01-25 22:26:29 +000011119static void remote_common __ARGS((typval_T *argvars, typval_T *rettv, int expr));
Bram Moolenaar0d660222005-01-07 21:51:51 +000011120
11121 static void
11122remote_common(argvars, rettv, expr)
Bram Moolenaar33570922005-01-25 22:26:29 +000011123 typval_T *argvars;
11124 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000011125 int expr;
11126{
11127 char_u *server_name;
11128 char_u *keys;
11129 char_u *r = NULL;
11130 char_u buf[NUMBUFLEN];
11131# ifdef WIN32
11132 HWND w;
11133# else
11134 Window w;
11135# endif
11136
11137 if (check_restricted() || check_secure())
11138 return;
11139
11140# ifdef FEAT_X11
11141 if (check_connection() == FAIL)
11142 return;
11143# endif
11144
11145 server_name = get_tv_string(&argvars[0]);
11146 keys = get_tv_string_buf(&argvars[1], buf);
11147# ifdef WIN32
11148 if (serverSendToVim(server_name, keys, &r, &w, expr, TRUE) < 0)
11149# else
11150 if (serverSendToVim(X_DISPLAY, server_name, keys, &r, &w, expr, 0, TRUE)
11151 < 0)
11152# endif
11153 {
11154 if (r != NULL)
11155 EMSG(r); /* sending worked but evaluation failed */
11156 else
11157 EMSG2(_("E241: Unable to send to %s"), server_name);
11158 return;
11159 }
11160
11161 rettv->vval.v_string = r;
11162
11163 if (argvars[2].v_type != VAR_UNKNOWN)
11164 {
Bram Moolenaar33570922005-01-25 22:26:29 +000011165 dictitem_T v;
Bram Moolenaar0d660222005-01-07 21:51:51 +000011166 char_u str[30];
11167
11168 sprintf((char *)str, "0x%x", (unsigned int)w);
Bram Moolenaar33570922005-01-25 22:26:29 +000011169 v.di_tv.v_type = VAR_STRING;
11170 v.di_tv.vval.v_string = vim_strsave(str);
11171 set_var(get_tv_string(&argvars[2]), &v.di_tv, FALSE);
11172 vim_free(v.di_tv.vval.v_string);
Bram Moolenaar0d660222005-01-07 21:51:51 +000011173 }
11174}
11175#endif
11176
11177/*
11178 * "remote_expr()" function
11179 */
11180/*ARGSUSED*/
11181 static void
11182f_remote_expr(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000011183 typval_T *argvars;
11184 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000011185{
11186 rettv->v_type = VAR_STRING;
11187 rettv->vval.v_string = NULL;
11188#ifdef FEAT_CLIENTSERVER
11189 remote_common(argvars, rettv, TRUE);
11190#endif
11191}
11192
11193/*
11194 * "remote_foreground()" function
11195 */
11196/*ARGSUSED*/
11197 static void
11198f_remote_foreground(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000011199 typval_T *argvars;
11200 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000011201{
11202 rettv->vval.v_number = 0;
11203#ifdef FEAT_CLIENTSERVER
11204# ifdef WIN32
11205 /* On Win32 it's done in this application. */
11206 serverForeground(get_tv_string(&argvars[0]));
11207# else
11208 /* Send a foreground() expression to the server. */
11209 argvars[1].v_type = VAR_STRING;
11210 argvars[1].vval.v_string = vim_strsave((char_u *)"foreground()");
11211 argvars[2].v_type = VAR_UNKNOWN;
11212 remote_common(argvars, rettv, TRUE);
11213 vim_free(argvars[1].vval.v_string);
11214# endif
11215#endif
11216}
11217
11218/*ARGSUSED*/
11219 static void
11220f_remote_peek(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000011221 typval_T *argvars;
11222 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000011223{
11224#ifdef FEAT_CLIENTSERVER
Bram Moolenaar33570922005-01-25 22:26:29 +000011225 dictitem_T v;
Bram Moolenaar0d660222005-01-07 21:51:51 +000011226 char_u *s = NULL;
11227# ifdef WIN32
11228 int n = 0;
11229# endif
11230
11231 if (check_restricted() || check_secure())
11232 {
11233 rettv->vval.v_number = -1;
11234 return;
11235 }
11236# ifdef WIN32
11237 sscanf(get_tv_string(&argvars[0]), "%x", &n);
11238 if (n == 0)
11239 rettv->vval.v_number = -1;
11240 else
11241 {
11242 s = serverGetReply((HWND)n, FALSE, FALSE, FALSE);
11243 rettv->vval.v_number = (s != NULL);
11244 }
11245# else
11246 rettv->vval.v_number = 0;
11247 if (check_connection() == FAIL)
11248 return;
11249
11250 rettv->vval.v_number = serverPeekReply(X_DISPLAY,
11251 serverStrToWin(get_tv_string(&argvars[0])), &s);
11252# endif
11253
11254 if (argvars[1].v_type != VAR_UNKNOWN && rettv->vval.v_number > 0)
11255 {
Bram Moolenaar33570922005-01-25 22:26:29 +000011256 v.di_tv.v_type = VAR_STRING;
11257 v.di_tv.vval.v_string = vim_strsave(s);
11258 set_var(get_tv_string(&argvars[1]), &v.di_tv, FALSE);
11259 vim_free(v.di_tv.vval.v_string);
Bram Moolenaar0d660222005-01-07 21:51:51 +000011260 }
11261#else
11262 rettv->vval.v_number = -1;
11263#endif
11264}
11265
11266/*ARGSUSED*/
11267 static void
11268f_remote_read(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000011269 typval_T *argvars;
11270 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000011271{
11272 char_u *r = NULL;
11273
11274#ifdef FEAT_CLIENTSERVER
11275 if (!check_restricted() && !check_secure())
11276 {
11277# ifdef WIN32
11278 /* The server's HWND is encoded in the 'id' parameter */
11279 int n = 0;
11280
11281 sscanf(get_tv_string(&argvars[0]), "%x", &n);
11282 if (n != 0)
11283 r = serverGetReply((HWND)n, FALSE, TRUE, TRUE);
11284 if (r == NULL)
11285# else
11286 if (check_connection() == FAIL || serverReadReply(X_DISPLAY,
11287 serverStrToWin(get_tv_string(&argvars[0])), &r, FALSE) < 0)
11288# endif
11289 EMSG(_("E277: Unable to read a server reply"));
11290 }
11291#endif
11292 rettv->v_type = VAR_STRING;
11293 rettv->vval.v_string = r;
11294}
11295
11296/*
11297 * "remote_send()" function
11298 */
11299/*ARGSUSED*/
11300 static void
11301f_remote_send(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000011302 typval_T *argvars;
11303 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000011304{
11305 rettv->v_type = VAR_STRING;
11306 rettv->vval.v_string = NULL;
11307#ifdef FEAT_CLIENTSERVER
11308 remote_common(argvars, rettv, FALSE);
11309#endif
11310}
11311
11312/*
Bram Moolenaar8c711452005-01-14 21:53:12 +000011313 * "remove()" function
Bram Moolenaar49cd9572005-01-03 21:06:01 +000011314 */
11315 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011316f_remove(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000011317 typval_T *argvars;
11318 typval_T *rettv;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000011319{
Bram Moolenaar33570922005-01-25 22:26:29 +000011320 list_T *l;
11321 listitem_T *item, *item2;
11322 listitem_T *li;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000011323 long idx;
Bram Moolenaar8a283e52005-01-06 23:28:25 +000011324 long end;
Bram Moolenaar8c711452005-01-14 21:53:12 +000011325 char_u *key;
Bram Moolenaar33570922005-01-25 22:26:29 +000011326 dict_T *d;
11327 dictitem_T *di;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000011328
Bram Moolenaar8a283e52005-01-06 23:28:25 +000011329 rettv->vval.v_number = 0;
Bram Moolenaar8c711452005-01-14 21:53:12 +000011330 if (argvars[0].v_type == VAR_DICT)
11331 {
11332 if (argvars[2].v_type != VAR_UNKNOWN)
11333 EMSG2(_(e_toomanyarg), "remove()");
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000011334 else if ((d = argvars[0].vval.v_dict) != NULL
Bram Moolenaar758711c2005-02-02 23:11:38 +000011335 && !tv_check_lock(d->dv_lock, (char_u *)"remove()"))
Bram Moolenaar8c711452005-01-14 21:53:12 +000011336 {
11337 key = get_tv_string(&argvars[1]);
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000011338 di = dict_find(d, key, -1);
Bram Moolenaar8c711452005-01-14 21:53:12 +000011339 if (di == NULL)
11340 EMSG2(_(e_dictkey), key);
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000011341 else
11342 {
11343 *rettv = di->di_tv;
11344 init_tv(&di->di_tv);
11345 dictitem_remove(d, di);
11346 }
Bram Moolenaar8c711452005-01-14 21:53:12 +000011347 }
11348 }
11349 else if (argvars[0].v_type != VAR_LIST)
11350 EMSG2(_(e_listdictarg), "remove()");
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000011351 else if ((l = argvars[0].vval.v_list) != NULL
11352 && !tv_check_lock(l->lv_lock, (char_u *)"remove()"))
Bram Moolenaar49cd9572005-01-03 21:06:01 +000011353 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011354 idx = get_tv_number(&argvars[1]);
Bram Moolenaar8a283e52005-01-06 23:28:25 +000011355 item = list_find(l, idx);
Bram Moolenaar49cd9572005-01-03 21:06:01 +000011356 if (item == NULL)
11357 EMSGN(_(e_listidx), idx);
11358 else
11359 {
Bram Moolenaar8a283e52005-01-06 23:28:25 +000011360 if (argvars[2].v_type == VAR_UNKNOWN)
11361 {
11362 /* Remove one item, return its value. */
Bram Moolenaar7480b5c2005-01-16 22:07:38 +000011363 list_remove(l, item, item);
Bram Moolenaar8a283e52005-01-06 23:28:25 +000011364 *rettv = item->li_tv;
11365 vim_free(item);
11366 }
11367 else
11368 {
11369 /* Remove range of items, return list with values. */
11370 end = get_tv_number(&argvars[2]);
11371 item2 = list_find(l, end);
11372 if (item2 == NULL)
11373 EMSGN(_(e_listidx), end);
11374 else
11375 {
Bram Moolenaar758711c2005-02-02 23:11:38 +000011376 int cnt = 0;
11377
11378 for (li = item; li != NULL; li = li->li_next)
11379 {
11380 ++cnt;
11381 if (li == item2)
11382 break;
11383 }
Bram Moolenaar8a283e52005-01-06 23:28:25 +000011384 if (li == NULL) /* didn't find "item2" after "item" */
11385 EMSG(_(e_invrange));
11386 else
11387 {
Bram Moolenaar7480b5c2005-01-16 22:07:38 +000011388 list_remove(l, item, item2);
Bram Moolenaar8a283e52005-01-06 23:28:25 +000011389 l = list_alloc();
11390 if (l != NULL)
11391 {
11392 rettv->v_type = VAR_LIST;
11393 rettv->vval.v_list = l;
11394 l->lv_first = item;
11395 l->lv_last = item2;
11396 l->lv_refcount = 1;
11397 item->li_prev = NULL;
11398 item2->li_next = NULL;
Bram Moolenaar758711c2005-02-02 23:11:38 +000011399 l->lv_len = cnt;
Bram Moolenaar8a283e52005-01-06 23:28:25 +000011400 }
11401 }
11402 }
11403 }
Bram Moolenaar49cd9572005-01-03 21:06:01 +000011404 }
11405 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000011406}
11407
11408/*
11409 * "rename({from}, {to})" function
11410 */
11411 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011412f_rename(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000011413 typval_T *argvars;
11414 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011415{
11416 char_u buf[NUMBUFLEN];
11417
11418 if (check_restricted() || check_secure())
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011419 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011420 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011421 rettv->vval.v_number = vim_rename(get_tv_string(&argvars[0]),
11422 get_tv_string_buf(&argvars[1], buf));
Bram Moolenaar071d4272004-06-13 20:20:40 +000011423}
11424
11425/*
Bram Moolenaar8a283e52005-01-06 23:28:25 +000011426 * "repeat()" function
11427 */
11428/*ARGSUSED*/
11429 static void
11430f_repeat(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000011431 typval_T *argvars;
11432 typval_T *rettv;
Bram Moolenaar8a283e52005-01-06 23:28:25 +000011433{
11434 char_u *p;
11435 int n;
11436 int slen;
11437 int len;
11438 char_u *r;
11439 int i;
Bram Moolenaar33570922005-01-25 22:26:29 +000011440 list_T *l;
Bram Moolenaar8a283e52005-01-06 23:28:25 +000011441
11442 n = get_tv_number(&argvars[1]);
11443 if (argvars[0].v_type == VAR_LIST)
11444 {
11445 l = list_alloc();
11446 if (l != NULL && argvars[0].vval.v_list != NULL)
11447 {
11448 l->lv_refcount = 1;
11449 while (n-- > 0)
11450 if (list_extend(l, argvars[0].vval.v_list, NULL) == FAIL)
11451 break;
11452 }
11453 rettv->v_type = VAR_LIST;
11454 rettv->vval.v_list = l;
11455 }
11456 else
11457 {
11458 p = get_tv_string(&argvars[0]);
11459 rettv->v_type = VAR_STRING;
11460 rettv->vval.v_string = NULL;
11461
11462 slen = (int)STRLEN(p);
11463 len = slen * n;
11464 if (len <= 0)
11465 return;
11466
11467 r = alloc(len + 1);
11468 if (r != NULL)
11469 {
11470 for (i = 0; i < n; i++)
11471 mch_memmove(r + i * slen, p, (size_t)slen);
11472 r[len] = NUL;
11473 }
11474
11475 rettv->vval.v_string = r;
11476 }
11477}
11478
11479/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000011480 * "resolve()" function
11481 */
11482 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011483f_resolve(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000011484 typval_T *argvars;
11485 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011486{
11487 char_u *p;
11488
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011489 p = get_tv_string(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +000011490#ifdef FEAT_SHORTCUT
11491 {
11492 char_u *v = NULL;
11493
11494 v = mch_resolve_shortcut(p);
11495 if (v != NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011496 rettv->vval.v_string = v;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011497 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011498 rettv->vval.v_string = vim_strsave(p);
Bram Moolenaar071d4272004-06-13 20:20:40 +000011499 }
11500#else
11501# ifdef HAVE_READLINK
11502 {
11503 char_u buf[MAXPATHL + 1];
11504 char_u *cpy;
11505 int len;
11506 char_u *remain = NULL;
11507 char_u *q;
11508 int is_relative_to_current = FALSE;
11509 int has_trailing_pathsep = FALSE;
11510 int limit = 100;
11511
11512 p = vim_strsave(p);
11513
11514 if (p[0] == '.' && (vim_ispathsep(p[1])
11515 || (p[1] == '.' && (vim_ispathsep(p[2])))))
11516 is_relative_to_current = TRUE;
11517
11518 len = STRLEN(p);
Bram Moolenaar1cd871b2004-12-19 22:46:22 +000011519 if (len > 0 && after_pathsep(p, p + len))
Bram Moolenaar071d4272004-06-13 20:20:40 +000011520 has_trailing_pathsep = TRUE;
11521
11522 q = getnextcomp(p);
11523 if (*q != NUL)
11524 {
11525 /* Separate the first path component in "p", and keep the
11526 * remainder (beginning with the path separator). */
11527 remain = vim_strsave(q - 1);
11528 q[-1] = NUL;
11529 }
11530
11531 for (;;)
11532 {
11533 for (;;)
11534 {
11535 len = readlink((char *)p, (char *)buf, MAXPATHL);
11536 if (len <= 0)
11537 break;
11538 buf[len] = NUL;
11539
11540 if (limit-- == 0)
11541 {
11542 vim_free(p);
11543 vim_free(remain);
11544 EMSG(_("E655: Too many symbolic links (cycle?)"));
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011545 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011546 goto fail;
11547 }
11548
11549 /* Ensure that the result will have a trailing path separator
11550 * if the argument has one. */
11551 if (remain == NULL && has_trailing_pathsep)
11552 add_pathsep(buf);
11553
11554 /* Separate the first path component in the link value and
11555 * concatenate the remainders. */
11556 q = getnextcomp(vim_ispathsep(*buf) ? buf + 1 : buf);
11557 if (*q != NUL)
11558 {
11559 if (remain == NULL)
11560 remain = vim_strsave(q - 1);
11561 else
11562 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000011563 cpy = vim_strnsave(q-1, STRLEN(q-1) + STRLEN(remain));
Bram Moolenaar071d4272004-06-13 20:20:40 +000011564 if (cpy != NULL)
11565 {
11566 STRCAT(cpy, remain);
11567 vim_free(remain);
11568 remain = cpy;
11569 }
11570 }
11571 q[-1] = NUL;
11572 }
11573
11574 q = gettail(p);
11575 if (q > p && *q == NUL)
11576 {
11577 /* Ignore trailing path separator. */
11578 q[-1] = NUL;
11579 q = gettail(p);
11580 }
11581 if (q > p && !mch_isFullName(buf))
11582 {
11583 /* symlink is relative to directory of argument */
11584 cpy = alloc((unsigned)(STRLEN(p) + STRLEN(buf) + 1));
11585 if (cpy != NULL)
11586 {
11587 STRCPY(cpy, p);
11588 STRCPY(gettail(cpy), buf);
11589 vim_free(p);
11590 p = cpy;
11591 }
11592 }
11593 else
11594 {
11595 vim_free(p);
11596 p = vim_strsave(buf);
11597 }
11598 }
11599
11600 if (remain == NULL)
11601 break;
11602
11603 /* Append the first path component of "remain" to "p". */
11604 q = getnextcomp(remain + 1);
11605 len = q - remain - (*q != NUL);
11606 cpy = vim_strnsave(p, STRLEN(p) + len);
11607 if (cpy != NULL)
11608 {
11609 STRNCAT(cpy, remain, len);
11610 vim_free(p);
11611 p = cpy;
11612 }
11613 /* Shorten "remain". */
11614 if (*q != NUL)
11615 STRCPY(remain, q - 1);
11616 else
11617 {
11618 vim_free(remain);
11619 remain = NULL;
11620 }
11621 }
11622
11623 /* If the result is a relative path name, make it explicitly relative to
11624 * the current directory if and only if the argument had this form. */
11625 if (!vim_ispathsep(*p))
11626 {
11627 if (is_relative_to_current
11628 && *p != NUL
11629 && !(p[0] == '.'
11630 && (p[1] == NUL
11631 || vim_ispathsep(p[1])
11632 || (p[1] == '.'
11633 && (p[2] == NUL
11634 || vim_ispathsep(p[2]))))))
11635 {
11636 /* Prepend "./". */
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000011637 cpy = concat_str((char_u *)"./", p);
Bram Moolenaar071d4272004-06-13 20:20:40 +000011638 if (cpy != NULL)
11639 {
Bram Moolenaar071d4272004-06-13 20:20:40 +000011640 vim_free(p);
11641 p = cpy;
11642 }
11643 }
11644 else if (!is_relative_to_current)
11645 {
11646 /* Strip leading "./". */
11647 q = p;
11648 while (q[0] == '.' && vim_ispathsep(q[1]))
11649 q += 2;
11650 if (q > p)
11651 mch_memmove(p, p + 2, STRLEN(p + 2) + (size_t)1);
11652 }
11653 }
11654
11655 /* Ensure that the result will have no trailing path separator
11656 * if the argument had none. But keep "/" or "//". */
11657 if (!has_trailing_pathsep)
11658 {
11659 q = p + STRLEN(p);
Bram Moolenaar1cd871b2004-12-19 22:46:22 +000011660 if (after_pathsep(p, q))
11661 *gettail_sep(p) = NUL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011662 }
11663
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011664 rettv->vval.v_string = p;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011665 }
11666# else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011667 rettv->vval.v_string = vim_strsave(p);
Bram Moolenaar071d4272004-06-13 20:20:40 +000011668# endif
11669#endif
11670
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011671 simplify_filename(rettv->vval.v_string);
Bram Moolenaar071d4272004-06-13 20:20:40 +000011672
11673#ifdef HAVE_READLINK
11674fail:
11675#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011676 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011677}
11678
11679/*
Bram Moolenaar0d660222005-01-07 21:51:51 +000011680 * "reverse({list})" function
Bram Moolenaar071d4272004-06-13 20:20:40 +000011681 */
11682 static void
Bram Moolenaar0d660222005-01-07 21:51:51 +000011683f_reverse(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000011684 typval_T *argvars;
11685 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011686{
Bram Moolenaar33570922005-01-25 22:26:29 +000011687 list_T *l;
11688 listitem_T *li, *ni;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011689
Bram Moolenaar0d660222005-01-07 21:51:51 +000011690 rettv->vval.v_number = 0;
11691 if (argvars[0].v_type != VAR_LIST)
11692 EMSG2(_(e_listarg), "reverse()");
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000011693 else if ((l = argvars[0].vval.v_list) != NULL
11694 && !tv_check_lock(l->lv_lock, (char_u *)"reverse()"))
Bram Moolenaar0d660222005-01-07 21:51:51 +000011695 {
11696 li = l->lv_last;
Bram Moolenaar81bf7082005-02-12 14:31:42 +000011697 l->lv_first = l->lv_last = NULL;
Bram Moolenaar758711c2005-02-02 23:11:38 +000011698 l->lv_len = 0;
Bram Moolenaar0d660222005-01-07 21:51:51 +000011699 while (li != NULL)
11700 {
11701 ni = li->li_prev;
11702 list_append(l, li);
11703 li = ni;
11704 }
11705 rettv->vval.v_list = l;
11706 rettv->v_type = VAR_LIST;
11707 ++l->lv_refcount;
11708 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000011709}
11710
Bram Moolenaar5eb86f92004-07-26 12:53:41 +000011711#define SP_NOMOVE 1 /* don't move cursor */
11712#define SP_REPEAT 2 /* repeat to find outer pair */
11713#define SP_RETCOUNT 4 /* return matchcount */
11714
Bram Moolenaar33570922005-01-25 22:26:29 +000011715static int get_search_arg __ARGS((typval_T *varp, int *flagsp));
Bram Moolenaar0d660222005-01-07 21:51:51 +000011716
11717/*
11718 * Get flags for a search function.
11719 * Possibly sets "p_ws".
11720 * Returns BACKWARD, FORWARD or zero (for an error).
11721 */
11722 static int
11723get_search_arg(varp, flagsp)
Bram Moolenaar33570922005-01-25 22:26:29 +000011724 typval_T *varp;
Bram Moolenaar0d660222005-01-07 21:51:51 +000011725 int *flagsp;
11726{
11727 int dir = FORWARD;
11728 char_u *flags;
11729 char_u nbuf[NUMBUFLEN];
11730 int mask;
11731
11732 if (varp->v_type != VAR_UNKNOWN)
11733 {
11734 flags = get_tv_string_buf(varp, nbuf);
11735 while (*flags != NUL)
11736 {
11737 switch (*flags)
11738 {
11739 case 'b': dir = BACKWARD; break;
11740 case 'w': p_ws = TRUE; break;
11741 case 'W': p_ws = FALSE; break;
11742 default: mask = 0;
11743 if (flagsp != NULL)
11744 switch (*flags)
11745 {
11746 case 'n': mask = SP_NOMOVE; break;
11747 case 'r': mask = SP_REPEAT; break;
11748 case 'm': mask = SP_RETCOUNT; break;
11749 }
11750 if (mask == 0)
11751 {
11752 EMSG2(_(e_invarg2), flags);
11753 dir = 0;
11754 }
11755 else
11756 *flagsp |= mask;
11757 }
11758 if (dir == 0)
11759 break;
11760 ++flags;
11761 }
11762 }
11763 return dir;
11764}
11765
Bram Moolenaar071d4272004-06-13 20:20:40 +000011766/*
11767 * "search()" function
11768 */
11769 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011770f_search(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000011771 typval_T *argvars;
11772 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011773{
11774 char_u *pat;
11775 pos_T pos;
Bram Moolenaar5eb86f92004-07-26 12:53:41 +000011776 pos_T save_cursor;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011777 int save_p_ws = p_ws;
11778 int dir;
Bram Moolenaar5eb86f92004-07-26 12:53:41 +000011779 int flags = 0;
11780
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011781 rettv->vval.v_number = 0; /* default: FAIL */
Bram Moolenaar071d4272004-06-13 20:20:40 +000011782
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011783 pat = get_tv_string(&argvars[0]);
Bram Moolenaar5eb86f92004-07-26 12:53:41 +000011784 dir = get_search_arg(&argvars[1], &flags); /* may set p_ws */
11785 if (dir == 0)
11786 goto theend;
11787 if ((flags & ~SP_NOMOVE) != 0)
11788 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011789 EMSG2(_(e_invarg2), get_tv_string(&argvars[1]));
Bram Moolenaar5eb86f92004-07-26 12:53:41 +000011790 goto theend;
11791 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000011792
Bram Moolenaar5eb86f92004-07-26 12:53:41 +000011793 pos = save_cursor = curwin->w_cursor;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011794 if (searchit(curwin, curbuf, &pos, dir, pat, 1L,
11795 SEARCH_KEEP, RE_SEARCH) != FAIL)
11796 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011797 rettv->vval.v_number = pos.lnum;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011798 curwin->w_cursor = pos;
11799 /* "/$" will put the cursor after the end of the line, may need to
11800 * correct that here */
11801 check_cursor();
11802 }
Bram Moolenaar5eb86f92004-07-26 12:53:41 +000011803
11804 /* If 'n' flag is used: restore cursor position. */
11805 if (flags & SP_NOMOVE)
11806 curwin->w_cursor = save_cursor;
11807theend:
Bram Moolenaar071d4272004-06-13 20:20:40 +000011808 p_ws = save_p_ws;
11809}
11810
Bram Moolenaar071d4272004-06-13 20:20:40 +000011811/*
11812 * "searchpair()" function
11813 */
11814 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011815f_searchpair(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000011816 typval_T *argvars;
11817 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011818{
11819 char_u *spat, *mpat, *epat;
11820 char_u *skip;
11821 char_u *pat, *pat2, *pat3;
11822 pos_T pos;
11823 pos_T firstpos;
11824 pos_T save_cursor;
11825 pos_T save_pos;
11826 int save_p_ws = p_ws;
11827 char_u *save_cpo;
11828 int dir;
11829 int flags = 0;
11830 char_u nbuf1[NUMBUFLEN];
11831 char_u nbuf2[NUMBUFLEN];
11832 char_u nbuf3[NUMBUFLEN];
11833 int n;
11834 int r;
11835 int nest = 1;
11836 int err;
11837
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011838 rettv->vval.v_number = 0; /* default: FAIL */
Bram Moolenaar071d4272004-06-13 20:20:40 +000011839
11840 /* Make 'cpoptions' empty, the 'l' flag should not be used here. */
11841 save_cpo = p_cpo;
11842 p_cpo = (char_u *)"";
11843
11844 /* Get the three pattern arguments: start, middle, end. */
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011845 spat = get_tv_string(&argvars[0]);
11846 mpat = get_tv_string_buf(&argvars[1], nbuf1);
11847 epat = get_tv_string_buf(&argvars[2], nbuf2);
Bram Moolenaar071d4272004-06-13 20:20:40 +000011848
11849 /* Make two search patterns: start/end (pat2, for in nested pairs) and
11850 * start/middle/end (pat3, for the top pair). */
11851 pat2 = alloc((unsigned)(STRLEN(spat) + STRLEN(epat) + 15));
11852 pat3 = alloc((unsigned)(STRLEN(spat) + STRLEN(mpat) + STRLEN(epat) + 23));
11853 if (pat2 == NULL || pat3 == NULL)
11854 goto theend;
11855 sprintf((char *)pat2, "\\(%s\\m\\)\\|\\(%s\\m\\)", spat, epat);
11856 if (*mpat == NUL)
11857 STRCPY(pat3, pat2);
11858 else
11859 sprintf((char *)pat3, "\\(%s\\m\\)\\|\\(%s\\m\\)\\|\\(%s\\m\\)",
11860 spat, epat, mpat);
11861
11862 /* Handle the optional fourth argument: flags */
11863 dir = get_search_arg(&argvars[3], &flags); /* may set p_ws */
Bram Moolenaar5eb86f92004-07-26 12:53:41 +000011864 if (dir == 0)
11865 goto theend;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011866
11867 /* Optional fifth argument: skip expresion */
Bram Moolenaar49cd9572005-01-03 21:06:01 +000011868 if (argvars[3].v_type == VAR_UNKNOWN
11869 || argvars[4].v_type == VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +000011870 skip = (char_u *)"";
11871 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011872 skip = get_tv_string_buf(&argvars[4], nbuf3);
Bram Moolenaar071d4272004-06-13 20:20:40 +000011873
11874 save_cursor = curwin->w_cursor;
11875 pos = curwin->w_cursor;
11876 firstpos.lnum = 0;
11877 pat = pat3;
11878 for (;;)
11879 {
11880 n = searchit(curwin, curbuf, &pos, dir, pat, 1L,
11881 SEARCH_KEEP, RE_SEARCH);
11882 if (n == FAIL || (firstpos.lnum != 0 && equalpos(pos, firstpos)))
11883 /* didn't find it or found the first match again: FAIL */
11884 break;
11885
11886 if (firstpos.lnum == 0)
11887 firstpos = pos;
11888
11889 /* If the skip pattern matches, ignore this match. */
11890 if (*skip != NUL)
11891 {
11892 save_pos = curwin->w_cursor;
11893 curwin->w_cursor = pos;
11894 r = eval_to_bool(skip, &err, NULL, FALSE);
11895 curwin->w_cursor = save_pos;
11896 if (err)
11897 {
11898 /* Evaluating {skip} caused an error, break here. */
11899 curwin->w_cursor = save_cursor;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011900 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011901 break;
11902 }
11903 if (r)
11904 continue;
11905 }
11906
11907 if ((dir == BACKWARD && n == 3) || (dir == FORWARD && n == 2))
11908 {
11909 /* Found end when searching backwards or start when searching
11910 * forward: nested pair. */
11911 ++nest;
11912 pat = pat2; /* nested, don't search for middle */
11913 }
11914 else
11915 {
11916 /* Found end when searching forward or start when searching
11917 * backward: end of (nested) pair; or found middle in outer pair. */
11918 if (--nest == 1)
11919 pat = pat3; /* outer level, search for middle */
11920 }
11921
11922 if (nest == 0)
11923 {
11924 /* Found the match: return matchcount or line number. */
11925 if (flags & SP_RETCOUNT)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011926 ++rettv->vval.v_number;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011927 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011928 rettv->vval.v_number = pos.lnum;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011929 curwin->w_cursor = pos;
11930 if (!(flags & SP_REPEAT))
11931 break;
11932 nest = 1; /* search for next unmatched */
11933 }
11934 }
11935
11936 /* If 'n' flag is used or search failed: restore cursor position. */
Bram Moolenaarc70646c2005-01-04 21:52:38 +000011937 if ((flags & SP_NOMOVE) || rettv->vval.v_number == 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +000011938 curwin->w_cursor = save_cursor;
11939
11940theend:
11941 vim_free(pat2);
11942 vim_free(pat3);
11943 p_ws = save_p_ws;
11944 p_cpo = save_cpo;
11945}
11946
Bram Moolenaar0d660222005-01-07 21:51:51 +000011947/*ARGSUSED*/
11948 static void
11949f_server2client(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000011950 typval_T *argvars;
11951 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011952{
Bram Moolenaar0d660222005-01-07 21:51:51 +000011953#ifdef FEAT_CLIENTSERVER
11954 char_u buf[NUMBUFLEN];
11955 char_u *server = get_tv_string(&argvars[0]);
11956 char_u *reply = get_tv_string_buf(&argvars[1], buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +000011957
Bram Moolenaar0d660222005-01-07 21:51:51 +000011958 rettv->vval.v_number = -1;
11959 if (check_restricted() || check_secure())
11960 return;
11961# ifdef FEAT_X11
11962 if (check_connection() == FAIL)
11963 return;
11964# endif
11965
11966 if (serverSendReply(server, reply) < 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +000011967 {
Bram Moolenaar0d660222005-01-07 21:51:51 +000011968 EMSG(_("E258: Unable to send to client"));
11969 return;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011970 }
Bram Moolenaar0d660222005-01-07 21:51:51 +000011971 rettv->vval.v_number = 0;
11972#else
11973 rettv->vval.v_number = -1;
11974#endif
11975}
11976
11977/*ARGSUSED*/
11978 static void
11979f_serverlist(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000011980 typval_T *argvars;
11981 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000011982{
11983 char_u *r = NULL;
11984
11985#ifdef FEAT_CLIENTSERVER
11986# ifdef WIN32
11987 r = serverGetVimNames();
11988# else
11989 make_connection();
11990 if (X_DISPLAY != NULL)
11991 r = serverGetVimNames(X_DISPLAY);
11992# endif
11993#endif
11994 rettv->v_type = VAR_STRING;
11995 rettv->vval.v_string = r;
Bram Moolenaar071d4272004-06-13 20:20:40 +000011996}
11997
11998/*
11999 * "setbufvar()" function
12000 */
12001/*ARGSUSED*/
12002 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012003f_setbufvar(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000012004 typval_T *argvars;
12005 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012006{
12007 buf_T *buf;
12008#ifdef FEAT_AUTOCMD
12009 aco_save_T aco;
12010#else
12011 buf_T *save_curbuf;
12012#endif
12013 char_u *varname, *bufvarname;
Bram Moolenaar33570922005-01-25 22:26:29 +000012014 typval_T *varp;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012015 char_u nbuf[NUMBUFLEN];
12016
12017 if (check_restricted() || check_secure())
12018 return;
12019 ++emsg_off;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012020 buf = get_buf_tv(&argvars[0]);
12021 varname = get_tv_string(&argvars[1]);
Bram Moolenaar071d4272004-06-13 20:20:40 +000012022 varp = &argvars[2];
12023
12024 if (buf != NULL && varname != NULL && varp != NULL)
12025 {
12026 /* set curbuf to be our buf, temporarily */
12027#ifdef FEAT_AUTOCMD
12028 aucmd_prepbuf(&aco, buf);
12029#else
12030 save_curbuf = curbuf;
12031 curbuf = buf;
12032#endif
12033
12034 if (*varname == '&')
12035 {
12036 ++varname;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012037 set_option_value(varname, get_tv_number(varp),
12038 get_tv_string_buf(varp, nbuf), OPT_LOCAL);
Bram Moolenaar071d4272004-06-13 20:20:40 +000012039 }
12040 else
12041 {
12042 bufvarname = alloc((unsigned)STRLEN(varname) + 3);
12043 if (bufvarname != NULL)
12044 {
12045 STRCPY(bufvarname, "b:");
12046 STRCPY(bufvarname + 2, varname);
Bram Moolenaar1c2fda22005-01-02 11:43:19 +000012047 set_var(bufvarname, varp, TRUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +000012048 vim_free(bufvarname);
12049 }
12050 }
12051
12052 /* reset notion of buffer */
12053#ifdef FEAT_AUTOCMD
12054 aucmd_restbuf(&aco);
12055#else
12056 curbuf = save_curbuf;
12057#endif
12058 }
12059 --emsg_off;
12060}
12061
12062/*
12063 * "setcmdpos()" function
12064 */
12065 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012066f_setcmdpos(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000012067 typval_T *argvars;
12068 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012069{
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012070 rettv->vval.v_number = set_cmdline_pos(
12071 (int)get_tv_number(&argvars[0]) - 1);
Bram Moolenaar071d4272004-06-13 20:20:40 +000012072}
12073
12074/*
12075 * "setline()" function
12076 */
12077 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012078f_setline(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000012079 typval_T *argvars;
12080 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012081{
12082 linenr_T lnum;
12083 char_u *line;
12084
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012085 lnum = get_tv_lnum(argvars);
12086 line = get_tv_string(&argvars[1]);
12087 rettv->vval.v_number = 1; /* FAIL is default */
Bram Moolenaar071d4272004-06-13 20:20:40 +000012088
12089 if (lnum >= 1
12090 && lnum <= curbuf->b_ml.ml_line_count
12091 && u_savesub(lnum) == OK
12092 && ml_replace(lnum, line, TRUE) == OK)
12093 {
12094 changed_bytes(lnum, 0);
12095 check_cursor_col();
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012096 rettv->vval.v_number = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012097 }
12098}
12099
12100/*
12101 * "setreg()" function
12102 */
12103 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012104f_setreg(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000012105 typval_T *argvars;
12106 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012107{
12108 int regname;
12109 char_u *strregname;
12110 char_u *stropt;
12111 int append;
12112 char_u yank_type;
12113 long block_len;
12114
12115 block_len = -1;
12116 yank_type = MAUTO;
12117 append = FALSE;
12118
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012119 strregname = get_tv_string(argvars);
12120 rettv->vval.v_number = 1; /* FAIL is default */
Bram Moolenaar071d4272004-06-13 20:20:40 +000012121
12122 regname = (strregname == NULL ? '"' : *strregname);
12123 if (regname == 0 || regname == '@')
12124 regname = '"';
12125 else if (regname == '=')
12126 return;
12127
Bram Moolenaar49cd9572005-01-03 21:06:01 +000012128 if (argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +000012129 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012130 for (stropt = get_tv_string(&argvars[2]); *stropt != NUL; ++stropt)
Bram Moolenaar071d4272004-06-13 20:20:40 +000012131 switch (*stropt)
12132 {
12133 case 'a': case 'A': /* append */
12134 append = TRUE;
12135 break;
12136 case 'v': case 'c': /* character-wise selection */
12137 yank_type = MCHAR;
12138 break;
12139 case 'V': case 'l': /* line-wise selection */
12140 yank_type = MLINE;
12141 break;
12142#ifdef FEAT_VISUAL
12143 case 'b': case Ctrl_V: /* block-wise selection */
12144 yank_type = MBLOCK;
12145 if (VIM_ISDIGIT(stropt[1]))
12146 {
12147 ++stropt;
12148 block_len = getdigits(&stropt) - 1;
12149 --stropt;
12150 }
12151 break;
12152#endif
12153 }
12154 }
12155
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012156 write_reg_contents_ex(regname, get_tv_string(&argvars[1]), -1,
Bram Moolenaar071d4272004-06-13 20:20:40 +000012157 append, yank_type, block_len);
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012158 rettv->vval.v_number = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012159}
12160
12161
12162/*
12163 * "setwinvar(expr)" function
12164 */
12165/*ARGSUSED*/
12166 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012167f_setwinvar(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000012168 typval_T *argvars;
12169 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012170{
12171 win_T *win;
12172#ifdef FEAT_WINDOWS
12173 win_T *save_curwin;
12174#endif
12175 char_u *varname, *winvarname;
Bram Moolenaar33570922005-01-25 22:26:29 +000012176 typval_T *varp;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012177 char_u nbuf[NUMBUFLEN];
12178
12179 if (check_restricted() || check_secure())
12180 return;
12181 ++emsg_off;
12182 win = find_win_by_nr(&argvars[0]);
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012183 varname = get_tv_string(&argvars[1]);
Bram Moolenaar071d4272004-06-13 20:20:40 +000012184 varp = &argvars[2];
12185
12186 if (win != NULL && varname != NULL && varp != NULL)
12187 {
12188#ifdef FEAT_WINDOWS
12189 /* set curwin to be our win, temporarily */
12190 save_curwin = curwin;
12191 curwin = win;
12192 curbuf = curwin->w_buffer;
12193#endif
12194
12195 if (*varname == '&')
12196 {
12197 ++varname;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012198 set_option_value(varname, get_tv_number(varp),
12199 get_tv_string_buf(varp, nbuf), OPT_LOCAL);
Bram Moolenaar071d4272004-06-13 20:20:40 +000012200 }
12201 else
12202 {
12203 winvarname = alloc((unsigned)STRLEN(varname) + 3);
12204 if (winvarname != NULL)
12205 {
12206 STRCPY(winvarname, "w:");
12207 STRCPY(winvarname + 2, varname);
Bram Moolenaar1c2fda22005-01-02 11:43:19 +000012208 set_var(winvarname, varp, TRUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +000012209 vim_free(winvarname);
12210 }
12211 }
12212
12213#ifdef FEAT_WINDOWS
12214 /* Restore current window, if it's still valid (autocomands can make
12215 * it invalid). */
12216 if (win_valid(save_curwin))
12217 {
12218 curwin = save_curwin;
12219 curbuf = curwin->w_buffer;
12220 }
12221#endif
12222 }
12223 --emsg_off;
12224}
12225
12226/*
Bram Moolenaar0d660222005-01-07 21:51:51 +000012227 * "simplify()" function
Bram Moolenaar071d4272004-06-13 20:20:40 +000012228 */
12229 static void
Bram Moolenaar0d660222005-01-07 21:51:51 +000012230f_simplify(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000012231 typval_T *argvars;
12232 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012233{
Bram Moolenaar0d660222005-01-07 21:51:51 +000012234 char_u *p;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012235
Bram Moolenaar0d660222005-01-07 21:51:51 +000012236 p = get_tv_string(&argvars[0]);
12237 rettv->vval.v_string = vim_strsave(p);
12238 simplify_filename(rettv->vval.v_string); /* simplify in place */
12239 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012240}
12241
Bram Moolenaar0d660222005-01-07 21:51:51 +000012242static int
12243#ifdef __BORLANDC__
12244 _RTLENTRYF
12245#endif
12246 item_compare __ARGS((const void *s1, const void *s2));
12247static int
12248#ifdef __BORLANDC__
12249 _RTLENTRYF
12250#endif
12251 item_compare2 __ARGS((const void *s1, const void *s2));
12252
12253static int item_compare_ic;
12254static char_u *item_compare_func;
12255#define ITEM_COMPARE_FAIL 999
12256
Bram Moolenaar071d4272004-06-13 20:20:40 +000012257/*
Bram Moolenaar0d660222005-01-07 21:51:51 +000012258 * Compare functions for f_sort() below.
Bram Moolenaar071d4272004-06-13 20:20:40 +000012259 */
Bram Moolenaar0d660222005-01-07 21:51:51 +000012260 static int
12261#ifdef __BORLANDC__
12262_RTLENTRYF
12263#endif
12264item_compare(s1, s2)
12265 const void *s1;
12266 const void *s2;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012267{
Bram Moolenaar0d660222005-01-07 21:51:51 +000012268 char_u *p1, *p2;
12269 char_u *tofree1, *tofree2;
12270 int res;
12271 char_u numbuf1[NUMBUFLEN];
12272 char_u numbuf2[NUMBUFLEN];
Bram Moolenaar071d4272004-06-13 20:20:40 +000012273
Bram Moolenaar33570922005-01-25 22:26:29 +000012274 p1 = tv2string(&(*(listitem_T **)s1)->li_tv, &tofree1, numbuf1);
12275 p2 = tv2string(&(*(listitem_T **)s2)->li_tv, &tofree2, numbuf2);
Bram Moolenaar0d660222005-01-07 21:51:51 +000012276 if (item_compare_ic)
12277 res = STRICMP(p1, p2);
Bram Moolenaar071d4272004-06-13 20:20:40 +000012278 else
Bram Moolenaar0d660222005-01-07 21:51:51 +000012279 res = STRCMP(p1, p2);
12280 vim_free(tofree1);
12281 vim_free(tofree2);
12282 return res;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012283}
12284
12285 static int
Bram Moolenaar0d660222005-01-07 21:51:51 +000012286#ifdef __BORLANDC__
12287_RTLENTRYF
Bram Moolenaar071d4272004-06-13 20:20:40 +000012288#endif
Bram Moolenaar0d660222005-01-07 21:51:51 +000012289item_compare2(s1, s2)
12290 const void *s1;
12291 const void *s2;
12292{
12293 int res;
Bram Moolenaar33570922005-01-25 22:26:29 +000012294 typval_T rettv;
12295 typval_T argv[2];
Bram Moolenaar0d660222005-01-07 21:51:51 +000012296 int dummy;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012297
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000012298 /* copy the values. This is needed to be able to set v_lock to VAR_FIXED
12299 * in the copy without changing the original list items. */
Bram Moolenaar33570922005-01-25 22:26:29 +000012300 copy_tv(&(*(listitem_T **)s1)->li_tv, &argv[0]);
12301 copy_tv(&(*(listitem_T **)s2)->li_tv, &argv[1]);
Bram Moolenaar0d660222005-01-07 21:51:51 +000012302
12303 rettv.v_type = VAR_UNKNOWN; /* clear_tv() uses this */
12304 res = call_func(item_compare_func, STRLEN(item_compare_func),
Bram Moolenaare9a41262005-01-15 22:18:47 +000012305 &rettv, 2, argv, 0L, 0L, &dummy, TRUE, NULL);
Bram Moolenaar0d660222005-01-07 21:51:51 +000012306 clear_tv(&argv[0]);
12307 clear_tv(&argv[1]);
12308
12309 if (res == FAIL)
12310 res = ITEM_COMPARE_FAIL;
12311 else
12312 res = get_tv_number(&rettv);
12313 clear_tv(&rettv);
12314 return res;
12315}
12316
12317/*
12318 * "sort({list})" function
12319 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000012320 static void
Bram Moolenaar0d660222005-01-07 21:51:51 +000012321f_sort(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000012322 typval_T *argvars;
12323 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012324{
Bram Moolenaar33570922005-01-25 22:26:29 +000012325 list_T *l;
12326 listitem_T *li;
12327 listitem_T **ptrs;
Bram Moolenaar0d660222005-01-07 21:51:51 +000012328 long len;
12329 long i;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012330
Bram Moolenaar0d660222005-01-07 21:51:51 +000012331 rettv->vval.v_number = 0;
12332 if (argvars[0].v_type != VAR_LIST)
12333 EMSG2(_(e_listarg), "sort()");
Bram Moolenaar071d4272004-06-13 20:20:40 +000012334 else
12335 {
Bram Moolenaar0d660222005-01-07 21:51:51 +000012336 l = argvars[0].vval.v_list;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000012337 if (l == NULL || tv_check_lock(l->lv_lock, (char_u *)"sort()"))
Bram Moolenaar0d660222005-01-07 21:51:51 +000012338 return;
12339 rettv->vval.v_list = l;
12340 rettv->v_type = VAR_LIST;
12341 ++l->lv_refcount;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012342
Bram Moolenaar0d660222005-01-07 21:51:51 +000012343 len = list_len(l);
12344 if (len <= 1)
12345 return; /* short list sorts pretty quickly */
Bram Moolenaar071d4272004-06-13 20:20:40 +000012346
Bram Moolenaar0d660222005-01-07 21:51:51 +000012347 item_compare_ic = FALSE;
12348 item_compare_func = NULL;
12349 if (argvars[1].v_type != VAR_UNKNOWN)
12350 {
12351 if (argvars[1].v_type == VAR_FUNC)
12352 item_compare_func = argvars[0].vval.v_string;
12353 else
12354 {
12355 i = get_tv_number(&argvars[1]);
12356 if (i == 1)
12357 item_compare_ic = TRUE;
12358 else
12359 item_compare_func = get_tv_string(&argvars[1]);
12360 }
12361 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000012362
Bram Moolenaar0d660222005-01-07 21:51:51 +000012363 /* Make an array with each entry pointing to an item in the List. */
Bram Moolenaar33570922005-01-25 22:26:29 +000012364 ptrs = (listitem_T **)alloc((int)(len * sizeof(listitem_T *)));
Bram Moolenaar0d660222005-01-07 21:51:51 +000012365 if (ptrs == NULL)
12366 return;
12367 i = 0;
12368 for (li = l->lv_first; li != NULL; li = li->li_next)
12369 ptrs[i++] = li;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012370
Bram Moolenaar0d660222005-01-07 21:51:51 +000012371 /* test the compare function */
12372 if (item_compare_func != NULL
12373 && item_compare2((void *)&ptrs[0], (void *)&ptrs[1])
12374 == ITEM_COMPARE_FAIL)
Bram Moolenaare49b69a2005-01-08 16:11:57 +000012375 EMSG(_("E702: Sort compare function failed"));
Bram Moolenaar071d4272004-06-13 20:20:40 +000012376 else
Bram Moolenaar0d660222005-01-07 21:51:51 +000012377 {
12378 /* Sort the array with item pointers. */
Bram Moolenaar33570922005-01-25 22:26:29 +000012379 qsort((void *)ptrs, (size_t)len, sizeof(listitem_T *),
Bram Moolenaar0d660222005-01-07 21:51:51 +000012380 item_compare_func == NULL ? item_compare : item_compare2);
12381
12382 /* Clear the List and append the items in the sorted order. */
12383 l->lv_first = l->lv_last = NULL;
Bram Moolenaar758711c2005-02-02 23:11:38 +000012384 l->lv_len = 0;
Bram Moolenaar0d660222005-01-07 21:51:51 +000012385 for (i = 0; i < len; ++i)
12386 list_append(l, ptrs[i]);
12387 }
12388
12389 vim_free(ptrs);
12390 }
12391}
12392
12393 static void
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000012394f_split(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000012395 typval_T *argvars;
12396 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000012397{
12398 char_u *str;
12399 char_u *end;
12400 char_u *pat;
12401 regmatch_T regmatch;
12402 char_u patbuf[NUMBUFLEN];
12403 char_u *save_cpo;
12404 int match;
Bram Moolenaar33570922005-01-25 22:26:29 +000012405 listitem_T *ni;
12406 list_T *l;
Bram Moolenaar0d660222005-01-07 21:51:51 +000012407 colnr_T col = 0;
12408
12409 /* Make 'cpoptions' empty, the 'l' flag should not be used here. */
12410 save_cpo = p_cpo;
12411 p_cpo = (char_u *)"";
12412
12413 str = get_tv_string(&argvars[0]);
12414 if (argvars[1].v_type == VAR_UNKNOWN)
12415 pat = (char_u *)"[\\x01- ]\\+";
12416 else
12417 pat = get_tv_string_buf(&argvars[1], patbuf);
12418
12419 l = list_alloc();
12420 if (l == NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000012421 return;
Bram Moolenaar0d660222005-01-07 21:51:51 +000012422 rettv->v_type = VAR_LIST;
12423 rettv->vval.v_list = l;
12424 ++l->lv_refcount;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012425
Bram Moolenaar0d660222005-01-07 21:51:51 +000012426 regmatch.regprog = vim_regcomp(pat, RE_MAGIC + RE_STRING);
12427 if (regmatch.regprog != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000012428 {
Bram Moolenaar0d660222005-01-07 21:51:51 +000012429 regmatch.rm_ic = FALSE;
12430 while (*str != NUL)
12431 {
12432 match = vim_regexec_nl(&regmatch, str, col);
12433 if (match)
12434 end = regmatch.startp[0];
12435 else
12436 end = str + STRLEN(str);
12437 if (end > str)
12438 {
12439 ni = listitem_alloc();
12440 if (ni == NULL)
12441 break;
12442 ni->li_tv.v_type = VAR_STRING;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000012443 ni->li_tv.v_lock = 0;
Bram Moolenaar0d660222005-01-07 21:51:51 +000012444 ni->li_tv.vval.v_string = vim_strnsave(str, end - str);
12445 list_append(l, ni);
12446 }
12447 if (!match)
12448 break;
12449 /* Advance to just after the match. */
12450 if (regmatch.endp[0] > str)
12451 col = 0;
12452 else
12453 {
12454 /* Don't get stuck at the same match. */
12455#ifdef FEAT_MBYTE
12456 col = mb_ptr2len_check(regmatch.endp[0]);
12457#else
12458 col = 1;
12459#endif
12460 }
12461 str = regmatch.endp[0];
12462 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000012463
Bram Moolenaar0d660222005-01-07 21:51:51 +000012464 vim_free(regmatch.regprog);
Bram Moolenaar071d4272004-06-13 20:20:40 +000012465 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000012466
Bram Moolenaar0d660222005-01-07 21:51:51 +000012467 p_cpo = save_cpo;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012468}
12469
12470#ifdef HAVE_STRFTIME
12471/*
12472 * "strftime({format}[, {time}])" function
12473 */
12474 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012475f_strftime(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000012476 typval_T *argvars;
12477 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012478{
12479 char_u result_buf[256];
12480 struct tm *curtime;
12481 time_t seconds;
12482 char_u *p;
12483
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012484 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012485
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012486 p = get_tv_string(&argvars[0]);
Bram Moolenaar49cd9572005-01-03 21:06:01 +000012487 if (argvars[1].v_type == VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +000012488 seconds = time(NULL);
12489 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012490 seconds = (time_t)get_tv_number(&argvars[1]);
Bram Moolenaar071d4272004-06-13 20:20:40 +000012491 curtime = localtime(&seconds);
12492 /* MSVC returns NULL for an invalid value of seconds. */
12493 if (curtime == NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012494 rettv->vval.v_string = vim_strsave((char_u *)_("(Invalid)"));
Bram Moolenaar071d4272004-06-13 20:20:40 +000012495 else
12496 {
12497# ifdef FEAT_MBYTE
12498 vimconv_T conv;
12499 char_u *enc;
12500
12501 conv.vc_type = CONV_NONE;
12502 enc = enc_locale();
12503 convert_setup(&conv, p_enc, enc);
12504 if (conv.vc_type != CONV_NONE)
12505 p = string_convert(&conv, p, NULL);
12506# endif
12507 if (p != NULL)
12508 (void)strftime((char *)result_buf, sizeof(result_buf),
12509 (char *)p, curtime);
12510 else
12511 result_buf[0] = NUL;
12512
12513# ifdef FEAT_MBYTE
12514 if (conv.vc_type != CONV_NONE)
12515 vim_free(p);
12516 convert_setup(&conv, enc, p_enc);
12517 if (conv.vc_type != CONV_NONE)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012518 rettv->vval.v_string = string_convert(&conv, result_buf, NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +000012519 else
12520# endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012521 rettv->vval.v_string = vim_strsave(result_buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +000012522
12523# ifdef FEAT_MBYTE
12524 /* Release conversion descriptors */
12525 convert_setup(&conv, NULL, NULL);
12526 vim_free(enc);
12527# endif
12528 }
12529}
12530#endif
12531
12532/*
12533 * "stridx()" function
12534 */
12535 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012536f_stridx(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000012537 typval_T *argvars;
12538 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012539{
12540 char_u buf[NUMBUFLEN];
12541 char_u *needle;
12542 char_u *haystack;
Bram Moolenaar33570922005-01-25 22:26:29 +000012543 char_u *save_haystack;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012544 char_u *pos;
Bram Moolenaar33570922005-01-25 22:26:29 +000012545 int start_idx;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012546
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012547 needle = get_tv_string(&argvars[1]);
Bram Moolenaar33570922005-01-25 22:26:29 +000012548 save_haystack = haystack = get_tv_string_buf(&argvars[0], buf);
12549 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012550
Bram Moolenaar33570922005-01-25 22:26:29 +000012551 if (argvars[2].v_type != VAR_UNKNOWN)
12552 {
12553 start_idx = get_tv_number(&argvars[2]);
Bram Moolenaar532c7802005-01-27 14:44:31 +000012554 if (start_idx >= (int)STRLEN(haystack))
Bram Moolenaar33570922005-01-25 22:26:29 +000012555 return;
Bram Moolenaar532c7802005-01-27 14:44:31 +000012556 if (start_idx >= 0)
12557 haystack += start_idx;
Bram Moolenaar33570922005-01-25 22:26:29 +000012558 }
12559
12560 pos = (char_u *)strstr((char *)haystack, (char *)needle);
12561 if (pos != NULL)
12562 rettv->vval.v_number = (varnumber_T)(pos - save_haystack);
Bram Moolenaar071d4272004-06-13 20:20:40 +000012563}
12564
12565/*
Bram Moolenaar49cd9572005-01-03 21:06:01 +000012566 * "string()" function
12567 */
12568 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012569f_string(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000012570 typval_T *argvars;
12571 typval_T *rettv;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000012572{
12573 char_u *tofree;
Bram Moolenaar8a283e52005-01-06 23:28:25 +000012574 char_u numbuf[NUMBUFLEN];
Bram Moolenaar49cd9572005-01-03 21:06:01 +000012575
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012576 rettv->v_type = VAR_STRING;
Bram Moolenaar8a283e52005-01-06 23:28:25 +000012577 rettv->vval.v_string = tv2string(&argvars[0], &tofree, numbuf);
Bram Moolenaar49cd9572005-01-03 21:06:01 +000012578 if (tofree == NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012579 rettv->vval.v_string = vim_strsave(rettv->vval.v_string);
Bram Moolenaar071d4272004-06-13 20:20:40 +000012580}
12581
12582/*
12583 * "strlen()" function
12584 */
12585 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012586f_strlen(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000012587 typval_T *argvars;
12588 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012589{
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012590 rettv->vval.v_number = (varnumber_T)(STRLEN(
12591 get_tv_string(&argvars[0])));
Bram Moolenaar071d4272004-06-13 20:20:40 +000012592}
12593
12594/*
12595 * "strpart()" function
12596 */
12597 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012598f_strpart(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000012599 typval_T *argvars;
12600 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012601{
12602 char_u *p;
12603 int n;
12604 int len;
12605 int slen;
12606
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012607 p = get_tv_string(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +000012608 slen = (int)STRLEN(p);
12609
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012610 n = get_tv_number(&argvars[1]);
Bram Moolenaar49cd9572005-01-03 21:06:01 +000012611 if (argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012612 len = get_tv_number(&argvars[2]);
Bram Moolenaar071d4272004-06-13 20:20:40 +000012613 else
12614 len = slen - n; /* default len: all bytes that are available. */
12615
12616 /*
12617 * Only return the overlap between the specified part and the actual
12618 * string.
12619 */
12620 if (n < 0)
12621 {
12622 len += n;
12623 n = 0;
12624 }
12625 else if (n > slen)
12626 n = slen;
12627 if (len < 0)
12628 len = 0;
12629 else if (n + len > slen)
12630 len = slen - n;
12631
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012632 rettv->v_type = VAR_STRING;
12633 rettv->vval.v_string = vim_strnsave(p + n, len);
Bram Moolenaar071d4272004-06-13 20:20:40 +000012634}
12635
12636/*
Bram Moolenaar0d660222005-01-07 21:51:51 +000012637 * "strridx()" function
12638 */
12639 static void
12640f_strridx(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000012641 typval_T *argvars;
12642 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000012643{
12644 char_u buf[NUMBUFLEN];
12645 char_u *needle;
12646 char_u *haystack;
12647 char_u *rest;
12648 char_u *lastmatch = NULL;
Bram Moolenaar532c7802005-01-27 14:44:31 +000012649 int haystack_len, end_idx;
Bram Moolenaar0d660222005-01-07 21:51:51 +000012650
12651 needle = get_tv_string(&argvars[1]);
12652 haystack = get_tv_string_buf(&argvars[0], buf);
Bram Moolenaar532c7802005-01-27 14:44:31 +000012653 haystack_len = STRLEN(haystack);
Bram Moolenaar0d660222005-01-07 21:51:51 +000012654 if (*needle == NUL)
12655 /* Empty string matches past the end. */
Bram Moolenaar532c7802005-01-27 14:44:31 +000012656 lastmatch = haystack + haystack_len;
Bram Moolenaar0d660222005-01-07 21:51:51 +000012657 else
Bram Moolenaar532c7802005-01-27 14:44:31 +000012658 {
12659 if (argvars[2].v_type != VAR_UNKNOWN)
12660 {
12661 /* Third argument: upper limit for index */
12662 end_idx = get_tv_number(&argvars[2]);
12663 if (end_idx < 0)
12664 {
12665 /* can never find a match */
12666 rettv->vval.v_number = -1;
12667 return;
12668 }
12669 }
12670 else
12671 end_idx = haystack_len;
12672
Bram Moolenaar0d660222005-01-07 21:51:51 +000012673 for (rest = haystack; *rest != '\0'; ++rest)
12674 {
12675 rest = (char_u *)strstr((char *)rest, (char *)needle);
Bram Moolenaar532c7802005-01-27 14:44:31 +000012676 if (rest == NULL || rest > haystack + end_idx)
Bram Moolenaar0d660222005-01-07 21:51:51 +000012677 break;
12678 lastmatch = rest;
12679 }
Bram Moolenaar532c7802005-01-27 14:44:31 +000012680 }
Bram Moolenaar0d660222005-01-07 21:51:51 +000012681
12682 if (lastmatch == NULL)
12683 rettv->vval.v_number = -1;
12684 else
12685 rettv->vval.v_number = (varnumber_T)(lastmatch - haystack);
12686}
12687
12688/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000012689 * "strtrans()" function
12690 */
12691 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012692f_strtrans(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000012693 typval_T *argvars;
12694 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012695{
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012696 rettv->v_type = VAR_STRING;
12697 rettv->vval.v_string = transstr(get_tv_string(&argvars[0]));
Bram Moolenaar071d4272004-06-13 20:20:40 +000012698}
12699
12700/*
Bram Moolenaar0d660222005-01-07 21:51:51 +000012701 * "submatch()" function
12702 */
12703 static void
12704f_submatch(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000012705 typval_T *argvars;
12706 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000012707{
12708 rettv->v_type = VAR_STRING;
12709 rettv->vval.v_string = reg_submatch((int)get_tv_number(&argvars[0]));
12710}
12711
12712/*
12713 * "substitute()" function
12714 */
12715 static void
12716f_substitute(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000012717 typval_T *argvars;
12718 typval_T *rettv;
Bram Moolenaar0d660222005-01-07 21:51:51 +000012719{
12720 char_u patbuf[NUMBUFLEN];
12721 char_u subbuf[NUMBUFLEN];
12722 char_u flagsbuf[NUMBUFLEN];
12723
12724 rettv->v_type = VAR_STRING;
12725 rettv->vval.v_string = do_string_sub(
12726 get_tv_string(&argvars[0]),
12727 get_tv_string_buf(&argvars[1], patbuf),
12728 get_tv_string_buf(&argvars[2], subbuf),
12729 get_tv_string_buf(&argvars[3], flagsbuf));
12730}
12731
12732/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000012733 * "synID(line, col, trans)" function
12734 */
12735/*ARGSUSED*/
12736 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012737f_synID(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000012738 typval_T *argvars;
12739 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012740{
12741 int id = 0;
12742#ifdef FEAT_SYN_HL
12743 long line;
12744 long col;
12745 int trans;
12746
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012747 line = get_tv_lnum(argvars);
12748 col = get_tv_number(&argvars[1]) - 1;
12749 trans = get_tv_number(&argvars[2]);
Bram Moolenaar071d4272004-06-13 20:20:40 +000012750
12751 if (line >= 1 && line <= curbuf->b_ml.ml_line_count
12752 && col >= 0 && col < (long)STRLEN(ml_get(line)))
12753 id = syn_get_id(line, col, trans);
12754#endif
12755
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012756 rettv->vval.v_number = id;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012757}
12758
12759/*
12760 * "synIDattr(id, what [, mode])" function
12761 */
12762/*ARGSUSED*/
12763 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012764f_synIDattr(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000012765 typval_T *argvars;
12766 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012767{
12768 char_u *p = NULL;
12769#ifdef FEAT_SYN_HL
12770 int id;
12771 char_u *what;
12772 char_u *mode;
12773 char_u modebuf[NUMBUFLEN];
12774 int modec;
12775
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012776 id = get_tv_number(&argvars[0]);
12777 what = get_tv_string(&argvars[1]);
Bram Moolenaar49cd9572005-01-03 21:06:01 +000012778 if (argvars[2].v_type != VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +000012779 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012780 mode = get_tv_string_buf(&argvars[2], modebuf);
Bram Moolenaar071d4272004-06-13 20:20:40 +000012781 modec = TOLOWER_ASC(mode[0]);
12782 if (modec != 't' && modec != 'c'
12783#ifdef FEAT_GUI
12784 && modec != 'g'
12785#endif
12786 )
12787 modec = 0; /* replace invalid with current */
12788 }
12789 else
12790 {
12791#ifdef FEAT_GUI
12792 if (gui.in_use)
12793 modec = 'g';
12794 else
12795#endif
12796 if (t_colors > 1)
12797 modec = 'c';
12798 else
12799 modec = 't';
12800 }
12801
12802
12803 switch (TOLOWER_ASC(what[0]))
12804 {
12805 case 'b':
12806 if (TOLOWER_ASC(what[1]) == 'g') /* bg[#] */
12807 p = highlight_color(id, what, modec);
12808 else /* bold */
12809 p = highlight_has_attr(id, HL_BOLD, modec);
12810 break;
12811
12812 case 'f': /* fg[#] */
12813 p = highlight_color(id, what, modec);
12814 break;
12815
12816 case 'i':
12817 if (TOLOWER_ASC(what[1]) == 'n') /* inverse */
12818 p = highlight_has_attr(id, HL_INVERSE, modec);
12819 else /* italic */
12820 p = highlight_has_attr(id, HL_ITALIC, modec);
12821 break;
12822
12823 case 'n': /* name */
12824 p = get_highlight_name(NULL, id - 1);
12825 break;
12826
12827 case 'r': /* reverse */
12828 p = highlight_has_attr(id, HL_INVERSE, modec);
12829 break;
12830
12831 case 's': /* standout */
12832 p = highlight_has_attr(id, HL_STANDOUT, modec);
12833 break;
12834
12835 case 'u': /* underline */
12836 p = highlight_has_attr(id, HL_UNDERLINE, modec);
12837 break;
12838 }
12839
12840 if (p != NULL)
12841 p = vim_strsave(p);
12842#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012843 rettv->v_type = VAR_STRING;
12844 rettv->vval.v_string = p;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012845}
12846
12847/*
12848 * "synIDtrans(id)" function
12849 */
12850/*ARGSUSED*/
12851 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012852f_synIDtrans(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000012853 typval_T *argvars;
12854 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012855{
12856 int id;
12857
12858#ifdef FEAT_SYN_HL
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012859 id = get_tv_number(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +000012860
12861 if (id > 0)
12862 id = syn_get_final_id(id);
12863 else
12864#endif
12865 id = 0;
12866
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012867 rettv->vval.v_number = id;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012868}
12869
12870/*
12871 * "system()" function
12872 */
12873 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012874f_system(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000012875 typval_T *argvars;
12876 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012877{
Bram Moolenaarc0197e22004-09-13 20:26:32 +000012878 char_u *res = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012879 char_u *p;
Bram Moolenaarc0197e22004-09-13 20:26:32 +000012880 char_u *infile = NULL;
12881 char_u buf[NUMBUFLEN];
12882 int err = FALSE;
12883 FILE *fd;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012884
Bram Moolenaar49cd9572005-01-03 21:06:01 +000012885 if (argvars[1].v_type != VAR_UNKNOWN)
Bram Moolenaarc0197e22004-09-13 20:26:32 +000012886 {
12887 /*
12888 * Write the string to a temp file, to be used for input of the shell
12889 * command.
12890 */
12891 if ((infile = vim_tempname('i')) == NULL)
12892 {
12893 EMSG(_(e_notmp));
12894 return;
12895 }
12896
12897 fd = mch_fopen((char *)infile, WRITEBIN);
12898 if (fd == NULL)
12899 {
12900 EMSG2(_(e_notopen), infile);
12901 goto done;
12902 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012903 p = get_tv_string_buf(&argvars[1], buf);
Bram Moolenaarc0197e22004-09-13 20:26:32 +000012904 if (fwrite(p, STRLEN(p), 1, fd) != 1)
12905 err = TRUE;
12906 if (fclose(fd) != 0)
12907 err = TRUE;
12908 if (err)
12909 {
12910 EMSG(_("E677: Error writing temp file"));
12911 goto done;
12912 }
12913 }
12914
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012915 res = get_cmd_output(get_tv_string(&argvars[0]), infile, SHELL_SILENT);
Bram Moolenaarc0197e22004-09-13 20:26:32 +000012916
Bram Moolenaar071d4272004-06-13 20:20:40 +000012917#ifdef USE_CR
12918 /* translate <CR> into <NL> */
Bram Moolenaarc0197e22004-09-13 20:26:32 +000012919 if (res != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000012920 {
12921 char_u *s;
12922
Bram Moolenaarc0197e22004-09-13 20:26:32 +000012923 for (s = res; *s; ++s)
Bram Moolenaar071d4272004-06-13 20:20:40 +000012924 {
12925 if (*s == CAR)
12926 *s = NL;
12927 }
12928 }
12929#else
12930# ifdef USE_CRNL
12931 /* translate <CR><NL> into <NL> */
Bram Moolenaarc0197e22004-09-13 20:26:32 +000012932 if (res != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000012933 {
12934 char_u *s, *d;
12935
Bram Moolenaarc0197e22004-09-13 20:26:32 +000012936 d = res;
12937 for (s = res; *s; ++s)
Bram Moolenaar071d4272004-06-13 20:20:40 +000012938 {
12939 if (s[0] == CAR && s[1] == NL)
12940 ++s;
12941 *d++ = *s;
12942 }
12943 *d = NUL;
12944 }
12945# endif
12946#endif
Bram Moolenaarc0197e22004-09-13 20:26:32 +000012947
12948done:
12949 if (infile != NULL)
12950 {
12951 mch_remove(infile);
12952 vim_free(infile);
12953 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012954 rettv->v_type = VAR_STRING;
12955 rettv->vval.v_string = res;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012956}
12957
12958/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000012959 * "tempname()" function
12960 */
12961/*ARGSUSED*/
12962 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012963f_tempname(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000012964 typval_T *argvars;
12965 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000012966{
12967 static int x = 'A';
12968
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012969 rettv->v_type = VAR_STRING;
12970 rettv->vval.v_string = vim_tempname(x);
Bram Moolenaar071d4272004-06-13 20:20:40 +000012971
12972 /* Advance 'x' to use A-Z and 0-9, so that there are at least 34 different
12973 * names. Skip 'I' and 'O', they are used for shell redirection. */
12974 do
12975 {
12976 if (x == 'Z')
12977 x = '0';
12978 else if (x == '9')
12979 x = 'A';
12980 else
12981 {
12982#ifdef EBCDIC
12983 if (x == 'I')
12984 x = 'J';
12985 else if (x == 'R')
12986 x = 'S';
12987 else
12988#endif
12989 ++x;
12990 }
12991 } while (x == 'I' || x == 'O');
12992}
12993
12994/*
12995 * "tolower(string)" function
12996 */
12997 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000012998f_tolower(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000012999 typval_T *argvars;
13000 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013001{
13002 char_u *p;
13003
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013004 p = vim_strsave(get_tv_string(&argvars[0]));
13005 rettv->v_type = VAR_STRING;
13006 rettv->vval.v_string = p;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013007
13008 if (p != NULL)
13009 while (*p != NUL)
13010 {
13011#ifdef FEAT_MBYTE
13012 int l;
13013
13014 if (enc_utf8)
13015 {
13016 int c, lc;
13017
13018 c = utf_ptr2char(p);
13019 lc = utf_tolower(c);
13020 l = utf_ptr2len_check(p);
13021 /* TODO: reallocate string when byte count changes. */
13022 if (utf_char2len(lc) == l)
13023 utf_char2bytes(lc, p);
13024 p += l;
13025 }
13026 else if (has_mbyte && (l = (*mb_ptr2len_check)(p)) > 1)
13027 p += l; /* skip multi-byte character */
13028 else
13029#endif
13030 {
13031 *p = TOLOWER_LOC(*p); /* note that tolower() can be a macro */
13032 ++p;
13033 }
13034 }
13035}
13036
13037/*
13038 * "toupper(string)" function
13039 */
13040 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013041f_toupper(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000013042 typval_T *argvars;
13043 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013044{
13045 char_u *p;
13046
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013047 p = vim_strsave(get_tv_string(&argvars[0]));
13048 rettv->v_type = VAR_STRING;
13049 rettv->vval.v_string = p;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013050
13051 if (p != NULL)
13052 while (*p != NUL)
13053 {
13054#ifdef FEAT_MBYTE
13055 int l;
13056
13057 if (enc_utf8)
13058 {
13059 int c, uc;
13060
13061 c = utf_ptr2char(p);
13062 uc = utf_toupper(c);
13063 l = utf_ptr2len_check(p);
13064 /* TODO: reallocate string when byte count changes. */
13065 if (utf_char2len(uc) == l)
13066 utf_char2bytes(uc, p);
13067 p += l;
13068 }
13069 else if (has_mbyte && (l = (*mb_ptr2len_check)(p)) > 1)
13070 p += l; /* skip multi-byte character */
13071 else
13072#endif
13073 {
13074 *p = TOUPPER_LOC(*p); /* note that toupper() can be a macro */
13075 p++;
13076 }
13077 }
13078}
13079
13080/*
Bram Moolenaar8299df92004-07-10 09:47:34 +000013081 * "tr(string, fromstr, tostr)" function
13082 */
13083 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013084f_tr(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000013085 typval_T *argvars;
13086 typval_T *rettv;
Bram Moolenaar8299df92004-07-10 09:47:34 +000013087{
13088 char_u *instr;
13089 char_u *fromstr;
13090 char_u *tostr;
13091 char_u *p;
13092#ifdef FEAT_MBYTE
13093 int inlen;
13094 int fromlen;
13095 int tolen;
13096 int idx;
13097 char_u *cpstr;
13098 int cplen;
13099 int first = TRUE;
13100#endif
13101 char_u buf[NUMBUFLEN];
13102 char_u buf2[NUMBUFLEN];
13103 garray_T ga;
13104
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013105 instr = get_tv_string(&argvars[0]);
13106 fromstr = get_tv_string_buf(&argvars[1], buf);
13107 tostr = get_tv_string_buf(&argvars[2], buf2);
Bram Moolenaar8299df92004-07-10 09:47:34 +000013108
13109 /* Default return value: empty string. */
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013110 rettv->v_type = VAR_STRING;
13111 rettv->vval.v_string = NULL;
Bram Moolenaar8299df92004-07-10 09:47:34 +000013112 ga_init2(&ga, (int)sizeof(char), 80);
13113
13114#ifdef FEAT_MBYTE
13115 if (!has_mbyte)
13116#endif
13117 /* not multi-byte: fromstr and tostr must be the same length */
13118 if (STRLEN(fromstr) != STRLEN(tostr))
13119 {
Bram Moolenaar5eb86f92004-07-26 12:53:41 +000013120#ifdef FEAT_MBYTE
Bram Moolenaar8299df92004-07-10 09:47:34 +000013121error:
Bram Moolenaar5eb86f92004-07-26 12:53:41 +000013122#endif
Bram Moolenaar8299df92004-07-10 09:47:34 +000013123 EMSG2(_(e_invarg2), fromstr);
13124 ga_clear(&ga);
13125 return;
13126 }
13127
13128 /* fromstr and tostr have to contain the same number of chars */
13129 while (*instr != NUL)
13130 {
13131#ifdef FEAT_MBYTE
13132 if (has_mbyte)
13133 {
13134 inlen = mb_ptr2len_check(instr);
13135 cpstr = instr;
13136 cplen = inlen;
13137 idx = 0;
13138 for (p = fromstr; *p != NUL; p += fromlen)
13139 {
13140 fromlen = mb_ptr2len_check(p);
13141 if (fromlen == inlen && STRNCMP(instr, p, inlen) == 0)
13142 {
13143 for (p = tostr; *p != NUL; p += tolen)
13144 {
13145 tolen = mb_ptr2len_check(p);
13146 if (idx-- == 0)
13147 {
13148 cplen = tolen;
13149 cpstr = p;
13150 break;
13151 }
13152 }
13153 if (*p == NUL) /* tostr is shorter than fromstr */
13154 goto error;
13155 break;
13156 }
13157 ++idx;
13158 }
13159
13160 if (first && cpstr == instr)
13161 {
13162 /* Check that fromstr and tostr have the same number of
13163 * (multi-byte) characters. Done only once when a character
13164 * of instr doesn't appear in fromstr. */
13165 first = FALSE;
13166 for (p = tostr; *p != NUL; p += tolen)
13167 {
13168 tolen = mb_ptr2len_check(p);
13169 --idx;
13170 }
13171 if (idx != 0)
13172 goto error;
13173 }
13174
13175 ga_grow(&ga, cplen);
Bram Moolenaar2df6dcc2004-07-12 15:53:54 +000013176 mch_memmove((char *)ga.ga_data + ga.ga_len, cpstr, (size_t)cplen);
Bram Moolenaar8299df92004-07-10 09:47:34 +000013177 ga.ga_len += cplen;
Bram Moolenaar8299df92004-07-10 09:47:34 +000013178
13179 instr += inlen;
13180 }
13181 else
13182#endif
13183 {
13184 /* When not using multi-byte chars we can do it faster. */
13185 p = vim_strchr(fromstr, *instr);
13186 if (p != NULL)
13187 ga_append(&ga, tostr[p - fromstr]);
13188 else
13189 ga_append(&ga, *instr);
13190 ++instr;
13191 }
13192 }
13193
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013194 rettv->vval.v_string = ga.ga_data;
Bram Moolenaar8299df92004-07-10 09:47:34 +000013195}
13196
13197/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000013198 * "type(expr)" function
13199 */
13200 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013201f_type(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000013202 typval_T *argvars;
13203 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013204{
Bram Moolenaar6cc16192005-01-08 21:49:45 +000013205 int n;
13206
13207 switch (argvars[0].v_type)
13208 {
13209 case VAR_NUMBER: n = 0; break;
13210 case VAR_STRING: n = 1; break;
13211 case VAR_FUNC: n = 2; break;
13212 case VAR_LIST: n = 3; break;
Bram Moolenaar758711c2005-02-02 23:11:38 +000013213 case VAR_DICT: n = 4; break;
Bram Moolenaar6cc16192005-01-08 21:49:45 +000013214 default: EMSG2(_(e_intern2), "f_type()"); n = 0; break;
13215 }
13216 rettv->vval.v_number = n;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013217}
13218
13219/*
Bram Moolenaar8c711452005-01-14 21:53:12 +000013220 * "values(dict)" function
13221 */
13222 static void
13223f_values(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000013224 typval_T *argvars;
13225 typval_T *rettv;
Bram Moolenaar8c711452005-01-14 21:53:12 +000013226{
13227 dict_list(argvars, rettv, 1);
13228}
13229
13230/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000013231 * "virtcol(string)" function
13232 */
13233 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013234f_virtcol(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000013235 typval_T *argvars;
13236 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013237{
13238 colnr_T vcol = 0;
13239 pos_T *fp;
13240
13241 fp = var2fpos(&argvars[0], FALSE);
13242 if (fp != NULL && fp->lnum <= curbuf->b_ml.ml_line_count)
13243 {
13244 getvvcol(curwin, fp, NULL, NULL, &vcol);
13245 ++vcol;
13246 }
13247
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013248 rettv->vval.v_number = vcol;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013249}
13250
13251/*
13252 * "visualmode()" function
13253 */
13254/*ARGSUSED*/
13255 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013256f_visualmode(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000013257 typval_T *argvars;
13258 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013259{
13260#ifdef FEAT_VISUAL
13261 char_u str[2];
13262
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013263 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013264 str[0] = curbuf->b_visual_mode_eval;
13265 str[1] = NUL;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013266 rettv->vval.v_string = vim_strsave(str);
Bram Moolenaar071d4272004-06-13 20:20:40 +000013267
13268 /* A non-zero number or non-empty string argument: reset mode. */
Bram Moolenaar49cd9572005-01-03 21:06:01 +000013269 if ((argvars[0].v_type == VAR_NUMBER
13270 && argvars[0].vval.v_number != 0)
13271 || (argvars[0].v_type == VAR_STRING
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013272 && *get_tv_string(&argvars[0]) != NUL))
Bram Moolenaar071d4272004-06-13 20:20:40 +000013273 curbuf->b_visual_mode_eval = NUL;
13274#else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013275 rettv->vval.v_number = 0; /* return anything, it won't work anyway */
Bram Moolenaar071d4272004-06-13 20:20:40 +000013276#endif
13277}
13278
13279/*
13280 * "winbufnr(nr)" function
13281 */
13282 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013283f_winbufnr(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000013284 typval_T *argvars;
13285 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013286{
13287 win_T *wp;
13288
13289 wp = find_win_by_nr(&argvars[0]);
13290 if (wp == NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013291 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013292 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013293 rettv->vval.v_number = wp->w_buffer->b_fnum;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013294}
13295
13296/*
13297 * "wincol()" function
13298 */
13299/*ARGSUSED*/
13300 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013301f_wincol(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000013302 typval_T *argvars;
13303 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013304{
13305 validate_cursor();
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013306 rettv->vval.v_number = curwin->w_wcol + 1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013307}
13308
13309/*
13310 * "winheight(nr)" function
13311 */
13312 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013313f_winheight(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000013314 typval_T *argvars;
13315 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013316{
13317 win_T *wp;
13318
13319 wp = find_win_by_nr(&argvars[0]);
13320 if (wp == NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013321 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013322 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013323 rettv->vval.v_number = wp->w_height;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013324}
13325
13326/*
13327 * "winline()" function
13328 */
13329/*ARGSUSED*/
13330 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013331f_winline(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000013332 typval_T *argvars;
13333 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013334{
13335 validate_cursor();
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013336 rettv->vval.v_number = curwin->w_wrow + 1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013337}
13338
13339/*
13340 * "winnr()" function
13341 */
13342/* ARGSUSED */
13343 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013344f_winnr(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000013345 typval_T *argvars;
13346 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013347{
13348 int nr = 1;
13349#ifdef FEAT_WINDOWS
13350 win_T *wp;
Bram Moolenaar5eb86f92004-07-26 12:53:41 +000013351 win_T *twin = curwin;
13352 char_u *arg;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013353
Bram Moolenaar49cd9572005-01-03 21:06:01 +000013354 if (argvars[0].v_type != VAR_UNKNOWN)
Bram Moolenaar5eb86f92004-07-26 12:53:41 +000013355 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013356 arg = get_tv_string(&argvars[0]);
Bram Moolenaar5eb86f92004-07-26 12:53:41 +000013357 if (STRCMP(arg, "$") == 0)
13358 twin = lastwin;
13359 else if (STRCMP(arg, "#") == 0)
13360 {
13361 twin = prevwin;
13362 if (prevwin == NULL)
13363 nr = 0;
13364 }
13365 else
13366 {
13367 EMSG2(_(e_invexpr2), arg);
13368 nr = 0;
13369 }
13370 }
13371
13372 if (nr > 0)
13373 for (wp = firstwin; wp != twin; wp = wp->w_next)
13374 ++nr;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013375#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013376 rettv->vval.v_number = nr;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013377}
13378
13379/*
13380 * "winrestcmd()" function
13381 */
13382/* ARGSUSED */
13383 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013384f_winrestcmd(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000013385 typval_T *argvars;
13386 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013387{
13388#ifdef FEAT_WINDOWS
13389 win_T *wp;
13390 int winnr = 1;
13391 garray_T ga;
13392 char_u buf[50];
13393
13394 ga_init2(&ga, (int)sizeof(char), 70);
13395 for (wp = firstwin; wp != NULL; wp = wp->w_next)
13396 {
13397 sprintf((char *)buf, "%dresize %d|", winnr, wp->w_height);
13398 ga_concat(&ga, buf);
13399# ifdef FEAT_VERTSPLIT
13400 sprintf((char *)buf, "vert %dresize %d|", winnr, wp->w_width);
13401 ga_concat(&ga, buf);
13402# endif
13403 ++winnr;
13404 }
Bram Moolenaar269ec652004-07-29 08:43:53 +000013405 ga_append(&ga, NUL);
Bram Moolenaar071d4272004-06-13 20:20:40 +000013406
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013407 rettv->vval.v_string = ga.ga_data;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013408#else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013409 rettv->vval.v_string = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013410#endif
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013411 rettv->v_type = VAR_STRING;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013412}
13413
13414/*
13415 * "winwidth(nr)" function
13416 */
13417 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013418f_winwidth(argvars, rettv)
Bram Moolenaar33570922005-01-25 22:26:29 +000013419 typval_T *argvars;
13420 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013421{
13422 win_T *wp;
13423
13424 wp = find_win_by_nr(&argvars[0]);
13425 if (wp == NULL)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013426 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013427 else
13428#ifdef FEAT_VERTSPLIT
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013429 rettv->vval.v_number = wp->w_width;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013430#else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013431 rettv->vval.v_number = Columns;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013432#endif
13433}
13434
13435 static win_T *
13436find_win_by_nr(vp)
Bram Moolenaar33570922005-01-25 22:26:29 +000013437 typval_T *vp;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013438{
13439#ifdef FEAT_WINDOWS
13440 win_T *wp;
13441#endif
13442 int nr;
13443
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013444 nr = get_tv_number(vp);
Bram Moolenaar071d4272004-06-13 20:20:40 +000013445
13446#ifdef FEAT_WINDOWS
13447 if (nr == 0)
13448 return curwin;
13449
13450 for (wp = firstwin; wp != NULL; wp = wp->w_next)
13451 if (--nr <= 0)
13452 break;
13453 return wp;
13454#else
13455 if (nr == 0 || nr == 1)
13456 return curwin;
13457 return NULL;
13458#endif
13459}
13460
13461/*
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000013462 * "writefile()" function
13463 */
13464 static void
13465f_writefile(argvars, rettv)
13466 typval_T *argvars;
13467 typval_T *rettv;
13468{
13469 int binary = FALSE;
13470 char_u *fname;
13471 FILE *fd;
13472 listitem_T *li;
13473 char_u *s;
13474 int ret = 0;
13475 int c;
13476
13477 if (argvars[0].v_type != VAR_LIST)
13478 {
13479 EMSG2(_(e_listarg), "writefile()");
13480 return;
13481 }
13482 if (argvars[0].vval.v_list == NULL)
13483 return;
13484
13485 if (argvars[2].v_type != VAR_UNKNOWN
13486 && STRCMP(get_tv_string(&argvars[2]), "b") == 0)
13487 binary = TRUE;
13488
13489 /* Always open the file in binary mode, library functions have a mind of
13490 * their own about CR-LF conversion. */
13491 fname = get_tv_string(&argvars[1]);
13492 if (*fname == NUL || (fd = mch_fopen((char *)fname, WRITEBIN)) == NULL)
13493 {
13494 EMSG2(_(e_notcreate), *fname == NUL ? (char_u *)_("<empty>") : fname);
13495 ret = -1;
13496 }
13497 else
13498 {
13499 for (li = argvars[0].vval.v_list->lv_first; li != NULL;
13500 li = li->li_next)
13501 {
13502 for (s = get_tv_string(&li->li_tv); *s != NUL; ++s)
13503 {
13504 if (*s == '\n')
13505 c = putc(NUL, fd);
13506 else
13507 c = putc(*s, fd);
13508 if (c == EOF)
13509 {
13510 ret = -1;
13511 break;
13512 }
13513 }
13514 if (!binary || li->li_next != NULL)
13515 if (putc('\n', fd) == EOF)
13516 {
13517 ret = -1;
13518 break;
13519 }
13520 if (ret < 0)
13521 {
13522 EMSG(_(e_write));
13523 break;
13524 }
13525 }
13526 fclose(fd);
13527 }
13528
13529 rettv->vval.v_number = ret;
13530}
13531
13532/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000013533 * Translate a String variable into a position.
13534 */
13535 static pos_T *
13536var2fpos(varp, lnum)
Bram Moolenaar33570922005-01-25 22:26:29 +000013537 typval_T *varp;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013538 int lnum; /* TRUE when $ is last line */
13539{
13540 char_u *name;
13541 static pos_T pos;
13542 pos_T *pp;
13543
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013544 name = get_tv_string(varp);
Bram Moolenaar071d4272004-06-13 20:20:40 +000013545 if (name[0] == '.') /* cursor */
13546 return &curwin->w_cursor;
13547 if (name[0] == '\'') /* mark */
13548 {
13549 pp = getmark(name[1], FALSE);
13550 if (pp == NULL || pp == (pos_T *)-1 || pp->lnum <= 0)
13551 return NULL;
13552 return pp;
13553 }
13554 if (name[0] == '$') /* last column or line */
13555 {
13556 if (lnum)
13557 {
13558 pos.lnum = curbuf->b_ml.ml_line_count;
13559 pos.col = 0;
13560 }
13561 else
13562 {
13563 pos.lnum = curwin->w_cursor.lnum;
13564 pos.col = (colnr_T)STRLEN(ml_get_curline());
13565 }
13566 return &pos;
13567 }
13568 return NULL;
13569}
13570
13571/*
13572 * Get the length of an environment variable name.
13573 * Advance "arg" to the first character after the name.
13574 * Return 0 for error.
13575 */
13576 static int
13577get_env_len(arg)
13578 char_u **arg;
13579{
13580 char_u *p;
13581 int len;
13582
13583 for (p = *arg; vim_isIDc(*p); ++p)
13584 ;
13585 if (p == *arg) /* no name found */
13586 return 0;
13587
13588 len = (int)(p - *arg);
13589 *arg = p;
13590 return len;
13591}
13592
13593/*
13594 * Get the length of the name of a function or internal variable.
13595 * "arg" is advanced to the first non-white character after the name.
13596 * Return 0 if something is wrong.
13597 */
13598 static int
13599get_id_len(arg)
13600 char_u **arg;
13601{
13602 char_u *p;
13603 int len;
13604
13605 /* Find the end of the name. */
13606 for (p = *arg; eval_isnamec(*p); ++p)
13607 ;
13608 if (p == *arg) /* no name found */
13609 return 0;
13610
13611 len = (int)(p - *arg);
13612 *arg = skipwhite(p);
13613
13614 return len;
13615}
13616
13617/*
Bram Moolenaara7043832005-01-21 11:56:39 +000013618 * Get the length of the name of a variable or function.
13619 * Only the name is recognized, does not handle ".key" or "[idx]".
Bram Moolenaar071d4272004-06-13 20:20:40 +000013620 * "arg" is advanced to the first non-white character after the name.
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000013621 * Return -1 if curly braces expansion failed.
13622 * Return 0 if something else is wrong.
Bram Moolenaar071d4272004-06-13 20:20:40 +000013623 * If the name contains 'magic' {}'s, expand them and return the
13624 * expanded name in an allocated string via 'alias' - caller must free.
13625 */
13626 static int
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000013627get_name_len(arg, alias, evaluate, verbose)
Bram Moolenaar071d4272004-06-13 20:20:40 +000013628 char_u **arg;
13629 char_u **alias;
13630 int evaluate;
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000013631 int verbose;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013632{
13633 int len;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013634 char_u *p;
13635 char_u *expr_start;
13636 char_u *expr_end;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013637
13638 *alias = NULL; /* default to no alias */
13639
13640 if ((*arg)[0] == K_SPECIAL && (*arg)[1] == KS_EXTRA
13641 && (*arg)[2] == (int)KE_SNR)
13642 {
13643 /* hard coded <SNR>, already translated */
13644 *arg += 3;
13645 return get_id_len(arg) + 3;
13646 }
13647 len = eval_fname_script(*arg);
13648 if (len > 0)
13649 {
13650 /* literal "<SID>", "s:" or "<SNR>" */
13651 *arg += len;
13652 }
13653
Bram Moolenaar071d4272004-06-13 20:20:40 +000013654 /*
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013655 * Find the end of the name; check for {} construction.
Bram Moolenaar071d4272004-06-13 20:20:40 +000013656 */
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013657 p = find_name_end(*arg, &expr_start, &expr_end, FALSE);
Bram Moolenaar071d4272004-06-13 20:20:40 +000013658 if (expr_start != NULL)
13659 {
13660 char_u *temp_string;
13661
13662 if (!evaluate)
13663 {
13664 len += (int)(p - *arg);
13665 *arg = skipwhite(p);
13666 return len;
13667 }
13668
13669 /*
13670 * Include any <SID> etc in the expanded string:
13671 * Thus the -len here.
13672 */
13673 temp_string = make_expanded_name(*arg - len, expr_start, expr_end, p);
13674 if (temp_string == NULL)
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000013675 return -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013676 *alias = temp_string;
13677 *arg = skipwhite(p);
13678 return (int)STRLEN(temp_string);
13679 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000013680
13681 len += get_id_len(arg);
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000013682 if (len == 0 && verbose)
Bram Moolenaar071d4272004-06-13 20:20:40 +000013683 EMSG2(_(e_invexpr2), *arg);
13684
13685 return len;
13686}
13687
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013688/*
13689 * Find the end of a variable or function name, taking care of magic braces.
13690 * If "expr_start" is not NULL then "expr_start" and "expr_end" are set to the
13691 * start and end of the first magic braces item.
13692 * Return a pointer to just after the name. Equal to "arg" if there is no
13693 * valid name.
13694 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000013695 static char_u *
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013696find_name_end(arg, expr_start, expr_end, incl_br)
Bram Moolenaar071d4272004-06-13 20:20:40 +000013697 char_u *arg;
13698 char_u **expr_start;
13699 char_u **expr_end;
Bram Moolenaar8c711452005-01-14 21:53:12 +000013700 int incl_br; /* Include [] indexes and .name */
Bram Moolenaar071d4272004-06-13 20:20:40 +000013701{
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013702 int mb_nest = 0;
13703 int br_nest = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013704 char_u *p;
13705
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013706 if (expr_start != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000013707 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013708 *expr_start = NULL;
13709 *expr_end = NULL;
13710 }
13711
13712 for (p = arg; *p != NUL
13713 && (eval_isnamec(*p)
Bram Moolenaare9a41262005-01-15 22:18:47 +000013714 || *p == '{'
Bram Moolenaar8c711452005-01-14 21:53:12 +000013715 || (incl_br && (*p == '[' || *p == '.'))
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013716 || mb_nest != 0
13717 || br_nest != 0); ++p)
13718 {
13719 if (mb_nest == 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +000013720 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013721 if (*p == '[')
13722 ++br_nest;
13723 else if (*p == ']')
13724 --br_nest;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013725 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013726 if (br_nest == 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +000013727 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000013728 if (*p == '{')
13729 {
13730 mb_nest++;
13731 if (expr_start != NULL && *expr_start == NULL)
13732 *expr_start = p;
13733 }
13734 else if (*p == '}')
13735 {
13736 mb_nest--;
13737 if (expr_start != NULL && mb_nest == 0 && *expr_end == NULL)
13738 *expr_end = p;
13739 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000013740 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000013741 }
13742
13743 return p;
13744}
13745
13746/*
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000013747 * Expands out the 'magic' {}'s in a variable/function name.
13748 * Note that this can call itself recursively, to deal with
13749 * constructs like foo{bar}{baz}{bam}
13750 * The four pointer arguments point to "foo{expre}ss{ion}bar"
13751 * "in_start" ^
13752 * "expr_start" ^
13753 * "expr_end" ^
13754 * "in_end" ^
13755 *
13756 * Returns a new allocated string, which the caller must free.
13757 * Returns NULL for failure.
13758 */
13759 static char_u *
13760make_expanded_name(in_start, expr_start, expr_end, in_end)
13761 char_u *in_start;
13762 char_u *expr_start;
13763 char_u *expr_end;
13764 char_u *in_end;
13765{
13766 char_u c1;
13767 char_u *retval = NULL;
13768 char_u *temp_result;
13769 char_u *nextcmd = NULL;
13770
13771 if (expr_end == NULL || in_end == NULL)
13772 return NULL;
13773 *expr_start = NUL;
13774 *expr_end = NUL;
13775 c1 = *in_end;
13776 *in_end = NUL;
13777
13778 temp_result = eval_to_string(expr_start + 1, &nextcmd);
13779 if (temp_result != NULL && nextcmd == NULL)
13780 {
13781 retval = alloc((unsigned)(STRLEN(temp_result) + (expr_start - in_start)
13782 + (in_end - expr_end) + 1));
13783 if (retval != NULL)
13784 {
13785 STRCPY(retval, in_start);
13786 STRCAT(retval, temp_result);
13787 STRCAT(retval, expr_end + 1);
13788 }
13789 }
13790 vim_free(temp_result);
13791
13792 *in_end = c1; /* put char back for error messages */
13793 *expr_start = '{';
13794 *expr_end = '}';
13795
13796 if (retval != NULL)
13797 {
13798 temp_result = find_name_end(retval, &expr_start, &expr_end, FALSE);
13799 if (expr_start != NULL)
13800 {
13801 /* Further expansion! */
13802 temp_result = make_expanded_name(retval, expr_start,
13803 expr_end, temp_result);
13804 vim_free(retval);
13805 retval = temp_result;
13806 }
13807 }
13808
13809 return retval;
13810}
13811
13812/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000013813 * Return TRUE if character "c" can be used in a variable or function name.
Bram Moolenaare9a41262005-01-15 22:18:47 +000013814 * Does not include '{' or '}' for magic braces.
Bram Moolenaar071d4272004-06-13 20:20:40 +000013815 */
13816 static int
13817eval_isnamec(c)
13818 int c;
13819{
Bram Moolenaare9a41262005-01-15 22:18:47 +000013820 return (ASCII_ISALNUM(c) || c == '_' || c == ':');
Bram Moolenaar071d4272004-06-13 20:20:40 +000013821}
13822
13823/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000013824 * Set number v: variable to "val".
13825 */
13826 void
13827set_vim_var_nr(idx, val)
13828 int idx;
13829 long val;
13830{
Bram Moolenaare9a41262005-01-15 22:18:47 +000013831 vimvars[idx].vv_nr = val;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013832}
13833
13834/*
13835 * Get number v: variable value;
13836 */
13837 long
13838get_vim_var_nr(idx)
13839 int idx;
13840{
Bram Moolenaare9a41262005-01-15 22:18:47 +000013841 return vimvars[idx].vv_nr;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013842}
13843
13844/*
13845 * Set v:count, v:count1 and v:prevcount.
13846 */
13847 void
13848set_vcount(count, count1)
13849 long count;
13850 long count1;
13851{
Bram Moolenaare9a41262005-01-15 22:18:47 +000013852 vimvars[VV_PREVCOUNT].vv_nr = vimvars[VV_COUNT].vv_nr;
13853 vimvars[VV_COUNT].vv_nr = count;
13854 vimvars[VV_COUNT1].vv_nr = count1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013855}
13856
13857/*
13858 * Set string v: variable to a copy of "val".
13859 */
13860 void
13861set_vim_var_string(idx, val, len)
13862 int idx;
13863 char_u *val;
13864 int len; /* length of "val" to use or -1 (whole string) */
13865{
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000013866 /* Need to do this (at least) once, since we can't initialize a union.
13867 * Will always be invoked when "v:progname" is set. */
13868 vimvars[VV_VERSION].vv_nr = VIM_VERSION_100;
13869
Bram Moolenaare9a41262005-01-15 22:18:47 +000013870 vim_free(vimvars[idx].vv_str);
Bram Moolenaar071d4272004-06-13 20:20:40 +000013871 if (val == NULL)
Bram Moolenaare9a41262005-01-15 22:18:47 +000013872 vimvars[idx].vv_str = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013873 else if (len == -1)
Bram Moolenaare9a41262005-01-15 22:18:47 +000013874 vimvars[idx].vv_str = vim_strsave(val);
Bram Moolenaar071d4272004-06-13 20:20:40 +000013875 else
Bram Moolenaare9a41262005-01-15 22:18:47 +000013876 vimvars[idx].vv_str = vim_strnsave(val, len);
Bram Moolenaar071d4272004-06-13 20:20:40 +000013877}
13878
13879/*
13880 * Set v:register if needed.
13881 */
13882 void
13883set_reg_var(c)
13884 int c;
13885{
13886 char_u regname;
13887
13888 if (c == 0 || c == ' ')
13889 regname = '"';
13890 else
13891 regname = c;
13892 /* Avoid free/alloc when the value is already right. */
Bram Moolenaare9a41262005-01-15 22:18:47 +000013893 if (vimvars[VV_REG].vv_str == NULL || vimvars[VV_REG].vv_str[0] != c)
Bram Moolenaar071d4272004-06-13 20:20:40 +000013894 set_vim_var_string(VV_REG, &regname, 1);
13895}
13896
13897/*
13898 * Get or set v:exception. If "oldval" == NULL, return the current value.
13899 * Otherwise, restore the value to "oldval" and return NULL.
13900 * Must always be called in pairs to save and restore v:exception! Does not
13901 * take care of memory allocations.
13902 */
13903 char_u *
13904v_exception(oldval)
13905 char_u *oldval;
13906{
13907 if (oldval == NULL)
Bram Moolenaare9a41262005-01-15 22:18:47 +000013908 return vimvars[VV_EXCEPTION].vv_str;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013909
Bram Moolenaare9a41262005-01-15 22:18:47 +000013910 vimvars[VV_EXCEPTION].vv_str = oldval;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013911 return NULL;
13912}
13913
13914/*
13915 * Get or set v:throwpoint. If "oldval" == NULL, return the current value.
13916 * Otherwise, restore the value to "oldval" and return NULL.
13917 * Must always be called in pairs to save and restore v:throwpoint! Does not
13918 * take care of memory allocations.
13919 */
13920 char_u *
13921v_throwpoint(oldval)
13922 char_u *oldval;
13923{
13924 if (oldval == NULL)
Bram Moolenaare9a41262005-01-15 22:18:47 +000013925 return vimvars[VV_THROWPOINT].vv_str;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013926
Bram Moolenaare9a41262005-01-15 22:18:47 +000013927 vimvars[VV_THROWPOINT].vv_str = oldval;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013928 return NULL;
13929}
13930
13931#if defined(FEAT_AUTOCMD) || defined(PROTO)
13932/*
13933 * Set v:cmdarg.
13934 * If "eap" != NULL, use "eap" to generate the value and return the old value.
13935 * If "oldarg" != NULL, restore the value to "oldarg" and return NULL.
13936 * Must always be called in pairs!
13937 */
13938 char_u *
13939set_cmdarg(eap, oldarg)
13940 exarg_T *eap;
13941 char_u *oldarg;
13942{
13943 char_u *oldval;
13944 char_u *newval;
13945 unsigned len;
13946
Bram Moolenaare9a41262005-01-15 22:18:47 +000013947 oldval = vimvars[VV_CMDARG].vv_str;
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +000013948 if (eap == NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000013949 {
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +000013950 vim_free(oldval);
Bram Moolenaare9a41262005-01-15 22:18:47 +000013951 vimvars[VV_CMDARG].vv_str = oldarg;
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +000013952 return NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013953 }
13954
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +000013955 if (eap->force_bin == FORCE_BIN)
13956 len = 6;
13957 else if (eap->force_bin == FORCE_NOBIN)
13958 len = 8;
13959 else
13960 len = 0;
13961 if (eap->force_ff != 0)
13962 len += (unsigned)STRLEN(eap->cmd + eap->force_ff) + 6;
13963# ifdef FEAT_MBYTE
13964 if (eap->force_enc != 0)
13965 len += (unsigned)STRLEN(eap->cmd + eap->force_enc) + 7;
13966# endif
13967
13968 newval = alloc(len + 1);
13969 if (newval == NULL)
13970 return NULL;
13971
13972 if (eap->force_bin == FORCE_BIN)
13973 sprintf((char *)newval, " ++bin");
13974 else if (eap->force_bin == FORCE_NOBIN)
13975 sprintf((char *)newval, " ++nobin");
13976 else
13977 *newval = NUL;
13978 if (eap->force_ff != 0)
13979 sprintf((char *)newval + STRLEN(newval), " ++ff=%s",
13980 eap->cmd + eap->force_ff);
13981# ifdef FEAT_MBYTE
13982 if (eap->force_enc != 0)
13983 sprintf((char *)newval + STRLEN(newval), " ++enc=%s",
13984 eap->cmd + eap->force_enc);
13985# endif
Bram Moolenaare9a41262005-01-15 22:18:47 +000013986 vimvars[VV_CMDARG].vv_str = newval;
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +000013987 return oldval;
Bram Moolenaar071d4272004-06-13 20:20:40 +000013988}
13989#endif
13990
13991/*
13992 * Get the value of internal variable "name".
13993 * Return OK or FAIL.
13994 */
13995 static int
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000013996get_var_tv(name, len, rettv, verbose)
Bram Moolenaar071d4272004-06-13 20:20:40 +000013997 char_u *name;
13998 int len; /* length of "name" */
Bram Moolenaar33570922005-01-25 22:26:29 +000013999 typval_T *rettv; /* NULL when only checking existence */
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000014000 int verbose; /* may give error message */
Bram Moolenaar071d4272004-06-13 20:20:40 +000014001{
14002 int ret = OK;
Bram Moolenaar33570922005-01-25 22:26:29 +000014003 typval_T *tv = NULL;
14004 typval_T atv;
14005 dictitem_T *v;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014006 int cc;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014007
14008 /* truncate the name, so that we can use strcmp() */
14009 cc = name[len];
14010 name[len] = NUL;
14011
14012 /*
14013 * Check for "b:changedtick".
14014 */
14015 if (STRCMP(name, "b:changedtick") == 0)
14016 {
Bram Moolenaare9a41262005-01-15 22:18:47 +000014017 atv.v_type = VAR_NUMBER;
14018 atv.vval.v_number = curbuf->b_changedtick;
14019 tv = &atv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014020 }
14021
14022 /*
Bram Moolenaar071d4272004-06-13 20:20:40 +000014023 * Check for user-defined variables.
14024 */
14025 else
14026 {
Bram Moolenaara7043832005-01-21 11:56:39 +000014027 v = find_var(name, NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +000014028 if (v != NULL)
Bram Moolenaar33570922005-01-25 22:26:29 +000014029 tv = &v->di_tv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014030 }
14031
Bram Moolenaare9a41262005-01-15 22:18:47 +000014032 if (tv == NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000014033 {
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000014034 if (rettv != NULL && verbose)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014035 EMSG2(_(e_undefvar), name);
Bram Moolenaar071d4272004-06-13 20:20:40 +000014036 ret = FAIL;
14037 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014038 else if (rettv != NULL)
Bram Moolenaare9a41262005-01-15 22:18:47 +000014039 copy_tv(tv, rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000014040
14041 name[len] = cc;
14042
14043 return ret;
14044}
14045
14046/*
Bram Moolenaar2a8d1f82005-02-05 21:43:56 +000014047 * Handle expr[expr], expr[expr:expr] subscript and .name lookup.
14048 * Also handle function call with Funcref variable: func(expr)
14049 * Can all be combined: dict.func(expr)[idx]['func'](expr)
14050 */
14051 static int
14052handle_subscript(arg, rettv, evaluate, verbose)
14053 char_u **arg;
14054 typval_T *rettv;
14055 int evaluate; /* do more than finding the end */
14056 int verbose; /* give error messages */
14057{
14058 int ret = OK;
14059 dict_T *selfdict = NULL;
14060 char_u *s;
14061 int len;
14062
14063 while (ret == OK
14064 && (**arg == '['
14065 || (**arg == '.' && rettv->v_type == VAR_DICT)
14066 || (**arg == '(' && rettv->v_type == VAR_FUNC))
14067 && !vim_iswhite(*(*arg - 1)))
14068 {
14069 if (**arg == '(')
14070 {
14071 s = rettv->vval.v_string;
14072
14073 /* Invoke the function. Recursive! */
14074 ret = get_func_tv(s, STRLEN(s), rettv, arg,
14075 curwin->w_cursor.lnum, curwin->w_cursor.lnum,
14076 &len, evaluate, selfdict);
14077
14078 /* Stop the expression evaluation when immediately aborting on
14079 * error, or when an interrupt occurred or an exception was thrown
14080 * but not caught. */
14081 if (aborting())
14082 {
14083 if (ret == OK)
14084 clear_tv(rettv);
14085 ret = FAIL;
14086 }
14087 dict_unref(selfdict);
14088 selfdict = NULL;
14089 }
14090 else /* **arg == '[' || **arg == '.' */
14091 {
14092 dict_unref(selfdict);
14093 if (rettv->v_type == VAR_DICT)
14094 {
14095 selfdict = rettv->vval.v_dict;
14096 if (selfdict != NULL)
14097 ++selfdict->dv_refcount;
14098 }
14099 else
14100 selfdict = NULL;
14101 if (eval_index(arg, rettv, evaluate, verbose) == FAIL)
14102 {
14103 clear_tv(rettv);
14104 ret = FAIL;
14105 }
14106 }
14107 }
14108 dict_unref(selfdict);
14109 return ret;
14110}
14111
14112/*
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014113 * Allocate memory for a variable type-value, and make it emtpy (0 or NULL
14114 * value).
14115 */
Bram Moolenaar33570922005-01-25 22:26:29 +000014116 static typval_T *
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014117alloc_tv()
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014118{
Bram Moolenaar33570922005-01-25 22:26:29 +000014119 return (typval_T *)alloc_clear((unsigned)sizeof(typval_T));
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014120}
14121
14122/*
14123 * Allocate memory for a variable type-value, and assign a string to it.
Bram Moolenaar071d4272004-06-13 20:20:40 +000014124 * The string "s" must have been allocated, it is consumed.
14125 * Return NULL for out of memory, the variable otherwise.
14126 */
Bram Moolenaar33570922005-01-25 22:26:29 +000014127 static typval_T *
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014128alloc_string_tv(s)
Bram Moolenaar071d4272004-06-13 20:20:40 +000014129 char_u *s;
14130{
Bram Moolenaar33570922005-01-25 22:26:29 +000014131 typval_T *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014132
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014133 rettv = alloc_tv();
14134 if (rettv != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000014135 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014136 rettv->v_type = VAR_STRING;
14137 rettv->vval.v_string = s;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014138 }
14139 else
14140 vim_free(s);
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014141 return rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014142}
14143
14144/*
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014145 * Free the memory for a variable type-value.
Bram Moolenaar071d4272004-06-13 20:20:40 +000014146 */
14147 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014148free_tv(varp)
Bram Moolenaar33570922005-01-25 22:26:29 +000014149 typval_T *varp;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014150{
14151 if (varp != NULL)
14152 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014153 switch (varp->v_type)
14154 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014155 case VAR_FUNC:
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000014156 func_unref(varp->vval.v_string);
14157 /*FALLTHROUGH*/
14158 case VAR_STRING:
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014159 vim_free(varp->vval.v_string);
14160 break;
14161 case VAR_LIST:
14162 list_unref(varp->vval.v_list);
14163 break;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000014164 case VAR_DICT:
14165 dict_unref(varp->vval.v_dict);
14166 break;
Bram Moolenaar758711c2005-02-02 23:11:38 +000014167 case VAR_NUMBER:
14168 case VAR_UNKNOWN:
14169 break;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014170 default:
Bram Moolenaar758711c2005-02-02 23:11:38 +000014171 EMSG2(_(e_intern2), "free_tv()");
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014172 break;
14173 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000014174 vim_free(varp);
14175 }
14176}
14177
14178/*
14179 * Free the memory for a variable value and set the value to NULL or 0.
14180 */
14181 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014182clear_tv(varp)
Bram Moolenaar33570922005-01-25 22:26:29 +000014183 typval_T *varp;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014184{
14185 if (varp != NULL)
14186 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014187 switch (varp->v_type)
Bram Moolenaar071d4272004-06-13 20:20:40 +000014188 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014189 case VAR_FUNC:
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000014190 func_unref(varp->vval.v_string);
14191 /*FALLTHROUGH*/
14192 case VAR_STRING:
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014193 vim_free(varp->vval.v_string);
14194 varp->vval.v_string = NULL;
14195 break;
14196 case VAR_LIST:
14197 list_unref(varp->vval.v_list);
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000014198 varp->vval.v_list = NULL;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014199 break;
Bram Moolenaar8c711452005-01-14 21:53:12 +000014200 case VAR_DICT:
14201 dict_unref(varp->vval.v_dict);
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000014202 varp->vval.v_dict = NULL;
Bram Moolenaar8c711452005-01-14 21:53:12 +000014203 break;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014204 case VAR_NUMBER:
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014205 varp->vval.v_number = 0;
14206 break;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014207 case VAR_UNKNOWN:
14208 break;
14209 default:
14210 EMSG2(_(e_intern2), "clear_tv()");
Bram Moolenaar071d4272004-06-13 20:20:40 +000014211 }
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000014212 varp->v_lock = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014213 }
14214}
14215
14216/*
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014217 * Set the value of a variable to NULL without freeing items.
14218 */
14219 static void
14220init_tv(varp)
Bram Moolenaar33570922005-01-25 22:26:29 +000014221 typval_T *varp;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014222{
14223 if (varp != NULL)
Bram Moolenaar33570922005-01-25 22:26:29 +000014224 vim_memset(varp, 0, sizeof(typval_T));
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014225}
14226
14227/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000014228 * Get the number value of a variable.
14229 * If it is a String variable, uses vim_str2nr().
14230 */
14231 static long
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014232get_tv_number(varp)
Bram Moolenaar33570922005-01-25 22:26:29 +000014233 typval_T *varp;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014234{
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014235 long n = 0L;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014236
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014237 switch (varp->v_type)
Bram Moolenaar071d4272004-06-13 20:20:40 +000014238 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014239 case VAR_NUMBER:
14240 n = (long)(varp->vval.v_number);
14241 break;
14242 case VAR_FUNC:
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000014243 EMSG(_("E703: Using a Funcref as a number"));
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014244 break;
14245 case VAR_STRING:
14246 if (varp->vval.v_string != NULL)
14247 vim_str2nr(varp->vval.v_string, NULL, NULL,
14248 TRUE, TRUE, &n, NULL);
14249 break;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000014250 case VAR_LIST:
Bram Moolenaar758711c2005-02-02 23:11:38 +000014251 EMSG(_("E745: Using a List as a number"));
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000014252 break;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000014253 case VAR_DICT:
14254 EMSG(_("E728: Using a Dictionary as a number"));
14255 break;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014256 default:
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000014257 EMSG2(_(e_intern2), "get_tv_number()");
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014258 break;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014259 }
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014260 return n;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014261}
14262
14263/*
14264 * Get the lnum from the first argument. Also accepts ".", "$", etc.
14265 */
14266 static linenr_T
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014267get_tv_lnum(argvars)
Bram Moolenaar33570922005-01-25 22:26:29 +000014268 typval_T *argvars;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014269{
Bram Moolenaar33570922005-01-25 22:26:29 +000014270 typval_T rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014271 linenr_T lnum;
14272
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014273 lnum = get_tv_number(&argvars[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +000014274 if (lnum == 0) /* no valid number, try using line() */
14275 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014276 rettv.v_type = VAR_NUMBER;
14277 f_line(argvars, &rettv);
14278 lnum = rettv.vval.v_number;
14279 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000014280 }
14281 return lnum;
14282}
14283
14284/*
14285 * Get the string value of a variable.
14286 * If it is a Number variable, the number is converted into a string.
Bram Moolenaara7043832005-01-21 11:56:39 +000014287 * get_tv_string() uses a single, static buffer. YOU CAN ONLY USE IT ONCE!
14288 * get_tv_string_buf() uses a given buffer.
Bram Moolenaar071d4272004-06-13 20:20:40 +000014289 * If the String variable has never been set, return an empty string.
14290 * Never returns NULL;
14291 */
14292 static char_u *
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014293get_tv_string(varp)
Bram Moolenaar33570922005-01-25 22:26:29 +000014294 typval_T *varp;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014295{
14296 static char_u mybuf[NUMBUFLEN];
14297
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014298 return get_tv_string_buf(varp, mybuf);
Bram Moolenaar071d4272004-06-13 20:20:40 +000014299}
14300
14301 static char_u *
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014302get_tv_string_buf(varp, buf)
Bram Moolenaar33570922005-01-25 22:26:29 +000014303 typval_T *varp;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014304 char_u *buf;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014305{
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014306 switch (varp->v_type)
Bram Moolenaar071d4272004-06-13 20:20:40 +000014307 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014308 case VAR_NUMBER:
14309 sprintf((char *)buf, "%ld", (long)varp->vval.v_number);
14310 return buf;
14311 case VAR_FUNC:
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000014312 EMSG(_("E729: using Funcref as a String"));
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014313 break;
14314 case VAR_LIST:
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000014315 EMSG(_("E730: using List as a String"));
Bram Moolenaar8c711452005-01-14 21:53:12 +000014316 break;
14317 case VAR_DICT:
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000014318 EMSG(_("E731: using Dictionary as a String"));
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014319 break;
14320 case VAR_STRING:
14321 if (varp->vval.v_string != NULL)
14322 return varp->vval.v_string;
14323 break;
14324 default:
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014325 EMSG2(_(e_intern2), "get_tv_string_buf()");
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014326 break;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014327 }
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014328 return (char_u *)"";
Bram Moolenaar071d4272004-06-13 20:20:40 +000014329}
14330
14331/*
14332 * Find variable "name" in the list of variables.
14333 * Return a pointer to it if found, NULL if not found.
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014334 * Careful: "a:0" variables don't have a name.
Bram Moolenaara7043832005-01-21 11:56:39 +000014335 * When "htp" is not NULL we are writing to the variable, set "htp" to the
Bram Moolenaar33570922005-01-25 22:26:29 +000014336 * hashtab_T used.
Bram Moolenaar071d4272004-06-13 20:20:40 +000014337 */
Bram Moolenaar33570922005-01-25 22:26:29 +000014338 static dictitem_T *
Bram Moolenaara7043832005-01-21 11:56:39 +000014339find_var(name, htp)
Bram Moolenaar071d4272004-06-13 20:20:40 +000014340 char_u *name;
Bram Moolenaar33570922005-01-25 22:26:29 +000014341 hashtab_T **htp;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014342{
Bram Moolenaar071d4272004-06-13 20:20:40 +000014343 char_u *varname;
Bram Moolenaar33570922005-01-25 22:26:29 +000014344 hashtab_T *ht;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014345
Bram Moolenaara7043832005-01-21 11:56:39 +000014346 ht = find_var_ht(name, &varname);
14347 if (htp != NULL)
14348 *htp = ht;
14349 if (ht == NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000014350 return NULL;
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000014351 return find_var_in_ht(ht, varname, htp != NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +000014352}
14353
14354/*
Bram Moolenaar33570922005-01-25 22:26:29 +000014355 * Find variable "varname" in hashtab "ht".
Bram Moolenaara7043832005-01-21 11:56:39 +000014356 * Returns NULL if not found.
Bram Moolenaar071d4272004-06-13 20:20:40 +000014357 */
Bram Moolenaar33570922005-01-25 22:26:29 +000014358 static dictitem_T *
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000014359find_var_in_ht(ht, varname, writing)
Bram Moolenaar33570922005-01-25 22:26:29 +000014360 hashtab_T *ht;
Bram Moolenaara7043832005-01-21 11:56:39 +000014361 char_u *varname;
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000014362 int writing;
Bram Moolenaara7043832005-01-21 11:56:39 +000014363{
Bram Moolenaar33570922005-01-25 22:26:29 +000014364 hashitem_T *hi;
14365
14366 if (*varname == NUL)
14367 {
14368 /* Must be something like "s:", otherwise "ht" would be NULL. */
14369 switch (varname[-2])
14370 {
14371 case 's': return &SCRIPT_SV(current_SID).sv_var;
14372 case 'g': return &globvars_var;
14373 case 'v': return &vimvars_var;
14374 case 'b': return &curbuf->b_bufvar;
14375 case 'w': return &curwin->w_winvar;
14376 case 'l': return &current_funccal->l_vars_var;
14377 case 'a': return &current_funccal->l_avars_var;
14378 }
14379 return NULL;
14380 }
Bram Moolenaara7043832005-01-21 11:56:39 +000014381
14382 hi = hash_find(ht, varname);
14383 if (HASHITEM_EMPTY(hi))
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000014384 {
14385 /* For global variables we may try auto-loading the script. If it
14386 * worked find the variable again. */
14387 if (ht == &globvarht && !writing
14388 && script_autoload(varname) && !aborting())
14389 hi = hash_find(ht, varname);
14390 if (HASHITEM_EMPTY(hi))
14391 return NULL;
14392 }
Bram Moolenaar33570922005-01-25 22:26:29 +000014393 return HI2DI(hi);
Bram Moolenaara7043832005-01-21 11:56:39 +000014394}
14395
14396/*
Bram Moolenaar33570922005-01-25 22:26:29 +000014397 * Find the hashtab used for a variable name.
Bram Moolenaara7043832005-01-21 11:56:39 +000014398 * Set "varname" to the start of name without ':'.
14399 */
Bram Moolenaar33570922005-01-25 22:26:29 +000014400 static hashtab_T *
Bram Moolenaara7043832005-01-21 11:56:39 +000014401find_var_ht(name, varname)
Bram Moolenaar071d4272004-06-13 20:20:40 +000014402 char_u *name;
14403 char_u **varname;
14404{
14405 if (name[1] != ':')
14406 {
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000014407 /* The name must not start with a colon. */
14408 if (name[0] == ':')
Bram Moolenaar071d4272004-06-13 20:20:40 +000014409 return NULL;
14410 *varname = name;
Bram Moolenaar532c7802005-01-27 14:44:31 +000014411
14412 /* "version" is "v:version" in all scopes */
14413 if (!HASHITEM_EMPTY(hash_find(&compat_hashtab, name)))
14414 return &compat_hashtab;
14415
Bram Moolenaar071d4272004-06-13 20:20:40 +000014416 if (current_funccal == NULL)
Bram Moolenaar33570922005-01-25 22:26:29 +000014417 return &globvarht; /* global variable */
14418 return &current_funccal->l_vars.dv_hashtab; /* l: variable */
Bram Moolenaar071d4272004-06-13 20:20:40 +000014419 }
14420 *varname = name + 2;
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000014421 if (*name == 'g') /* global variable */
14422 return &globvarht;
14423 /* There must be no ':' in the rest of the name, unless g: is used */
14424 if (vim_strchr(name + 2, ':') != NULL)
14425 return NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014426 if (*name == 'b') /* buffer variable */
Bram Moolenaar33570922005-01-25 22:26:29 +000014427 return &curbuf->b_vars.dv_hashtab;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014428 if (*name == 'w') /* window variable */
Bram Moolenaar33570922005-01-25 22:26:29 +000014429 return &curwin->w_vars.dv_hashtab;
Bram Moolenaar33570922005-01-25 22:26:29 +000014430 if (*name == 'v') /* v: variable */
14431 return &vimvarht;
14432 if (*name == 'a' && current_funccal != NULL) /* function argument */
14433 return &current_funccal->l_avars.dv_hashtab;
14434 if (*name == 'l' && current_funccal != NULL) /* local function variable */
14435 return &current_funccal->l_vars.dv_hashtab;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014436 if (*name == 's' /* script variable */
14437 && current_SID > 0 && current_SID <= ga_scripts.ga_len)
14438 return &SCRIPT_VARS(current_SID);
14439 return NULL;
14440}
14441
14442/*
14443 * Get the string value of a (global/local) variable.
14444 * Returns NULL when it doesn't exist.
14445 */
14446 char_u *
14447get_var_value(name)
14448 char_u *name;
14449{
Bram Moolenaar33570922005-01-25 22:26:29 +000014450 dictitem_T *v;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014451
Bram Moolenaara7043832005-01-21 11:56:39 +000014452 v = find_var(name, NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +000014453 if (v == NULL)
14454 return NULL;
Bram Moolenaar33570922005-01-25 22:26:29 +000014455 return get_tv_string(&v->di_tv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000014456}
14457
14458/*
Bram Moolenaar33570922005-01-25 22:26:29 +000014459 * Allocate a new hashtab for a sourced script. It will be used while
Bram Moolenaar071d4272004-06-13 20:20:40 +000014460 * sourcing this script and when executing functions defined in the script.
14461 */
14462 void
14463new_script_vars(id)
14464 scid_T id;
14465{
Bram Moolenaara7043832005-01-21 11:56:39 +000014466 int i;
Bram Moolenaar33570922005-01-25 22:26:29 +000014467 hashtab_T *ht;
14468 scriptvar_T *sv;
Bram Moolenaara7043832005-01-21 11:56:39 +000014469
Bram Moolenaar071d4272004-06-13 20:20:40 +000014470 if (ga_grow(&ga_scripts, (int)(id - ga_scripts.ga_len)) == OK)
14471 {
Bram Moolenaara7043832005-01-21 11:56:39 +000014472 /* Re-allocating ga_data means that an ht_array pointing to
14473 * ht_smallarray becomes invalid. We can recognize this: ht_mask is
Bram Moolenaar33570922005-01-25 22:26:29 +000014474 * at its init value. Also reset "v_dict", it's always the same. */
Bram Moolenaara7043832005-01-21 11:56:39 +000014475 for (i = 1; i <= ga_scripts.ga_len; ++i)
14476 {
14477 ht = &SCRIPT_VARS(i);
14478 if (ht->ht_mask == HT_INIT_SIZE - 1)
14479 ht->ht_array = ht->ht_smallarray;
Bram Moolenaar33570922005-01-25 22:26:29 +000014480 sv = &SCRIPT_SV(i);
14481 sv->sv_var.di_tv.vval.v_dict = &sv->sv_dict;
Bram Moolenaara7043832005-01-21 11:56:39 +000014482 }
14483
Bram Moolenaar071d4272004-06-13 20:20:40 +000014484 while (ga_scripts.ga_len < id)
14485 {
Bram Moolenaar33570922005-01-25 22:26:29 +000014486 sv = &SCRIPT_SV(ga_scripts.ga_len + 1);
14487 init_var_dict(&sv->sv_dict, &sv->sv_var);
Bram Moolenaar071d4272004-06-13 20:20:40 +000014488 ++ga_scripts.ga_len;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014489 }
14490 }
14491}
14492
14493/*
Bram Moolenaar33570922005-01-25 22:26:29 +000014494 * Initialize dictionary "dict" as a scope and set variable "dict_var" to
14495 * point to it.
Bram Moolenaar071d4272004-06-13 20:20:40 +000014496 */
14497 void
Bram Moolenaar33570922005-01-25 22:26:29 +000014498init_var_dict(dict, dict_var)
14499 dict_T *dict;
14500 dictitem_T *dict_var;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014501{
Bram Moolenaar33570922005-01-25 22:26:29 +000014502 hash_init(&dict->dv_hashtab);
14503 dict->dv_refcount = 99999;
14504 dict_var->di_tv.vval.v_dict = dict;
14505 dict_var->di_tv.v_type = VAR_DICT;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000014506 dict_var->di_tv.v_lock = VAR_FIXED;
Bram Moolenaar33570922005-01-25 22:26:29 +000014507 dict_var->di_flags = DI_FLAGS_RO | DI_FLAGS_FIX;
14508 dict_var->di_key[0] = NUL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014509}
14510
14511/*
14512 * Clean up a list of internal variables.
Bram Moolenaar33570922005-01-25 22:26:29 +000014513 * Frees all allocated variables and the value they contain.
14514 * Clears hashtab "ht", does not free it.
Bram Moolenaar071d4272004-06-13 20:20:40 +000014515 */
14516 void
Bram Moolenaara7043832005-01-21 11:56:39 +000014517vars_clear(ht)
Bram Moolenaar33570922005-01-25 22:26:29 +000014518 hashtab_T *ht;
14519{
14520 vars_clear_ext(ht, TRUE);
14521}
14522
14523/*
14524 * Like vars_clear(), but only free the value if "free_val" is TRUE.
14525 */
14526 static void
14527vars_clear_ext(ht, free_val)
14528 hashtab_T *ht;
14529 int free_val;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014530{
Bram Moolenaara7043832005-01-21 11:56:39 +000014531 int todo;
Bram Moolenaar33570922005-01-25 22:26:29 +000014532 hashitem_T *hi;
14533 dictitem_T *v;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014534
Bram Moolenaar33570922005-01-25 22:26:29 +000014535 hash_lock(ht);
Bram Moolenaara7043832005-01-21 11:56:39 +000014536 todo = ht->ht_used;
14537 for (hi = ht->ht_array; todo > 0; ++hi)
14538 {
14539 if (!HASHITEM_EMPTY(hi))
14540 {
14541 --todo;
14542
Bram Moolenaar33570922005-01-25 22:26:29 +000014543 /* Free the variable. Don't remove it from the hashtab,
Bram Moolenaara7043832005-01-21 11:56:39 +000014544 * ht_array might change then. hash_clear() takes care of it
14545 * later. */
Bram Moolenaar33570922005-01-25 22:26:29 +000014546 v = HI2DI(hi);
14547 if (free_val)
14548 clear_tv(&v->di_tv);
14549 if ((v->di_flags & DI_FLAGS_FIX) == 0)
14550 vim_free(v);
Bram Moolenaara7043832005-01-21 11:56:39 +000014551 }
14552 }
14553 hash_clear(ht);
Bram Moolenaar071d4272004-06-13 20:20:40 +000014554}
14555
Bram Moolenaara7043832005-01-21 11:56:39 +000014556/*
Bram Moolenaar33570922005-01-25 22:26:29 +000014557 * Delete a variable from hashtab "ht" at item "hi".
14558 * Clear the variable value and free the dictitem.
Bram Moolenaara7043832005-01-21 11:56:39 +000014559 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000014560 static void
Bram Moolenaara7043832005-01-21 11:56:39 +000014561delete_var(ht, hi)
Bram Moolenaar33570922005-01-25 22:26:29 +000014562 hashtab_T *ht;
14563 hashitem_T *hi;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014564{
Bram Moolenaar33570922005-01-25 22:26:29 +000014565 dictitem_T *di = HI2DI(hi);
Bram Moolenaara7043832005-01-21 11:56:39 +000014566
14567 hash_remove(ht, hi);
Bram Moolenaar33570922005-01-25 22:26:29 +000014568 clear_tv(&di->di_tv);
14569 vim_free(di);
Bram Moolenaar071d4272004-06-13 20:20:40 +000014570}
14571
14572/*
14573 * List the value of one internal variable.
14574 */
14575 static void
14576list_one_var(v, prefix)
Bram Moolenaar33570922005-01-25 22:26:29 +000014577 dictitem_T *v;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014578 char_u *prefix;
14579{
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014580 char_u *tofree;
14581 char_u *s;
Bram Moolenaar8a283e52005-01-06 23:28:25 +000014582 char_u numbuf[NUMBUFLEN];
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014583
Bram Moolenaar33570922005-01-25 22:26:29 +000014584 s = echo_string(&v->di_tv, &tofree, numbuf);
14585 list_one_var_a(prefix, v->di_key, v->di_tv.v_type,
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014586 s == NULL ? (char_u *)"" : s);
14587 vim_free(tofree);
Bram Moolenaar071d4272004-06-13 20:20:40 +000014588}
14589
Bram Moolenaar071d4272004-06-13 20:20:40 +000014590 static void
14591list_one_var_a(prefix, name, type, string)
14592 char_u *prefix;
14593 char_u *name;
14594 int type;
14595 char_u *string;
14596{
14597 msg_attr(prefix, 0); /* don't use msg(), it overwrites "v:statusmsg" */
14598 if (name != NULL) /* "a:" vars don't have a name stored */
14599 msg_puts(name);
14600 msg_putchar(' ');
14601 msg_advance(22);
14602 if (type == VAR_NUMBER)
14603 msg_putchar('#');
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014604 else if (type == VAR_FUNC)
14605 msg_putchar('*');
14606 else if (type == VAR_LIST)
14607 {
14608 msg_putchar('[');
14609 if (*string == '[')
14610 ++string;
14611 }
Bram Moolenaar8c711452005-01-14 21:53:12 +000014612 else if (type == VAR_DICT)
14613 {
14614 msg_putchar('{');
14615 if (*string == '{')
14616 ++string;
14617 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000014618 else
14619 msg_putchar(' ');
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014620
Bram Moolenaar071d4272004-06-13 20:20:40 +000014621 msg_outtrans(string);
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014622
14623 if (type == VAR_FUNC)
14624 msg_puts((char_u *)"()");
Bram Moolenaar071d4272004-06-13 20:20:40 +000014625}
14626
14627/*
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014628 * Set variable "name" to value in "tv".
Bram Moolenaar071d4272004-06-13 20:20:40 +000014629 * If the variable already exists, the value is updated.
14630 * Otherwise the variable is created.
14631 */
14632 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014633set_var(name, tv, copy)
Bram Moolenaar071d4272004-06-13 20:20:40 +000014634 char_u *name;
Bram Moolenaar33570922005-01-25 22:26:29 +000014635 typval_T *tv;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014636 int copy; /* make copy of value in "tv" */
Bram Moolenaar071d4272004-06-13 20:20:40 +000014637{
Bram Moolenaar33570922005-01-25 22:26:29 +000014638 dictitem_T *v;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014639 char_u *varname;
Bram Moolenaar33570922005-01-25 22:26:29 +000014640 hashtab_T *ht;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014641
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014642 if (tv->v_type == VAR_FUNC)
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014643 {
14644 if (!(vim_strchr((char_u *)"wbs", name[0]) != NULL && name[1] == ':')
14645 && !ASCII_ISUPPER((name[0] != NUL && name[1] == ':')
14646 ? name[2] : name[0]))
14647 {
Bram Moolenaare49b69a2005-01-08 16:11:57 +000014648 EMSG2(_("E704: Funcref variable name must start with a capital: %s"), name);
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014649 return;
14650 }
14651 if (function_exists(name))
14652 {
Bram Moolenaar81bf7082005-02-12 14:31:42 +000014653 EMSG2(_("705: Variable name conflicts with existing function: %s"),
14654 name);
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014655 return;
14656 }
14657 }
14658
Bram Moolenaara7043832005-01-21 11:56:39 +000014659 ht = find_var_ht(name, &varname);
Bram Moolenaar33570922005-01-25 22:26:29 +000014660 if (ht == NULL || *varname == NUL)
Bram Moolenaara7043832005-01-21 11:56:39 +000014661 {
14662 EMSG2(_("E461: Illegal variable name: %s"), name);
14663 return;
14664 }
14665
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000014666 v = find_var_in_ht(ht, varname, TRUE);
Bram Moolenaar33570922005-01-25 22:26:29 +000014667 if (v != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000014668 {
Bram Moolenaar33570922005-01-25 22:26:29 +000014669 /* existing variable, need to clear the value */
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000014670 if (var_check_ro(v->di_flags, name)
14671 || tv_check_lock(v->di_tv.v_lock, name))
Bram Moolenaar33570922005-01-25 22:26:29 +000014672 return;
14673 if (v->di_tv.v_type != tv->v_type
14674 && !((v->di_tv.v_type == VAR_STRING
14675 || v->di_tv.v_type == VAR_NUMBER)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014676 && (tv->v_type == VAR_STRING
14677 || tv->v_type == VAR_NUMBER)))
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014678 {
Bram Moolenaare49b69a2005-01-08 16:11:57 +000014679 EMSG2(_("E706: Variable type mismatch for: %s"), name);
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014680 return;
14681 }
Bram Moolenaar33570922005-01-25 22:26:29 +000014682
14683 /*
Bram Moolenaar758711c2005-02-02 23:11:38 +000014684 * Handle setting internal v: variables separately: we don't change
14685 * the type.
Bram Moolenaar33570922005-01-25 22:26:29 +000014686 */
14687 if (ht == &vimvarht)
14688 {
14689 if (v->di_tv.v_type == VAR_STRING)
14690 {
14691 vim_free(v->di_tv.vval.v_string);
14692 if (copy || tv->v_type != VAR_STRING)
14693 v->di_tv.vval.v_string = vim_strsave(get_tv_string(tv));
14694 else
14695 {
14696 /* Take over the string to avoid an extra alloc/free. */
14697 v->di_tv.vval.v_string = tv->vval.v_string;
14698 tv->vval.v_string = NULL;
14699 }
14700 }
14701 else if (v->di_tv.v_type != VAR_NUMBER)
14702 EMSG2(_(e_intern2), "set_var()");
14703 else
14704 v->di_tv.vval.v_number = get_tv_number(tv);
14705 return;
14706 }
14707
14708 clear_tv(&v->di_tv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000014709 }
14710 else /* add a new variable */
14711 {
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000014712 v = (dictitem_T *)alloc((unsigned)(sizeof(dictitem_T)
14713 + STRLEN(varname)));
Bram Moolenaara7043832005-01-21 11:56:39 +000014714 if (v == NULL)
14715 return;
Bram Moolenaar33570922005-01-25 22:26:29 +000014716 STRCPY(v->di_key, varname);
Bram Moolenaar33570922005-01-25 22:26:29 +000014717 if (hash_add(ht, DI2HIKEY(v)) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000014718 {
Bram Moolenaara7043832005-01-21 11:56:39 +000014719 vim_free(v);
Bram Moolenaar071d4272004-06-13 20:20:40 +000014720 return;
14721 }
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000014722 v->di_flags = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014723 }
Bram Moolenaara7043832005-01-21 11:56:39 +000014724
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014725 if (copy || tv->v_type == VAR_NUMBER)
Bram Moolenaar33570922005-01-25 22:26:29 +000014726 copy_tv(tv, &v->di_tv);
Bram Moolenaar1c2fda22005-01-02 11:43:19 +000014727 else
14728 {
Bram Moolenaar33570922005-01-25 22:26:29 +000014729 v->di_tv = *tv;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000014730 v->di_tv.v_lock = 0;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014731 init_tv(tv);
Bram Moolenaar1c2fda22005-01-02 11:43:19 +000014732 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000014733}
14734
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014735/*
Bram Moolenaar33570922005-01-25 22:26:29 +000014736 * Return TRUE if di_flags "flags" indicate read-only variable "name".
14737 * Also give an error message.
14738 */
14739 static int
14740var_check_ro(flags, name)
14741 int flags;
14742 char_u *name;
14743{
14744 if (flags & DI_FLAGS_RO)
14745 {
14746 EMSG2(_(e_readonlyvar), name);
14747 return TRUE;
14748 }
14749 if ((flags & DI_FLAGS_RO_SBX) && sandbox)
14750 {
14751 EMSG2(_(e_readonlysbx), name);
14752 return TRUE;
14753 }
14754 return FALSE;
14755}
14756
14757/*
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000014758 * Return TRUE if typeval "tv" is set to be locked (immutable).
14759 * Also give an error message, using "name".
14760 */
14761 static int
14762tv_check_lock(lock, name)
14763 int lock;
14764 char_u *name;
14765{
14766 if (lock & VAR_LOCKED)
14767 {
14768 EMSG2(_("E741: Value is locked: %s"),
14769 name == NULL ? (char_u *)_("Unknown") : name);
14770 return TRUE;
14771 }
14772 if (lock & VAR_FIXED)
14773 {
14774 EMSG2(_("E742: Cannot change value of %s"),
14775 name == NULL ? (char_u *)_("Unknown") : name);
14776 return TRUE;
14777 }
14778 return FALSE;
14779}
14780
14781/*
Bram Moolenaar33570922005-01-25 22:26:29 +000014782 * Copy the values from typval_T "from" to typval_T "to".
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014783 * When needed allocates string or increases reference count.
Bram Moolenaare9a41262005-01-15 22:18:47 +000014784 * Does not make a copy of a list or dict but copies the reference!
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014785 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000014786 static void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014787copy_tv(from, to)
Bram Moolenaar33570922005-01-25 22:26:29 +000014788 typval_T *from;
14789 typval_T *to;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014790{
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014791 to->v_type = from->v_type;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000014792 to->v_lock = 0;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014793 switch (from->v_type)
14794 {
14795 case VAR_NUMBER:
14796 to->vval.v_number = from->vval.v_number;
14797 break;
14798 case VAR_STRING:
14799 case VAR_FUNC:
14800 if (from->vval.v_string == NULL)
14801 to->vval.v_string = NULL;
14802 else
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000014803 {
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014804 to->vval.v_string = vim_strsave(from->vval.v_string);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000014805 if (from->v_type == VAR_FUNC)
14806 func_ref(to->vval.v_string);
14807 }
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014808 break;
14809 case VAR_LIST:
14810 if (from->vval.v_list == NULL)
14811 to->vval.v_list = NULL;
14812 else
14813 {
14814 to->vval.v_list = from->vval.v_list;
14815 ++to->vval.v_list->lv_refcount;
14816 }
14817 break;
Bram Moolenaar8c711452005-01-14 21:53:12 +000014818 case VAR_DICT:
14819 if (from->vval.v_dict == NULL)
14820 to->vval.v_dict = NULL;
14821 else
14822 {
14823 to->vval.v_dict = from->vval.v_dict;
14824 ++to->vval.v_dict->dv_refcount;
14825 }
14826 break;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014827 default:
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014828 EMSG2(_(e_intern2), "copy_tv()");
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014829 break;
14830 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000014831}
14832
14833/*
Bram Moolenaare9a41262005-01-15 22:18:47 +000014834 * Make a copy of an item.
14835 * Lists and Dictionaries are also copied. A deep copy if "deep" is set.
Bram Moolenaar81bf7082005-02-12 14:31:42 +000014836 * For deepcopy() "copyID" is zero for a full copy or the ID for when a
14837 * reference to an already copied list/dict can be used.
14838 * Returns FAIL or OK.
Bram Moolenaare9a41262005-01-15 22:18:47 +000014839 */
Bram Moolenaar81bf7082005-02-12 14:31:42 +000014840 static int
14841item_copy(from, to, deep, copyID)
Bram Moolenaar33570922005-01-25 22:26:29 +000014842 typval_T *from;
14843 typval_T *to;
Bram Moolenaare9a41262005-01-15 22:18:47 +000014844 int deep;
Bram Moolenaar81bf7082005-02-12 14:31:42 +000014845 int copyID;
Bram Moolenaare9a41262005-01-15 22:18:47 +000014846{
14847 static int recurse = 0;
Bram Moolenaar81bf7082005-02-12 14:31:42 +000014848 int ret = OK;
Bram Moolenaare9a41262005-01-15 22:18:47 +000014849
Bram Moolenaar33570922005-01-25 22:26:29 +000014850 if (recurse >= DICT_MAXNEST)
Bram Moolenaare9a41262005-01-15 22:18:47 +000014851 {
14852 EMSG(_("E698: variable nested too deep for making a copy"));
Bram Moolenaar81bf7082005-02-12 14:31:42 +000014853 return FAIL;
Bram Moolenaare9a41262005-01-15 22:18:47 +000014854 }
14855 ++recurse;
14856
14857 switch (from->v_type)
14858 {
14859 case VAR_NUMBER:
14860 case VAR_STRING:
14861 case VAR_FUNC:
14862 copy_tv(from, to);
14863 break;
14864 case VAR_LIST:
14865 to->v_type = VAR_LIST;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000014866 to->v_lock = 0;
Bram Moolenaar81bf7082005-02-12 14:31:42 +000014867 if (from->vval.v_list == NULL)
14868 to->vval.v_list = NULL;
14869 else if (copyID != 0 && from->vval.v_list->lv_copyID == copyID)
14870 {
14871 /* use the copy made earlier */
14872 to->vval.v_list = from->vval.v_list->lv_copylist;
14873 ++to->vval.v_list->lv_refcount;
14874 }
14875 else
14876 to->vval.v_list = list_copy(from->vval.v_list, deep, copyID);
14877 if (to->vval.v_list == NULL)
14878 ret = FAIL;
Bram Moolenaare9a41262005-01-15 22:18:47 +000014879 break;
14880 case VAR_DICT:
14881 to->v_type = VAR_DICT;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000014882 to->v_lock = 0;
Bram Moolenaar81bf7082005-02-12 14:31:42 +000014883 if (from->vval.v_dict == NULL)
14884 to->vval.v_dict = NULL;
14885 else if (copyID != 0 && from->vval.v_dict->dv_copyID == copyID)
14886 {
14887 /* use the copy made earlier */
14888 to->vval.v_dict = from->vval.v_dict->dv_copydict;
14889 ++to->vval.v_dict->dv_refcount;
14890 }
14891 else
14892 to->vval.v_dict = dict_copy(from->vval.v_dict, deep, copyID);
14893 if (to->vval.v_dict == NULL)
14894 ret = FAIL;
Bram Moolenaare9a41262005-01-15 22:18:47 +000014895 break;
14896 default:
14897 EMSG2(_(e_intern2), "item_copy()");
Bram Moolenaar81bf7082005-02-12 14:31:42 +000014898 ret = FAIL;
Bram Moolenaare9a41262005-01-15 22:18:47 +000014899 }
14900 --recurse;
Bram Moolenaar81bf7082005-02-12 14:31:42 +000014901 return ret;
Bram Moolenaare9a41262005-01-15 22:18:47 +000014902}
14903
14904/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000014905 * ":echo expr1 ..." print each argument separated with a space, add a
14906 * newline at the end.
14907 * ":echon expr1 ..." print each argument plain.
14908 */
14909 void
14910ex_echo(eap)
14911 exarg_T *eap;
14912{
14913 char_u *arg = eap->arg;
Bram Moolenaar33570922005-01-25 22:26:29 +000014914 typval_T rettv;
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014915 char_u *tofree;
Bram Moolenaar071d4272004-06-13 20:20:40 +000014916 char_u *p;
14917 int needclr = TRUE;
14918 int atstart = TRUE;
Bram Moolenaar8a283e52005-01-06 23:28:25 +000014919 char_u numbuf[NUMBUFLEN];
Bram Moolenaar071d4272004-06-13 20:20:40 +000014920
14921 if (eap->skip)
14922 ++emsg_skip;
14923 while (*arg != NUL && *arg != '|' && *arg != '\n' && !got_int)
14924 {
14925 p = arg;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014926 if (eval1(&arg, &rettv, !eap->skip) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000014927 {
14928 /*
14929 * Report the invalid expression unless the expression evaluation
14930 * has been cancelled due to an aborting error, an interrupt, or an
14931 * exception.
14932 */
14933 if (!aborting())
14934 EMSG2(_(e_invexpr2), p);
14935 break;
14936 }
14937 if (!eap->skip)
14938 {
14939 if (atstart)
14940 {
14941 atstart = FALSE;
14942 /* Call msg_start() after eval1(), evaluating the expression
14943 * may cause a message to appear. */
14944 if (eap->cmdidx == CMD_echo)
14945 msg_start();
14946 }
14947 else if (eap->cmdidx == CMD_echo)
14948 msg_puts_attr((char_u *)" ", echo_attr);
Bram Moolenaar81bf7082005-02-12 14:31:42 +000014949 p = echo_string(&rettv, &tofree, numbuf);
14950 if (p != NULL)
14951 for ( ; *p != NUL && !got_int; ++p)
Bram Moolenaar071d4272004-06-13 20:20:40 +000014952 {
Bram Moolenaar81bf7082005-02-12 14:31:42 +000014953 if (*p == '\n' || *p == '\r' || *p == TAB)
Bram Moolenaar071d4272004-06-13 20:20:40 +000014954 {
Bram Moolenaar81bf7082005-02-12 14:31:42 +000014955 if (*p != TAB && needclr)
14956 {
14957 /* remove any text still there from the command */
14958 msg_clr_eos();
14959 needclr = FALSE;
14960 }
14961 msg_putchar_attr(*p, echo_attr);
Bram Moolenaar071d4272004-06-13 20:20:40 +000014962 }
14963 else
Bram Moolenaar81bf7082005-02-12 14:31:42 +000014964 {
14965#ifdef FEAT_MBYTE
14966 if (has_mbyte)
14967 {
14968 int i = (*mb_ptr2len_check)(p);
14969
14970 (void)msg_outtrans_len_attr(p, i, echo_attr);
14971 p += i - 1;
14972 }
14973 else
Bram Moolenaar071d4272004-06-13 20:20:40 +000014974#endif
Bram Moolenaar81bf7082005-02-12 14:31:42 +000014975 (void)msg_outtrans_len_attr(p, 1, echo_attr);
14976 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000014977 }
Bram Moolenaar49cd9572005-01-03 21:06:01 +000014978 vim_free(tofree);
Bram Moolenaar071d4272004-06-13 20:20:40 +000014979 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +000014980 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000014981 arg = skipwhite(arg);
14982 }
14983 eap->nextcmd = check_nextcmd(arg);
14984
14985 if (eap->skip)
14986 --emsg_skip;
14987 else
14988 {
14989 /* remove text that may still be there from the command */
14990 if (needclr)
14991 msg_clr_eos();
14992 if (eap->cmdidx == CMD_echo)
14993 msg_end();
14994 }
14995}
14996
14997/*
14998 * ":echohl {name}".
14999 */
15000 void
15001ex_echohl(eap)
15002 exarg_T *eap;
15003{
15004 int id;
15005
15006 id = syn_name2id(eap->arg);
15007 if (id == 0)
15008 echo_attr = 0;
15009 else
15010 echo_attr = syn_id2attr(id);
15011}
15012
15013/*
15014 * ":execute expr1 ..." execute the result of an expression.
15015 * ":echomsg expr1 ..." Print a message
15016 * ":echoerr expr1 ..." Print an error
15017 * Each gets spaces around each argument and a newline at the end for
15018 * echo commands
15019 */
15020 void
15021ex_execute(eap)
15022 exarg_T *eap;
15023{
15024 char_u *arg = eap->arg;
Bram Moolenaar33570922005-01-25 22:26:29 +000015025 typval_T rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015026 int ret = OK;
15027 char_u *p;
15028 garray_T ga;
15029 int len;
15030 int save_did_emsg;
15031
15032 ga_init2(&ga, 1, 80);
15033
15034 if (eap->skip)
15035 ++emsg_skip;
15036 while (*arg != NUL && *arg != '|' && *arg != '\n')
15037 {
15038 p = arg;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015039 if (eval1(&arg, &rettv, !eap->skip) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000015040 {
15041 /*
15042 * Report the invalid expression unless the expression evaluation
15043 * has been cancelled due to an aborting error, an interrupt, or an
15044 * exception.
15045 */
15046 if (!aborting())
15047 EMSG2(_(e_invexpr2), p);
15048 ret = FAIL;
15049 break;
15050 }
15051
15052 if (!eap->skip)
15053 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015054 p = get_tv_string(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000015055 len = (int)STRLEN(p);
15056 if (ga_grow(&ga, len + 2) == FAIL)
15057 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015058 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000015059 ret = FAIL;
15060 break;
15061 }
15062 if (ga.ga_len)
Bram Moolenaar071d4272004-06-13 20:20:40 +000015063 ((char_u *)(ga.ga_data))[ga.ga_len++] = ' ';
Bram Moolenaar071d4272004-06-13 20:20:40 +000015064 STRCPY((char_u *)(ga.ga_data) + ga.ga_len, p);
Bram Moolenaar071d4272004-06-13 20:20:40 +000015065 ga.ga_len += len;
15066 }
15067
Bram Moolenaarc70646c2005-01-04 21:52:38 +000015068 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000015069 arg = skipwhite(arg);
15070 }
15071
15072 if (ret != FAIL && ga.ga_data != NULL)
15073 {
15074 if (eap->cmdidx == CMD_echomsg)
15075 MSG_ATTR(ga.ga_data, echo_attr);
15076 else if (eap->cmdidx == CMD_echoerr)
15077 {
15078 /* We don't want to abort following commands, restore did_emsg. */
15079 save_did_emsg = did_emsg;
15080 EMSG((char_u *)ga.ga_data);
15081 if (!force_abort)
15082 did_emsg = save_did_emsg;
15083 }
15084 else if (eap->cmdidx == CMD_execute)
15085 do_cmdline((char_u *)ga.ga_data,
15086 eap->getline, eap->cookie, DOCMD_NOWAIT|DOCMD_VERBOSE);
15087 }
15088
15089 ga_clear(&ga);
15090
15091 if (eap->skip)
15092 --emsg_skip;
15093
15094 eap->nextcmd = check_nextcmd(arg);
15095}
15096
15097/*
15098 * Skip over the name of an option: "&option", "&g:option" or "&l:option".
15099 * "arg" points to the "&" or '+' when called, to "option" when returning.
15100 * Returns NULL when no option name found. Otherwise pointer to the char
15101 * after the option name.
15102 */
15103 static char_u *
15104find_option_end(arg, opt_flags)
15105 char_u **arg;
15106 int *opt_flags;
15107{
15108 char_u *p = *arg;
15109
15110 ++p;
15111 if (*p == 'g' && p[1] == ':')
15112 {
15113 *opt_flags = OPT_GLOBAL;
15114 p += 2;
15115 }
15116 else if (*p == 'l' && p[1] == ':')
15117 {
15118 *opt_flags = OPT_LOCAL;
15119 p += 2;
15120 }
15121 else
15122 *opt_flags = 0;
15123
15124 if (!ASCII_ISALPHA(*p))
15125 return NULL;
15126 *arg = p;
15127
15128 if (p[0] == 't' && p[1] == '_' && p[2] != NUL && p[3] != NUL)
15129 p += 4; /* termcap option */
15130 else
15131 while (ASCII_ISALPHA(*p))
15132 ++p;
15133 return p;
15134}
15135
15136/*
15137 * ":function"
15138 */
15139 void
15140ex_function(eap)
15141 exarg_T *eap;
15142{
15143 char_u *theline;
15144 int j;
15145 int c;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015146 int saved_did_emsg;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015147 char_u *name = NULL;
15148 char_u *p;
15149 char_u *arg;
15150 garray_T newargs;
15151 garray_T newlines;
15152 int varargs = FALSE;
15153 int mustend = FALSE;
15154 int flags = 0;
15155 ufunc_T *fp;
15156 int indent;
15157 int nesting;
15158 char_u *skip_until = NULL;
Bram Moolenaar33570922005-01-25 22:26:29 +000015159 dictitem_T *v;
15160 funcdict_T fudi;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000015161 static int func_nr = 0; /* number for nameless function */
15162 int paren;
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000015163 hashtab_T *ht;
15164 int todo;
15165 hashitem_T *hi;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015166
15167 /*
15168 * ":function" without argument: list functions.
15169 */
15170 if (ends_excmd(*eap->arg))
15171 {
15172 if (!eap->skip)
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000015173 {
15174 todo = globvarht.ht_used;
15175 for (hi = globvarht.ht_array; todo > 0 && !got_int; ++hi)
15176 {
15177 if (!HASHITEM_EMPTY(hi))
15178 {
15179 --todo;
15180 fp = HI2UF(hi);
15181 if (!isdigit(*fp->uf_name))
15182 list_func_head(fp, FALSE);
15183 }
15184 }
15185 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000015186 eap->nextcmd = check_nextcmd(eap->arg);
15187 return;
15188 }
15189
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000015190 /*
15191 * Get the function name. There are these situations:
15192 * func normal function name
15193 * "name" == func, "fudi.fd_dict" == NULL
15194 * dict.func new dictionary entry
15195 * "name" == NULL, "fudi.fd_dict" set,
15196 * "fudi.fd_di" == NULL, "fudi.fd_newkey" == func
15197 * dict.func existing dict entry with a Funcref
15198 * "name" == fname, "fudi.fd_dict" set,
15199 * "fudi.fd_di" set, "fudi.fd_newkey" == NULL
15200 * dict.func existing dict entry that's not a Funcref
15201 * "name" == NULL, "fudi.fd_dict" set,
15202 * "fudi.fd_di" set, "fudi.fd_newkey" == NULL
15203 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000015204 p = eap->arg;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000015205 name = trans_function_name(&p, eap->skip, 0, &fudi);
15206 paren = (vim_strchr(p, '(') != NULL);
15207 if (name == NULL && (fudi.fd_dict == NULL || !paren) && !eap->skip)
Bram Moolenaar071d4272004-06-13 20:20:40 +000015208 {
15209 /*
15210 * Return on an invalid expression in braces, unless the expression
15211 * evaluation has been cancelled due to an aborting error, an
15212 * interrupt, or an exception.
15213 */
15214 if (!aborting())
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000015215 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000015216 if (!eap->skip && fudi.fd_newkey != NULL)
15217 EMSG2(_(e_dictkey), fudi.fd_newkey);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000015218 vim_free(fudi.fd_newkey);
Bram Moolenaar071d4272004-06-13 20:20:40 +000015219 return;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000015220 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000015221 else
15222 eap->skip = TRUE;
15223 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000015224 /* An error in a function call during evaluation of an expression in magic
15225 * braces should not cause the function not to be defined. */
15226 saved_did_emsg = did_emsg;
15227 did_emsg = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015228
15229 /*
15230 * ":function func" with only function name: list function.
15231 */
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000015232 if (!paren)
Bram Moolenaar071d4272004-06-13 20:20:40 +000015233 {
15234 if (!ends_excmd(*skipwhite(p)))
15235 {
15236 EMSG(_(e_trailing));
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000015237 goto ret_free;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015238 }
15239 eap->nextcmd = check_nextcmd(p);
15240 if (eap->nextcmd != NULL)
15241 *p = NUL;
15242 if (!eap->skip && !got_int)
15243 {
15244 fp = find_func(name);
15245 if (fp != NULL)
15246 {
15247 list_func_head(fp, TRUE);
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000015248 for (j = 0; j < fp->uf_lines.ga_len && !got_int; ++j)
Bram Moolenaar071d4272004-06-13 20:20:40 +000015249 {
15250 msg_putchar('\n');
15251 msg_outnum((long)(j + 1));
15252 if (j < 9)
15253 msg_putchar(' ');
15254 if (j < 99)
15255 msg_putchar(' ');
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000015256 msg_prt_line(FUNCLINE(fp, j), FALSE);
Bram Moolenaar071d4272004-06-13 20:20:40 +000015257 out_flush(); /* show a line at a time */
15258 ui_breakcheck();
15259 }
15260 if (!got_int)
15261 {
15262 msg_putchar('\n');
15263 msg_puts((char_u *)" endfunction");
15264 }
15265 }
15266 else
Bram Moolenaar81bf7082005-02-12 14:31:42 +000015267 emsg_funcname("E123: Undefined function: %s", name);
Bram Moolenaar071d4272004-06-13 20:20:40 +000015268 }
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000015269 goto ret_free;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015270 }
15271
15272 /*
15273 * ":function name(arg1, arg2)" Define function.
15274 */
15275 p = skipwhite(p);
15276 if (*p != '(')
15277 {
15278 if (!eap->skip)
15279 {
15280 EMSG2(_("E124: Missing '(': %s"), eap->arg);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000015281 goto ret_free;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015282 }
15283 /* attempt to continue by skipping some text */
15284 if (vim_strchr(p, '(') != NULL)
15285 p = vim_strchr(p, '(');
15286 }
15287 p = skipwhite(p + 1);
15288
15289 ga_init2(&newargs, (int)sizeof(char_u *), 3);
15290 ga_init2(&newlines, (int)sizeof(char_u *), 3);
15291
15292 /*
15293 * Isolate the arguments: "arg1, arg2, ...)"
15294 */
15295 while (*p != ')')
15296 {
15297 if (p[0] == '.' && p[1] == '.' && p[2] == '.')
15298 {
15299 varargs = TRUE;
15300 p += 3;
15301 mustend = TRUE;
15302 }
15303 else
15304 {
15305 arg = p;
15306 while (ASCII_ISALNUM(*p) || *p == '_')
15307 ++p;
15308 if (arg == p || isdigit(*arg)
15309 || (p - arg == 9 && STRNCMP(arg, "firstline", 9) == 0)
15310 || (p - arg == 8 && STRNCMP(arg, "lastline", 8) == 0))
15311 {
15312 if (!eap->skip)
15313 EMSG2(_("E125: Illegal argument: %s"), arg);
15314 break;
15315 }
15316 if (ga_grow(&newargs, 1) == FAIL)
15317 goto erret;
15318 c = *p;
15319 *p = NUL;
15320 arg = vim_strsave(arg);
15321 if (arg == NULL)
15322 goto erret;
15323 ((char_u **)(newargs.ga_data))[newargs.ga_len] = arg;
15324 *p = c;
15325 newargs.ga_len++;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015326 if (*p == ',')
15327 ++p;
15328 else
15329 mustend = TRUE;
15330 }
15331 p = skipwhite(p);
15332 if (mustend && *p != ')')
15333 {
15334 if (!eap->skip)
15335 EMSG2(_(e_invarg2), eap->arg);
15336 break;
15337 }
15338 }
15339 ++p; /* skip the ')' */
15340
Bram Moolenaare9a41262005-01-15 22:18:47 +000015341 /* find extra arguments "range", "dict" and "abort" */
Bram Moolenaar071d4272004-06-13 20:20:40 +000015342 for (;;)
15343 {
15344 p = skipwhite(p);
15345 if (STRNCMP(p, "range", 5) == 0)
15346 {
15347 flags |= FC_RANGE;
15348 p += 5;
15349 }
Bram Moolenaare9a41262005-01-15 22:18:47 +000015350 else if (STRNCMP(p, "dict", 4) == 0)
15351 {
15352 flags |= FC_DICT;
15353 p += 4;
15354 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000015355 else if (STRNCMP(p, "abort", 5) == 0)
15356 {
15357 flags |= FC_ABORT;
15358 p += 5;
15359 }
15360 else
15361 break;
15362 }
15363
15364 if (*p != NUL && *p != '"' && *p != '\n' && !eap->skip && !did_emsg)
15365 EMSG(_(e_trailing));
15366
15367 /*
15368 * Read the body of the function, until ":endfunction" is found.
15369 */
15370 if (KeyTyped)
15371 {
15372 /* Check if the function already exists, don't let the user type the
15373 * whole function before telling him it doesn't work! For a script we
15374 * need to skip the body to be able to find what follows. */
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000015375 if (!eap->skip && !eap->forceit)
15376 {
15377 if (fudi.fd_dict != NULL && fudi.fd_newkey == NULL)
15378 EMSG(_(e_funcdict));
15379 else if (name != NULL && find_func(name) != NULL)
Bram Moolenaar81bf7082005-02-12 14:31:42 +000015380 emsg_funcname(e_funcexts, name);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000015381 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000015382
15383 msg_putchar('\n'); /* don't overwrite the function name */
15384 cmdline_row = msg_row;
15385 }
15386
15387 indent = 2;
15388 nesting = 0;
15389 for (;;)
15390 {
15391 msg_scroll = TRUE;
15392 need_wait_return = FALSE;
15393 if (eap->getline == NULL)
15394 theline = getcmdline(':', 0L, indent);
15395 else
15396 theline = eap->getline(':', eap->cookie, indent);
15397 if (KeyTyped)
15398 lines_left = Rows - 1;
15399 if (theline == NULL)
15400 {
15401 EMSG(_("E126: Missing :endfunction"));
15402 goto erret;
15403 }
15404
15405 if (skip_until != NULL)
15406 {
15407 /* between ":append" and "." and between ":python <<EOF" and "EOF"
15408 * don't check for ":endfunc". */
15409 if (STRCMP(theline, skip_until) == 0)
15410 {
15411 vim_free(skip_until);
15412 skip_until = NULL;
15413 }
15414 }
15415 else
15416 {
15417 /* skip ':' and blanks*/
15418 for (p = theline; vim_iswhite(*p) || *p == ':'; ++p)
15419 ;
15420
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000015421 /* Check for "endfunction". */
15422 if (checkforcmd(&p, "endfunction", 4) && nesting-- == 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +000015423 {
15424 vim_free(theline);
15425 break;
15426 }
15427
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000015428 /* Increase indent inside "if", "while", "for" and "try", decrease
Bram Moolenaar071d4272004-06-13 20:20:40 +000015429 * at "end". */
15430 if (indent > 2 && STRNCMP(p, "end", 3) == 0)
15431 indent -= 2;
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000015432 else if (STRNCMP(p, "if", 2) == 0
15433 || STRNCMP(p, "wh", 2) == 0
15434 || STRNCMP(p, "for", 3) == 0
Bram Moolenaar071d4272004-06-13 20:20:40 +000015435 || STRNCMP(p, "try", 3) == 0)
15436 indent += 2;
15437
15438 /* Check for defining a function inside this function. */
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000015439 if (checkforcmd(&p, "function", 2))
Bram Moolenaar071d4272004-06-13 20:20:40 +000015440 {
Bram Moolenaar31c67ef2005-01-11 21:34:41 +000015441 if (*p == '!')
15442 p = skipwhite(p + 1);
Bram Moolenaar071d4272004-06-13 20:20:40 +000015443 p += eval_fname_script(p);
15444 if (ASCII_ISALPHA(*p))
15445 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000015446 vim_free(trans_function_name(&p, TRUE, 0, NULL));
Bram Moolenaar071d4272004-06-13 20:20:40 +000015447 if (*skipwhite(p) == '(')
15448 {
15449 ++nesting;
15450 indent += 2;
15451 }
15452 }
15453 }
15454
15455 /* Check for ":append" or ":insert". */
15456 p = skip_range(p, NULL);
15457 if ((p[0] == 'a' && (!ASCII_ISALPHA(p[1]) || p[1] == 'p'))
15458 || (p[0] == 'i'
15459 && (!ASCII_ISALPHA(p[1]) || (p[1] == 'n'
15460 && (!ASCII_ISALPHA(p[2]) || (p[2] == 's'))))))
15461 skip_until = vim_strsave((char_u *)".");
15462
15463 /* Check for ":python <<EOF", ":tcl <<EOF", etc. */
15464 arg = skipwhite(skiptowhite(p));
15465 if (arg[0] == '<' && arg[1] =='<'
15466 && ((p[0] == 'p' && p[1] == 'y'
15467 && (!ASCII_ISALPHA(p[2]) || p[2] == 't'))
15468 || (p[0] == 'p' && p[1] == 'e'
15469 && (!ASCII_ISALPHA(p[2]) || p[2] == 'r'))
15470 || (p[0] == 't' && p[1] == 'c'
15471 && (!ASCII_ISALPHA(p[2]) || p[2] == 'l'))
15472 || (p[0] == 'r' && p[1] == 'u' && p[2] == 'b'
15473 && (!ASCII_ISALPHA(p[3]) || p[3] == 'y'))
Bram Moolenaar325b7a22004-07-05 15:58:32 +000015474 || (p[0] == 'm' && p[1] == 'z'
15475 && (!ASCII_ISALPHA(p[2]) || p[2] == 's'))
Bram Moolenaar071d4272004-06-13 20:20:40 +000015476 ))
15477 {
15478 /* ":python <<" continues until a dot, like ":append" */
15479 p = skipwhite(arg + 2);
15480 if (*p == NUL)
15481 skip_until = vim_strsave((char_u *)".");
15482 else
15483 skip_until = vim_strsave(p);
15484 }
15485 }
15486
15487 /* Add the line to the function. */
15488 if (ga_grow(&newlines, 1) == FAIL)
15489 goto erret;
15490 ((char_u **)(newlines.ga_data))[newlines.ga_len] = theline;
15491 newlines.ga_len++;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015492 }
15493
15494 /* Don't define the function when skipping commands or when an error was
15495 * detected. */
15496 if (eap->skip || did_emsg)
15497 goto erret;
15498
15499 /*
15500 * If there are no errors, add the function
15501 */
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000015502 if (fudi.fd_dict == NULL)
Bram Moolenaar49cd9572005-01-03 21:06:01 +000015503 {
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000015504 v = find_var(name, &ht);
Bram Moolenaar33570922005-01-25 22:26:29 +000015505 if (v != NULL && v->di_tv.v_type == VAR_FUNC)
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000015506 {
Bram Moolenaar81bf7082005-02-12 14:31:42 +000015507 emsg_funcname("E707: Function name conflicts with variable: %s",
15508 name);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000015509 goto erret;
15510 }
Bram Moolenaar49cd9572005-01-03 21:06:01 +000015511
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000015512 fp = find_func(name);
15513 if (fp != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000015514 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000015515 if (!eap->forceit)
15516 {
Bram Moolenaar81bf7082005-02-12 14:31:42 +000015517 emsg_funcname(e_funcexts, name);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000015518 goto erret;
15519 }
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000015520 if (fp->uf_calls > 0)
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000015521 {
Bram Moolenaar81bf7082005-02-12 14:31:42 +000015522 emsg_funcname("E127: Cannot redefine function %s: It is in use",
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000015523 name);
15524 goto erret;
15525 }
15526 /* redefine existing function */
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000015527 ga_clear_strings(&(fp->uf_args));
15528 ga_clear_strings(&(fp->uf_lines));
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000015529 vim_free(name);
15530 name = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015531 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000015532 }
15533 else
15534 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000015535 char numbuf[20];
15536
15537 fp = NULL;
15538 if (fudi.fd_newkey == NULL && !eap->forceit)
15539 {
15540 EMSG(_(e_funcdict));
15541 goto erret;
15542 }
Bram Moolenaar758711c2005-02-02 23:11:38 +000015543 if (fudi.fd_di == NULL)
15544 {
15545 /* Can't add a function to a locked dictionary */
15546 if (tv_check_lock(fudi.fd_dict->dv_lock, eap->arg))
15547 goto erret;
15548 }
15549 /* Can't change an existing function if it is locked */
15550 else if (tv_check_lock(fudi.fd_di->di_tv.v_lock, eap->arg))
15551 goto erret;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000015552
15553 /* Give the function a sequential number. Can only be used with a
15554 * Funcref! */
15555 vim_free(name);
15556 sprintf(numbuf, "%d", ++func_nr);
15557 name = vim_strsave((char_u *)numbuf);
15558 if (name == NULL)
15559 goto erret;
15560 }
15561
15562 if (fp == NULL)
15563 {
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000015564 if (fudi.fd_dict == NULL && vim_strchr(name, ':') != NULL)
15565 {
15566 int slen, plen;
15567 char_u *scriptname;
15568
15569 /* Check that the autoload name matches the script name. */
15570 j = FAIL;
15571 if (sourcing_name != NULL)
15572 {
15573 scriptname = autoload_name(name);
15574 if (scriptname != NULL)
15575 {
15576 p = vim_strchr(scriptname, '/');
15577 plen = STRLEN(p);
15578 slen = STRLEN(sourcing_name);
15579 if (slen > plen && fnamecmp(p,
15580 sourcing_name + slen - plen) == 0)
15581 j = OK;
15582 vim_free(scriptname);
15583 }
15584 }
15585 if (j == FAIL)
15586 {
15587 EMSG2(_("E746: Function name does not match script file name: %s"), name);
15588 goto erret;
15589 }
15590 }
15591
15592 fp = (ufunc_T *)alloc((unsigned)(sizeof(ufunc_T) + STRLEN(name)));
Bram Moolenaar071d4272004-06-13 20:20:40 +000015593 if (fp == NULL)
15594 goto erret;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000015595
15596 if (fudi.fd_dict != NULL)
15597 {
15598 if (fudi.fd_di == NULL)
15599 {
15600 /* add new dict entry */
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000015601 fudi.fd_di = dictitem_alloc(fudi.fd_newkey);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000015602 if (fudi.fd_di == NULL)
15603 {
15604 vim_free(fp);
15605 goto erret;
15606 }
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000015607 if (dict_add(fudi.fd_dict, fudi.fd_di) == FAIL)
15608 {
15609 vim_free(fudi.fd_di);
15610 goto erret;
15611 }
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000015612 }
15613 else
15614 /* overwrite existing dict entry */
15615 clear_tv(&fudi.fd_di->di_tv);
15616 fudi.fd_di->di_tv.v_type = VAR_FUNC;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000015617 fudi.fd_di->di_tv.v_lock = 0;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000015618 fudi.fd_di->di_tv.vval.v_string = vim_strsave(name);
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000015619 fp->uf_refcount = 1;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000015620 }
15621
Bram Moolenaar071d4272004-06-13 20:20:40 +000015622 /* insert the new function in the function list */
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000015623 STRCPY(fp->uf_name, name);
15624 hash_add(&func_hashtab, UF2HIKEY(fp));
Bram Moolenaar071d4272004-06-13 20:20:40 +000015625 }
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000015626 fp->uf_args = newargs;
15627 fp->uf_lines = newlines;
15628 fp->uf_varargs = varargs;
15629 fp->uf_flags = flags;
15630 fp->uf_calls = 0;
15631 fp->uf_script_ID = current_SID;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000015632 goto ret_free;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015633
15634erret:
Bram Moolenaar071d4272004-06-13 20:20:40 +000015635 ga_clear_strings(&newargs);
15636 ga_clear_strings(&newlines);
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000015637ret_free:
15638 vim_free(skip_until);
15639 vim_free(fudi.fd_newkey);
Bram Moolenaar071d4272004-06-13 20:20:40 +000015640 vim_free(name);
Bram Moolenaar071d4272004-06-13 20:20:40 +000015641 did_emsg |= saved_did_emsg;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015642}
15643
15644/*
15645 * Get a function name, translating "<SID>" and "<SNR>".
Bram Moolenaara7043832005-01-21 11:56:39 +000015646 * Also handles a Funcref in a List or Dictionary.
Bram Moolenaar071d4272004-06-13 20:20:40 +000015647 * Returns the function name in allocated memory, or NULL for failure.
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000015648 * flags:
15649 * TFN_INT: internal function name OK
15650 * TFN_QUIET: be quiet
Bram Moolenaar071d4272004-06-13 20:20:40 +000015651 * Advances "pp" to just after the function name (if no error).
15652 */
15653 static char_u *
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000015654trans_function_name(pp, skip, flags, fdp)
Bram Moolenaar071d4272004-06-13 20:20:40 +000015655 char_u **pp;
15656 int skip; /* only find the end, don't evaluate */
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000015657 int flags;
Bram Moolenaar33570922005-01-25 22:26:29 +000015658 funcdict_T *fdp; /* return: info about dictionary used */
Bram Moolenaar071d4272004-06-13 20:20:40 +000015659{
Bram Moolenaar7480b5c2005-01-16 22:07:38 +000015660 char_u *name = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015661 char_u *start;
15662 char_u *end;
15663 int lead;
15664 char_u sid_buf[20];
Bram Moolenaar071d4272004-06-13 20:20:40 +000015665 int len;
Bram Moolenaar33570922005-01-25 22:26:29 +000015666 lval_T lv;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000015667
15668 if (fdp != NULL)
Bram Moolenaar33570922005-01-25 22:26:29 +000015669 vim_memset(fdp, 0, sizeof(funcdict_T));
Bram Moolenaar071d4272004-06-13 20:20:40 +000015670 start = *pp;
Bram Moolenaara7043832005-01-21 11:56:39 +000015671
15672 /* Check for hard coded <SNR>: already translated function ID (from a user
15673 * command). */
15674 if ((*pp)[0] == K_SPECIAL && (*pp)[1] == KS_EXTRA
15675 && (*pp)[2] == (int)KE_SNR)
15676 {
15677 *pp += 3;
15678 len = get_id_len(pp) + 3;
15679 return vim_strnsave(start, len);
15680 }
15681
15682 /* A name starting with "<SID>" or "<SNR>" is local to a script. But
15683 * don't skip over "s:", get_lval() needs it for "s:dict.func". */
Bram Moolenaar071d4272004-06-13 20:20:40 +000015684 lead = eval_fname_script(start);
Bram Moolenaara7043832005-01-21 11:56:39 +000015685 if (lead > 2)
Bram Moolenaar071d4272004-06-13 20:20:40 +000015686 start += lead;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +000015687
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000015688 end = get_lval(start, NULL, &lv, FALSE, skip, flags & TFN_QUIET);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +000015689 if (end == start)
15690 {
15691 if (!skip)
15692 EMSG(_("E129: Function name required"));
15693 goto theend;
15694 }
Bram Moolenaara7043832005-01-21 11:56:39 +000015695 if (end == NULL || (lv.ll_tv != NULL && (lead > 2 || lv.ll_range)))
Bram Moolenaar7480b5c2005-01-16 22:07:38 +000015696 {
15697 /*
15698 * Report an invalid expression in braces, unless the expression
15699 * evaluation has been cancelled due to an aborting error, an
15700 * interrupt, or an exception.
15701 */
15702 if (!aborting())
15703 {
15704 if (end != NULL)
15705 EMSG2(_(e_invarg2), start);
15706 }
15707 else
15708 *pp = find_name_end(start, NULL, NULL, TRUE);
15709 goto theend;
15710 }
15711
15712 if (lv.ll_tv != NULL)
15713 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000015714 if (fdp != NULL)
15715 {
15716 fdp->fd_dict = lv.ll_dict;
15717 fdp->fd_newkey = lv.ll_newkey;
15718 lv.ll_newkey = NULL;
15719 fdp->fd_di = lv.ll_di;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000015720 }
Bram Moolenaar7480b5c2005-01-16 22:07:38 +000015721 if (lv.ll_tv->v_type == VAR_FUNC && lv.ll_tv->vval.v_string != NULL)
15722 {
15723 name = vim_strsave(lv.ll_tv->vval.v_string);
15724 *pp = end;
15725 }
15726 else
15727 {
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000015728 if (!skip && !(flags & TFN_QUIET) && (fdp == NULL
15729 || lv.ll_dict == NULL || fdp->fd_newkey == NULL))
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000015730 EMSG(_(e_funcref));
15731 else
15732 *pp = end;
Bram Moolenaar7480b5c2005-01-16 22:07:38 +000015733 name = NULL;
15734 }
15735 goto theend;
15736 }
15737
15738 if (lv.ll_name == NULL)
15739 {
15740 /* Error found, but continue after the function name. */
15741 *pp = end;
15742 goto theend;
15743 }
15744
15745 if (lv.ll_exp_name != NULL)
15746 len = STRLEN(lv.ll_exp_name);
15747 else
Bram Moolenaara7043832005-01-21 11:56:39 +000015748 {
15749 if (lead == 2) /* skip over "s:" */
15750 lv.ll_name += 2;
15751 len = (int)(end - lv.ll_name);
15752 }
Bram Moolenaar7480b5c2005-01-16 22:07:38 +000015753
15754 /*
15755 * Copy the function name to allocated memory.
15756 * Accept <SID>name() inside a script, translate into <SNR>123_name().
15757 * Accept <SNR>123_name() outside a script.
15758 */
15759 if (skip)
15760 lead = 0; /* do nothing */
15761 else if (lead > 0)
15762 {
15763 lead = 3;
15764 if (eval_fname_sid(*pp)) /* If it's "<SID>" */
15765 {
15766 if (current_SID <= 0)
15767 {
15768 EMSG(_(e_usingsid));
15769 goto theend;
15770 }
15771 sprintf((char *)sid_buf, "%ld_", (long)current_SID);
15772 lead += (int)STRLEN(sid_buf);
15773 }
15774 }
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +000015775 else if (!(flags & TFN_INT) && builtin_function(lv.ll_name))
Bram Moolenaar7480b5c2005-01-16 22:07:38 +000015776 {
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +000015777 EMSG2(_("E128: Function name must start with a capital or contain a colon: %s"), lv.ll_name);
Bram Moolenaar7480b5c2005-01-16 22:07:38 +000015778 goto theend;
15779 }
15780 name = alloc((unsigned)(len + lead + 1));
15781 if (name != NULL)
15782 {
15783 if (lead > 0)
15784 {
15785 name[0] = K_SPECIAL;
15786 name[1] = KS_EXTRA;
15787 name[2] = (int)KE_SNR;
Bram Moolenaara7043832005-01-21 11:56:39 +000015788 if (lead > 3) /* If it's "<SID>" */
Bram Moolenaar7480b5c2005-01-16 22:07:38 +000015789 STRCPY(name + 3, sid_buf);
15790 }
15791 mch_memmove(name + lead, lv.ll_name, (size_t)len);
15792 name[len + lead] = NUL;
15793 }
15794 *pp = end;
15795
15796theend:
15797 clear_lval(&lv);
15798 return name;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015799}
15800
15801/*
15802 * Return 5 if "p" starts with "<SID>" or "<SNR>" (ignoring case).
15803 * Return 2 if "p" starts with "s:".
15804 * Return 0 otherwise.
15805 */
15806 static int
15807eval_fname_script(p)
15808 char_u *p;
15809{
15810 if (p[0] == '<' && (STRNICMP(p + 1, "SID>", 4) == 0
15811 || STRNICMP(p + 1, "SNR>", 4) == 0))
15812 return 5;
15813 if (p[0] == 's' && p[1] == ':')
15814 return 2;
15815 return 0;
15816}
15817
15818/*
15819 * Return TRUE if "p" starts with "<SID>" or "s:".
15820 * Only works if eval_fname_script() returned non-zero for "p"!
15821 */
15822 static int
15823eval_fname_sid(p)
15824 char_u *p;
15825{
15826 return (*p == 's' || TOUPPER_ASC(p[2]) == 'I');
15827}
15828
15829/*
15830 * List the head of the function: "name(arg1, arg2)".
15831 */
15832 static void
15833list_func_head(fp, indent)
15834 ufunc_T *fp;
15835 int indent;
15836{
15837 int j;
15838
15839 msg_start();
15840 if (indent)
15841 MSG_PUTS(" ");
15842 MSG_PUTS("function ");
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000015843 if (fp->uf_name[0] == K_SPECIAL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000015844 {
15845 MSG_PUTS_ATTR("<SNR>", hl_attr(HLF_8));
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000015846 msg_puts(fp->uf_name + 3);
Bram Moolenaar071d4272004-06-13 20:20:40 +000015847 }
15848 else
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000015849 msg_puts(fp->uf_name);
Bram Moolenaar071d4272004-06-13 20:20:40 +000015850 msg_putchar('(');
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000015851 for (j = 0; j < fp->uf_args.ga_len; ++j)
Bram Moolenaar071d4272004-06-13 20:20:40 +000015852 {
15853 if (j)
15854 MSG_PUTS(", ");
15855 msg_puts(FUNCARG(fp, j));
15856 }
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000015857 if (fp->uf_varargs)
Bram Moolenaar071d4272004-06-13 20:20:40 +000015858 {
15859 if (j)
15860 MSG_PUTS(", ");
15861 MSG_PUTS("...");
15862 }
15863 msg_putchar(')');
15864}
15865
15866/*
15867 * Find a function by name, return pointer to it in ufuncs.
15868 * Return NULL for unknown function.
15869 */
15870 static ufunc_T *
15871find_func(name)
15872 char_u *name;
15873{
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000015874 hashitem_T *hi;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015875
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000015876 hi = hash_find(&func_hashtab, name);
15877 if (!HASHITEM_EMPTY(hi))
15878 return HI2UF(hi);
15879 return NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015880}
15881
Bram Moolenaar49cd9572005-01-03 21:06:01 +000015882/*
15883 * Return TRUE if a function "name" exists.
15884 */
15885 static int
15886function_exists(name)
15887 char_u *name;
15888{
15889 char_u *p = name;
15890 int n = FALSE;
15891
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000015892 p = trans_function_name(&p, FALSE, TFN_INT|TFN_QUIET, NULL);
Bram Moolenaar49cd9572005-01-03 21:06:01 +000015893 if (p != NULL)
15894 {
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +000015895 if (builtin_function(p))
Bram Moolenaar49cd9572005-01-03 21:06:01 +000015896 n = (find_internal_func(p) >= 0);
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +000015897 else
15898 n = (find_func(p) != NULL);
Bram Moolenaar49cd9572005-01-03 21:06:01 +000015899 vim_free(p);
15900 }
15901 return n;
15902}
15903
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +000015904/*
15905 * Return TRUE if "name" looks like a builtin function name: starts with a
15906 * lower case letter and doesn't contain a ':'.
15907 */
15908 static int
15909builtin_function(name)
15910 char_u *name;
15911{
15912 return ASCII_ISLOWER(name[0]) && vim_strchr(name, ':') == NULL;
15913}
15914
15915/*
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000015916 * If "name" has a package name try autoloading the script for it.
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +000015917 * Return TRUE if a package was loaded.
15918 */
15919 static int
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000015920script_autoload(name)
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +000015921 char_u *name;
15922{
15923 char_u *p;
15924 char_u *scriptname;
15925 int ret = FALSE;
15926
15927 /* If there is no colon after name[1] there is no package name. */
15928 p = vim_strchr(name, ':');
15929 if (p == NULL || p <= name + 2)
15930 return FALSE;
15931
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000015932 /* Try loading the package from $VIMRUNTIME/autoload/<name>.vim */
15933 scriptname = autoload_name(name);
15934 if (cmd_runtime(scriptname, FALSE) == OK)
15935 ret = TRUE;
15936
15937 vim_free(scriptname);
15938 return ret;
15939}
15940
15941/*
15942 * Return the autoload script name for a function or variable name.
15943 * Returns NULL when out of memory.
15944 */
15945 static char_u *
15946autoload_name(name)
15947 char_u *name;
15948{
15949 char_u *p;
15950 char_u *scriptname;
15951
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +000015952 /* Get the script file name: replace ':' with '/', append ".vim". */
15953 scriptname = alloc((unsigned)(STRLEN(name) + 14));
15954 if (scriptname == NULL)
15955 return FALSE;
15956 STRCPY(scriptname, "autoload/");
15957 STRCAT(scriptname, name);
15958 *vim_strrchr(scriptname, ':') = NUL;
15959 STRCAT(scriptname, ".vim");
15960 while ((p = vim_strchr(scriptname, ':')) != NULL)
15961 *p = '/';
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000015962 return scriptname;
Bram Moolenaarb11bd7e2005-02-07 22:05:52 +000015963}
15964
Bram Moolenaar071d4272004-06-13 20:20:40 +000015965#if defined(FEAT_CMDL_COMPL) || defined(PROTO)
15966
15967/*
15968 * Function given to ExpandGeneric() to obtain the list of user defined
15969 * function names.
15970 */
15971 char_u *
15972get_user_func_name(xp, idx)
15973 expand_T *xp;
15974 int idx;
15975{
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000015976 static long_u done;
15977 static hashitem_T *hi;
15978 ufunc_T *fp;
Bram Moolenaar071d4272004-06-13 20:20:40 +000015979
15980 if (idx == 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +000015981 {
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000015982 done = 0;
15983 hi = func_hashtab.ht_array;
15984 }
15985 if (done < func_hashtab.ht_used)
15986 {
15987 if (done++ > 0)
15988 ++hi;
15989 while (HASHITEM_EMPTY(hi))
15990 ++hi;
15991 fp = HI2UF(hi);
15992
15993 if (STRLEN(fp->uf_name) + 4 >= IOSIZE)
15994 return fp->uf_name; /* prevents overflow */
Bram Moolenaar071d4272004-06-13 20:20:40 +000015995
15996 cat_func_name(IObuff, fp);
15997 if (xp->xp_context != EXPAND_USER_FUNC)
15998 {
15999 STRCAT(IObuff, "(");
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000016000 if (!fp->uf_varargs && fp->uf_args.ga_len == 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +000016001 STRCAT(IObuff, ")");
16002 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000016003 return IObuff;
16004 }
16005 return NULL;
16006}
16007
16008#endif /* FEAT_CMDL_COMPL */
16009
16010/*
16011 * Copy the function name of "fp" to buffer "buf".
16012 * "buf" must be able to hold the function name plus three bytes.
16013 * Takes care of script-local function names.
16014 */
16015 static void
16016cat_func_name(buf, fp)
16017 char_u *buf;
16018 ufunc_T *fp;
16019{
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000016020 if (fp->uf_name[0] == K_SPECIAL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000016021 {
16022 STRCPY(buf, "<SNR>");
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000016023 STRCAT(buf, fp->uf_name + 3);
Bram Moolenaar071d4272004-06-13 20:20:40 +000016024 }
16025 else
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000016026 STRCPY(buf, fp->uf_name);
Bram Moolenaar071d4272004-06-13 20:20:40 +000016027}
16028
16029/*
16030 * ":delfunction {name}"
16031 */
16032 void
16033ex_delfunction(eap)
16034 exarg_T *eap;
16035{
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000016036 ufunc_T *fp = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016037 char_u *p;
16038 char_u *name;
Bram Moolenaar33570922005-01-25 22:26:29 +000016039 funcdict_T fudi;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016040
16041 p = eap->arg;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000016042 name = trans_function_name(&p, eap->skip, 0, &fudi);
16043 vim_free(fudi.fd_newkey);
Bram Moolenaar071d4272004-06-13 20:20:40 +000016044 if (name == NULL)
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000016045 {
16046 if (fudi.fd_dict != NULL && !eap->skip)
16047 EMSG(_(e_funcref));
Bram Moolenaar071d4272004-06-13 20:20:40 +000016048 return;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000016049 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000016050 if (!ends_excmd(*skipwhite(p)))
16051 {
16052 vim_free(name);
16053 EMSG(_(e_trailing));
16054 return;
16055 }
16056 eap->nextcmd = check_nextcmd(p);
16057 if (eap->nextcmd != NULL)
16058 *p = NUL;
16059
16060 if (!eap->skip)
16061 fp = find_func(name);
16062 vim_free(name);
16063
16064 if (!eap->skip)
16065 {
16066 if (fp == NULL)
16067 {
16068 EMSG2(_("E130: Undefined function: %s"), eap->arg);
16069 return;
16070 }
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000016071 if (fp->uf_calls > 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +000016072 {
16073 EMSG2(_("E131: Cannot delete function %s: It is in use"), eap->arg);
16074 return;
16075 }
16076
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000016077 if (fudi.fd_dict != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000016078 {
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000016079 /* Delete the dict item that refers to the function, it will
16080 * invoke func_unref() and possibly delete the function. */
Bram Moolenaarce5e58e2005-01-19 22:24:34 +000016081 dictitem_remove(fudi.fd_dict, fudi.fd_di);
Bram Moolenaar071d4272004-06-13 20:20:40 +000016082 }
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000016083 else
16084 func_free(fp);
16085 }
16086}
16087
16088/*
16089 * Free a function and remove it from the list of functions.
16090 */
16091 static void
16092func_free(fp)
16093 ufunc_T *fp;
16094{
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000016095 hashitem_T *hi;
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000016096
16097 /* clear this function */
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000016098 ga_clear_strings(&(fp->uf_args));
16099 ga_clear_strings(&(fp->uf_lines));
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000016100
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000016101 /* remove the function from the function hashtable */
16102 hi = hash_find(&func_hashtab, UF2HIKEY(fp));
16103 if (HASHITEM_EMPTY(hi))
16104 EMSG2(_(e_intern2), "func_free()");
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000016105 else
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000016106 hash_remove(&func_hashtab, hi);
16107
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000016108 vim_free(fp);
16109}
16110
16111/*
16112 * Unreference a Function: decrement the reference count and free it when it
16113 * becomes zero. Only for numbered functions.
16114 */
16115 static void
16116func_unref(name)
16117 char_u *name;
16118{
16119 ufunc_T *fp;
16120
16121 if (name != NULL && isdigit(*name))
16122 {
16123 fp = find_func(name);
16124 if (fp == NULL)
16125 EMSG2(_(e_intern2), "func_unref()");
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000016126 else if (--fp->uf_refcount <= 0)
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000016127 {
16128 /* Only delete it when it's not being used. Otherwise it's done
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000016129 * when "uf_calls" becomes zero. */
16130 if (fp->uf_calls == 0)
Bram Moolenaar9ef486d2005-01-17 22:23:00 +000016131 func_free(fp);
16132 }
16133 }
16134}
16135
16136/*
16137 * Count a reference to a Function.
16138 */
16139 static void
16140func_ref(name)
16141 char_u *name;
16142{
16143 ufunc_T *fp;
16144
16145 if (name != NULL && isdigit(*name))
16146 {
16147 fp = find_func(name);
16148 if (fp == NULL)
16149 EMSG2(_(e_intern2), "func_ref()");
16150 else
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000016151 ++fp->uf_refcount;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016152 }
16153}
16154
16155/*
16156 * Call a user function.
16157 */
16158 static void
Bram Moolenaare9a41262005-01-15 22:18:47 +000016159call_user_func(fp, argcount, argvars, rettv, firstline, lastline, selfdict)
Bram Moolenaar071d4272004-06-13 20:20:40 +000016160 ufunc_T *fp; /* pointer to function */
16161 int argcount; /* nr of args */
Bram Moolenaar33570922005-01-25 22:26:29 +000016162 typval_T *argvars; /* arguments */
16163 typval_T *rettv; /* return value */
Bram Moolenaar071d4272004-06-13 20:20:40 +000016164 linenr_T firstline; /* first line of range */
16165 linenr_T lastline; /* last line of range */
Bram Moolenaar33570922005-01-25 22:26:29 +000016166 dict_T *selfdict; /* Dictionary for "self" */
Bram Moolenaar071d4272004-06-13 20:20:40 +000016167{
Bram Moolenaar33570922005-01-25 22:26:29 +000016168 char_u *save_sourcing_name;
16169 linenr_T save_sourcing_lnum;
16170 scid_T save_current_SID;
16171 funccall_T fc;
16172 funccall_T *save_fcp = current_funccal;
16173 int save_did_emsg;
16174 static int depth = 0;
16175 dictitem_T *v;
16176 int fixvar_idx = 0; /* index in fixvar[] */
16177 int i;
16178 int ai;
16179 char_u numbuf[NUMBUFLEN];
16180 char_u *name;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016181
16182 /* If depth of calling is getting too high, don't execute the function */
16183 if (depth >= p_mfd)
16184 {
16185 EMSG(_("E132: Function call depth is higher than 'maxfuncdepth'"));
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016186 rettv->v_type = VAR_NUMBER;
16187 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016188 return;
16189 }
16190 ++depth;
16191
16192 line_breakcheck(); /* check for CTRL-C hit */
16193
Bram Moolenaar33570922005-01-25 22:26:29 +000016194 current_funccal = &fc;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016195 fc.func = fp;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016196 fc.rettv = rettv;
16197 rettv->vval.v_number = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016198 fc.linenr = 0;
16199 fc.returned = FALSE;
16200 fc.level = ex_nesting_level;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016201 /* Check if this function has a breakpoint. */
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000016202 fc.breakpoint = dbg_find_breakpoint(FALSE, fp->uf_name, (linenr_T)0);
Bram Moolenaar071d4272004-06-13 20:20:40 +000016203 fc.dbg_tick = debug_tick;
16204
Bram Moolenaar33570922005-01-25 22:26:29 +000016205 /*
16206 * Note about using fc.fixvar[]: This is an array of FIXVAR_CNT variables
16207 * with names up to VAR_SHORT_LEN long. This avoids having to alloc/free
16208 * each argument variable and saves a lot of time.
16209 */
16210 /*
16211 * Init l: variables.
16212 */
16213 init_var_dict(&fc.l_vars, &fc.l_vars_var);
Bram Moolenaara7043832005-01-21 11:56:39 +000016214 if (selfdict != NULL)
Bram Moolenaare9a41262005-01-15 22:18:47 +000016215 {
Bram Moolenaar33570922005-01-25 22:26:29 +000016216 /* Set l:self to "selfdict". */
16217 v = &fc.fixvar[fixvar_idx++].var;
16218 STRCPY(v->di_key, "self");
16219 v->di_flags = DI_FLAGS_RO + DI_FLAGS_FIX;
16220 hash_add(&fc.l_vars.dv_hashtab, DI2HIKEY(v));
16221 v->di_tv.v_type = VAR_DICT;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000016222 v->di_tv.v_lock = 0;
Bram Moolenaar33570922005-01-25 22:26:29 +000016223 v->di_tv.vval.v_dict = selfdict;
16224 ++selfdict->dv_refcount;
16225 }
Bram Moolenaare9a41262005-01-15 22:18:47 +000016226
Bram Moolenaar33570922005-01-25 22:26:29 +000016227 /*
16228 * Init a: variables.
16229 * Set a:0 to "argcount".
16230 * Set a:000 to a list with room for the "..." arguments.
16231 */
16232 init_var_dict(&fc.l_avars, &fc.l_avars_var);
16233 add_nr_var(&fc.l_avars, &fc.fixvar[fixvar_idx++].var, "0",
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000016234 (varnumber_T)(argcount - fp->uf_args.ga_len));
Bram Moolenaar33570922005-01-25 22:26:29 +000016235 v = &fc.fixvar[fixvar_idx++].var;
16236 STRCPY(v->di_key, "000");
16237 v->di_flags = DI_FLAGS_RO | DI_FLAGS_FIX;
16238 hash_add(&fc.l_avars.dv_hashtab, DI2HIKEY(v));
16239 v->di_tv.v_type = VAR_LIST;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000016240 v->di_tv.v_lock = VAR_FIXED;
Bram Moolenaar33570922005-01-25 22:26:29 +000016241 v->di_tv.vval.v_list = &fc.l_varlist;
16242 vim_memset(&fc.l_varlist, 0, sizeof(list_T));
16243 fc.l_varlist.lv_refcount = 99999;
16244
16245 /*
16246 * Set a:firstline to "firstline" and a:lastline to "lastline".
16247 * Set a:name to named arguments.
16248 * Set a:N to the "..." arguments.
16249 */
16250 add_nr_var(&fc.l_avars, &fc.fixvar[fixvar_idx++].var, "firstline",
16251 (varnumber_T)firstline);
16252 add_nr_var(&fc.l_avars, &fc.fixvar[fixvar_idx++].var, "lastline",
16253 (varnumber_T)lastline);
16254 for (i = 0; i < argcount; ++i)
16255 {
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000016256 ai = i - fp->uf_args.ga_len;
Bram Moolenaar33570922005-01-25 22:26:29 +000016257 if (ai < 0)
16258 /* named argument a:name */
16259 name = FUNCARG(fp, i);
16260 else
Bram Moolenaare9a41262005-01-15 22:18:47 +000016261 {
Bram Moolenaar33570922005-01-25 22:26:29 +000016262 /* "..." argument a:1, a:2, etc. */
16263 sprintf((char *)numbuf, "%d", ai + 1);
16264 name = numbuf;
16265 }
16266 if (fixvar_idx < FIXVAR_CNT && STRLEN(name) <= VAR_SHORT_LEN)
16267 {
16268 v = &fc.fixvar[fixvar_idx++].var;
16269 v->di_flags = DI_FLAGS_RO | DI_FLAGS_FIX;
16270 }
16271 else
16272 {
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000016273 v = (dictitem_T *)alloc((unsigned)(sizeof(dictitem_T)
16274 + STRLEN(name)));
Bram Moolenaar33570922005-01-25 22:26:29 +000016275 if (v == NULL)
16276 break;
16277 v->di_flags = DI_FLAGS_RO;
16278 }
16279 STRCPY(v->di_key, name);
16280 hash_add(&fc.l_avars.dv_hashtab, DI2HIKEY(v));
16281
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000016282 /* Note: the values are copied directly to avoid alloc/free.
16283 * "argvars" must have VAR_FIXED for v_lock. */
Bram Moolenaar33570922005-01-25 22:26:29 +000016284 v->di_tv = argvars[i];
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000016285 v->di_tv.v_lock = VAR_FIXED;
Bram Moolenaar33570922005-01-25 22:26:29 +000016286
16287 if (ai >= 0 && ai < MAX_FUNC_ARGS)
16288 {
16289 list_append(&fc.l_varlist, &fc.l_listitems[ai]);
16290 fc.l_listitems[ai].li_tv = argvars[i];
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000016291 fc.l_listitems[ai].li_tv.v_lock = VAR_FIXED;
Bram Moolenaare9a41262005-01-15 22:18:47 +000016292 }
16293 }
16294
Bram Moolenaar071d4272004-06-13 20:20:40 +000016295 /* Don't redraw while executing the function. */
16296 ++RedrawingDisabled;
16297 save_sourcing_name = sourcing_name;
16298 save_sourcing_lnum = sourcing_lnum;
16299 sourcing_lnum = 1;
16300 sourcing_name = alloc((unsigned)((save_sourcing_name == NULL ? 0
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000016301 : STRLEN(save_sourcing_name)) + STRLEN(fp->uf_name) + 13));
Bram Moolenaar071d4272004-06-13 20:20:40 +000016302 if (sourcing_name != NULL)
16303 {
16304 if (save_sourcing_name != NULL
16305 && STRNCMP(save_sourcing_name, "function ", 9) == 0)
16306 sprintf((char *)sourcing_name, "%s..", save_sourcing_name);
16307 else
16308 STRCPY(sourcing_name, "function ");
16309 cat_func_name(sourcing_name + STRLEN(sourcing_name), fp);
16310
16311 if (p_verbose >= 12)
16312 {
16313 ++no_wait_return;
16314 msg_scroll = TRUE; /* always scroll up, don't overwrite */
16315 msg_str((char_u *)_("calling %s"), sourcing_name);
16316 if (p_verbose >= 14)
16317 {
Bram Moolenaar071d4272004-06-13 20:20:40 +000016318 char_u buf[MSG_BUF_LEN];
Bram Moolenaar758711c2005-02-02 23:11:38 +000016319 char_u numbuf[NUMBUFLEN];
16320 char_u *tofree;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016321
16322 msg_puts((char_u *)"(");
16323 for (i = 0; i < argcount; ++i)
16324 {
16325 if (i > 0)
16326 msg_puts((char_u *)", ");
Bram Moolenaar49cd9572005-01-03 21:06:01 +000016327 if (argvars[i].v_type == VAR_NUMBER)
16328 msg_outnum((long)argvars[i].vval.v_number);
Bram Moolenaar071d4272004-06-13 20:20:40 +000016329 else
16330 {
Bram Moolenaar758711c2005-02-02 23:11:38 +000016331 trunc_string(tv2string(&argvars[i], &tofree, numbuf),
Bram Moolenaar071d4272004-06-13 20:20:40 +000016332 buf, MSG_BUF_LEN);
Bram Moolenaar071d4272004-06-13 20:20:40 +000016333 msg_puts(buf);
Bram Moolenaar758711c2005-02-02 23:11:38 +000016334 vim_free(tofree);
Bram Moolenaar071d4272004-06-13 20:20:40 +000016335 }
16336 }
16337 msg_puts((char_u *)")");
16338 }
16339 msg_puts((char_u *)"\n"); /* don't overwrite this either */
16340 cmdline_row = msg_row;
16341 --no_wait_return;
16342 }
16343 }
16344 save_current_SID = current_SID;
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000016345 current_SID = fp->uf_script_ID;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016346 save_did_emsg = did_emsg;
16347 did_emsg = FALSE;
16348
16349 /* call do_cmdline() to execute the lines */
16350 do_cmdline(NULL, get_func_line, (void *)&fc,
16351 DOCMD_NOWAIT|DOCMD_VERBOSE|DOCMD_REPEAT);
16352
16353 --RedrawingDisabled;
16354
16355 /* when the function was aborted because of an error, return -1 */
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000016356 if ((did_emsg && (fp->uf_flags & FC_ABORT)) || rettv->v_type == VAR_UNKNOWN)
Bram Moolenaar071d4272004-06-13 20:20:40 +000016357 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016358 clear_tv(rettv);
16359 rettv->v_type = VAR_NUMBER;
16360 rettv->vval.v_number = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016361 }
16362
16363 /* when being verbose, mention the return value */
16364 if (p_verbose >= 12)
16365 {
Bram Moolenaar758711c2005-02-02 23:11:38 +000016366 char_u *sn;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016367
16368 ++no_wait_return;
16369 msg_scroll = TRUE; /* always scroll up, don't overwrite */
16370
16371 /* Make sure the output fits in IObuff. */
16372 sn = sourcing_name;
16373 if (STRLEN(sourcing_name) > IOSIZE / 2 - 50)
16374 sn = sourcing_name + STRLEN(sourcing_name) - (IOSIZE / 2 - 50);
16375
16376 if (aborting())
16377 smsg((char_u *)_("%s aborted"), sn);
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016378 else if (fc.rettv->v_type == VAR_NUMBER)
Bram Moolenaar071d4272004-06-13 20:20:40 +000016379 smsg((char_u *)_("%s returning #%ld"), sn,
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016380 (long)fc.rettv->vval.v_number);
Bram Moolenaar758711c2005-02-02 23:11:38 +000016381 else
Bram Moolenaar071d4272004-06-13 20:20:40 +000016382 {
Bram Moolenaar758711c2005-02-02 23:11:38 +000016383 char_u buf[MSG_BUF_LEN];
16384 char_u numbuf[NUMBUFLEN];
16385 char_u *tofree;
16386
16387 trunc_string(tv2string(fc.rettv, &tofree, numbuf),
16388 buf, MSG_BUF_LEN);
16389 smsg((char_u *)_("%s returning %s"), sn, buf);
16390 vim_free(tofree);
Bram Moolenaar071d4272004-06-13 20:20:40 +000016391 }
16392 msg_puts((char_u *)"\n"); /* don't overwrite this either */
16393 cmdline_row = msg_row;
16394 --no_wait_return;
16395 }
16396
16397 vim_free(sourcing_name);
16398 sourcing_name = save_sourcing_name;
16399 sourcing_lnum = save_sourcing_lnum;
16400 current_SID = save_current_SID;
16401
16402 if (p_verbose >= 12 && sourcing_name != NULL)
16403 {
16404 ++no_wait_return;
16405 msg_scroll = TRUE; /* always scroll up, don't overwrite */
16406 msg_str((char_u *)_("continuing in %s"), sourcing_name);
16407 msg_puts((char_u *)"\n"); /* don't overwrite this either */
16408 cmdline_row = msg_row;
16409 --no_wait_return;
16410 }
16411
16412 did_emsg |= save_did_emsg;
16413 current_funccal = save_fcp;
16414
Bram Moolenaar33570922005-01-25 22:26:29 +000016415 /* The a: variables typevals were not alloced, only free the allocated
16416 * variables. */
16417 vars_clear_ext(&fc.l_avars.dv_hashtab, FALSE);
16418
16419 vars_clear(&fc.l_vars.dv_hashtab); /* free all l: variables */
Bram Moolenaar071d4272004-06-13 20:20:40 +000016420 --depth;
16421}
16422
16423/*
Bram Moolenaar33570922005-01-25 22:26:29 +000016424 * Add a number variable "name" to dict "dp" with value "nr".
16425 */
16426 static void
16427add_nr_var(dp, v, name, nr)
16428 dict_T *dp;
16429 dictitem_T *v;
16430 char *name;
16431 varnumber_T nr;
16432{
16433 STRCPY(v->di_key, name);
16434 v->di_flags = DI_FLAGS_RO | DI_FLAGS_FIX;
16435 hash_add(&dp->dv_hashtab, DI2HIKEY(v));
16436 v->di_tv.v_type = VAR_NUMBER;
Bram Moolenaar2e6aff32005-01-31 19:25:36 +000016437 v->di_tv.v_lock = VAR_FIXED;
Bram Moolenaar33570922005-01-25 22:26:29 +000016438 v->di_tv.vval.v_number = nr;
16439}
16440
16441/*
Bram Moolenaar071d4272004-06-13 20:20:40 +000016442 * ":return [expr]"
16443 */
16444 void
16445ex_return(eap)
16446 exarg_T *eap;
16447{
16448 char_u *arg = eap->arg;
Bram Moolenaar33570922005-01-25 22:26:29 +000016449 typval_T rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016450 int returning = FALSE;
16451
16452 if (current_funccal == NULL)
16453 {
16454 EMSG(_("E133: :return not inside a function"));
16455 return;
16456 }
16457
16458 if (eap->skip)
16459 ++emsg_skip;
16460
16461 eap->nextcmd = NULL;
16462 if ((*arg != NUL && *arg != '|' && *arg != '\n')
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016463 && eval0(arg, &rettv, &eap->nextcmd, !eap->skip) != FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000016464 {
16465 if (!eap->skip)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016466 returning = do_return(eap, FALSE, TRUE, &rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000016467 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016468 clear_tv(&rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000016469 }
16470 /* It's safer to return also on error. */
16471 else if (!eap->skip)
16472 {
16473 /*
16474 * Return unless the expression evaluation has been cancelled due to an
16475 * aborting error, an interrupt, or an exception.
16476 */
16477 if (!aborting())
16478 returning = do_return(eap, FALSE, TRUE, NULL);
16479 }
16480
16481 /* When skipping or the return gets pending, advance to the next command
16482 * in this line (!returning). Otherwise, ignore the rest of the line.
16483 * Following lines will be ignored by get_func_line(). */
16484 if (returning)
16485 eap->nextcmd = NULL;
16486 else if (eap->nextcmd == NULL) /* no argument */
16487 eap->nextcmd = check_nextcmd(arg);
16488
16489 if (eap->skip)
16490 --emsg_skip;
16491}
16492
16493/*
16494 * Return from a function. Possibly makes the return pending. Also called
16495 * for a pending return at the ":endtry" or after returning from an extra
16496 * do_cmdline(). "reanimate" is used in the latter case. "is_cmd" is set
Bram Moolenaar33570922005-01-25 22:26:29 +000016497 * when called due to a ":return" command. "rettv" may point to a typval_T
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016498 * with the return rettv. Returns TRUE when the return can be carried out,
Bram Moolenaar071d4272004-06-13 20:20:40 +000016499 * FALSE when the return gets pending.
16500 */
16501 int
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016502do_return(eap, reanimate, is_cmd, rettv)
Bram Moolenaar071d4272004-06-13 20:20:40 +000016503 exarg_T *eap;
16504 int reanimate;
16505 int is_cmd;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016506 void *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016507{
16508 int idx;
16509 struct condstack *cstack = eap->cstack;
16510
16511 if (reanimate)
16512 /* Undo the return. */
16513 current_funccal->returned = FALSE;
16514
16515 /*
16516 * Cleanup (and inactivate) conditionals, but stop when a try conditional
16517 * not in its finally clause (which then is to be executed next) is found.
16518 * In this case, make the ":return" pending for execution at the ":endtry".
16519 * Otherwise, return normally.
16520 */
16521 idx = cleanup_conditionals(eap->cstack, 0, TRUE);
16522 if (idx >= 0)
16523 {
16524 cstack->cs_pending[idx] = CSTP_RETURN;
16525
16526 if (!is_cmd && !reanimate)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016527 /* A pending return again gets pending. "rettv" points to an
16528 * allocated variable with the rettv of the original ":return"'s
Bram Moolenaar071d4272004-06-13 20:20:40 +000016529 * argument if present or is NULL else. */
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016530 cstack->cs_rettv[idx] = rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016531 else
16532 {
16533 /* When undoing a return in order to make it pending, get the stored
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016534 * return rettv. */
Bram Moolenaar071d4272004-06-13 20:20:40 +000016535 if (reanimate)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016536 rettv = current_funccal->rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016537
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016538 if (rettv != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000016539 {
16540 /* Store the value of the pending return. */
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016541 if ((cstack->cs_rettv[idx] = alloc_tv()) != NULL)
Bram Moolenaar33570922005-01-25 22:26:29 +000016542 *(typval_T *)cstack->cs_rettv[idx] = *(typval_T *)rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016543 else
16544 EMSG(_(e_outofmem));
16545 }
16546 else
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016547 cstack->cs_rettv[idx] = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016548
16549 if (reanimate)
16550 {
16551 /* The pending return value could be overwritten by a ":return"
16552 * without argument in a finally clause; reset the default
16553 * return value. */
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016554 current_funccal->rettv->v_type = VAR_NUMBER;
16555 current_funccal->rettv->vval.v_number = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016556 }
16557 }
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016558 report_make_pending(CSTP_RETURN, rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000016559 }
16560 else
16561 {
16562 current_funccal->returned = TRUE;
16563
16564 /* If the return is carried out now, store the return value. For
16565 * a return immediately after reanimation, the value is already
16566 * there. */
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016567 if (!reanimate && rettv != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +000016568 {
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016569 clear_tv(current_funccal->rettv);
Bram Moolenaar33570922005-01-25 22:26:29 +000016570 *current_funccal->rettv = *(typval_T *)rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016571 if (!is_cmd)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016572 vim_free(rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000016573 }
16574 }
16575
16576 return idx < 0;
16577}
16578
16579/*
16580 * Free the variable with a pending return value.
16581 */
16582 void
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016583discard_pending_return(rettv)
16584 void *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016585{
Bram Moolenaar33570922005-01-25 22:26:29 +000016586 free_tv((typval_T *)rettv);
Bram Moolenaar071d4272004-06-13 20:20:40 +000016587}
16588
16589/*
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016590 * Generate a return command for producing the value of "rettv". The result
Bram Moolenaar071d4272004-06-13 20:20:40 +000016591 * is an allocated string. Used by report_pending() for verbose messages.
16592 */
16593 char_u *
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016594get_return_cmd(rettv)
16595 void *rettv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016596{
Bram Moolenaar81bf7082005-02-12 14:31:42 +000016597 char_u *s = NULL;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016598 char_u *tofree = NULL;
Bram Moolenaar8a283e52005-01-06 23:28:25 +000016599 char_u numbuf[NUMBUFLEN];
Bram Moolenaar071d4272004-06-13 20:20:40 +000016600
Bram Moolenaar81bf7082005-02-12 14:31:42 +000016601 if (rettv != NULL)
Bram Moolenaar33570922005-01-25 22:26:29 +000016602 s = echo_string((typval_T *)rettv, &tofree, numbuf);
Bram Moolenaar81bf7082005-02-12 14:31:42 +000016603 if (s == NULL)
16604 s = (char_u *)"";
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016605
16606 STRCPY(IObuff, ":return ");
16607 STRNCPY(IObuff + 8, s, IOSIZE - 8);
16608 if (STRLEN(s) + 8 >= IOSIZE)
16609 STRCPY(IObuff + IOSIZE - 4, "...");
16610 vim_free(tofree);
16611 return vim_strsave(IObuff);
Bram Moolenaar071d4272004-06-13 20:20:40 +000016612}
16613
16614/*
16615 * Get next function line.
16616 * Called by do_cmdline() to get the next line.
16617 * Returns allocated string, or NULL for end of function.
16618 */
16619/* ARGSUSED */
16620 char_u *
16621get_func_line(c, cookie, indent)
16622 int c; /* not used */
16623 void *cookie;
16624 int indent; /* not used */
16625{
Bram Moolenaar33570922005-01-25 22:26:29 +000016626 funccall_T *fcp = (funccall_T *)cookie;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016627 char_u *retval;
16628 garray_T *gap; /* growarray with function lines */
16629
16630 /* If breakpoints have been added/deleted need to check for it. */
16631 if (fcp->dbg_tick != debug_tick)
16632 {
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000016633 fcp->breakpoint = dbg_find_breakpoint(FALSE, fcp->func->uf_name,
Bram Moolenaar071d4272004-06-13 20:20:40 +000016634 sourcing_lnum);
16635 fcp->dbg_tick = debug_tick;
16636 }
16637
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000016638 gap = &fcp->func->uf_lines;
16639 if ((fcp->func->uf_flags & FC_ABORT) && did_emsg && !aborted_in_try())
Bram Moolenaar071d4272004-06-13 20:20:40 +000016640 retval = NULL;
16641 else if (fcp->returned || fcp->linenr >= gap->ga_len)
16642 retval = NULL;
16643 else
16644 {
16645 retval = vim_strsave(((char_u **)(gap->ga_data))[fcp->linenr++]);
16646 sourcing_lnum = fcp->linenr;
16647 }
16648
16649 /* Did we encounter a breakpoint? */
16650 if (fcp->breakpoint != 0 && fcp->breakpoint <= sourcing_lnum)
16651 {
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000016652 dbg_breakpoint(fcp->func->uf_name, sourcing_lnum);
Bram Moolenaar071d4272004-06-13 20:20:40 +000016653 /* Find next breakpoint. */
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000016654 fcp->breakpoint = dbg_find_breakpoint(FALSE, fcp->func->uf_name,
Bram Moolenaar071d4272004-06-13 20:20:40 +000016655 sourcing_lnum);
16656 fcp->dbg_tick = debug_tick;
16657 }
16658
16659 return retval;
16660}
16661
16662/*
16663 * Return TRUE if the currently active function should be ended, because a
16664 * return was encountered or an error occured. Used inside a ":while".
16665 */
16666 int
16667func_has_ended(cookie)
16668 void *cookie;
16669{
Bram Moolenaar33570922005-01-25 22:26:29 +000016670 funccall_T *fcp = (funccall_T *)cookie;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016671
16672 /* Ignore the "abort" flag if the abortion behavior has been changed due to
16673 * an error inside a try conditional. */
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000016674 return (((fcp->func->uf_flags & FC_ABORT) && did_emsg && !aborted_in_try())
Bram Moolenaar071d4272004-06-13 20:20:40 +000016675 || fcp->returned);
16676}
16677
16678/*
16679 * return TRUE if cookie indicates a function which "abort"s on errors.
16680 */
16681 int
16682func_has_abort(cookie)
16683 void *cookie;
16684{
Bram Moolenaar5313dcb2005-02-22 08:56:13 +000016685 return ((funccall_T *)cookie)->func->uf_flags & FC_ABORT;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016686}
16687
16688#if defined(FEAT_VIMINFO) || defined(FEAT_SESSION)
16689typedef enum
16690{
16691 VAR_FLAVOUR_DEFAULT,
16692 VAR_FLAVOUR_SESSION,
16693 VAR_FLAVOUR_VIMINFO
16694} var_flavour_T;
16695
16696static var_flavour_T var_flavour __ARGS((char_u *varname));
16697
16698 static var_flavour_T
16699var_flavour(varname)
16700 char_u *varname;
16701{
16702 char_u *p = varname;
16703
16704 if (ASCII_ISUPPER(*p))
16705 {
16706 while (*(++p))
16707 if (ASCII_ISLOWER(*p))
16708 return VAR_FLAVOUR_SESSION;
16709 return VAR_FLAVOUR_VIMINFO;
16710 }
16711 else
16712 return VAR_FLAVOUR_DEFAULT;
16713}
16714#endif
16715
16716#if defined(FEAT_VIMINFO) || defined(PROTO)
16717/*
16718 * Restore global vars that start with a capital from the viminfo file
16719 */
16720 int
16721read_viminfo_varlist(virp, writing)
16722 vir_T *virp;
16723 int writing;
16724{
16725 char_u *tab;
16726 int is_string = FALSE;
Bram Moolenaar33570922005-01-25 22:26:29 +000016727 typval_T tv;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016728
16729 if (!writing && (find_viminfo_parameter('!') != NULL))
16730 {
16731 tab = vim_strchr(virp->vir_line + 1, '\t');
16732 if (tab != NULL)
16733 {
16734 *tab++ = '\0'; /* isolate the variable name */
16735 if (*tab == 'S') /* string var */
16736 is_string = TRUE;
16737
16738 tab = vim_strchr(tab, '\t');
16739 if (tab != NULL)
16740 {
Bram Moolenaar071d4272004-06-13 20:20:40 +000016741 if (is_string)
16742 {
Bram Moolenaar3d60ec22005-01-05 22:19:46 +000016743 tv.v_type = VAR_STRING;
16744 tv.vval.v_string = viminfo_readstring(virp,
Bram Moolenaar071d4272004-06-13 20:20:40 +000016745 (int)(tab - virp->vir_line + 1), TRUE);
Bram Moolenaar071d4272004-06-13 20:20:40 +000016746 }
16747 else
16748 {
Bram Moolenaar3d60ec22005-01-05 22:19:46 +000016749 tv.v_type = VAR_NUMBER;
16750 tv.vval.v_number = atol((char *)tab + 1);
Bram Moolenaar071d4272004-06-13 20:20:40 +000016751 }
Bram Moolenaar3d60ec22005-01-05 22:19:46 +000016752 set_var(virp->vir_line + 1, &tv, FALSE);
16753 if (is_string)
16754 vim_free(tv.vval.v_string);
Bram Moolenaar071d4272004-06-13 20:20:40 +000016755 }
16756 }
16757 }
16758
16759 return viminfo_readline(virp);
16760}
16761
16762/*
16763 * Write global vars that start with a capital to the viminfo file
16764 */
16765 void
16766write_viminfo_varlist(fp)
16767 FILE *fp;
16768{
Bram Moolenaar33570922005-01-25 22:26:29 +000016769 hashitem_T *hi;
16770 dictitem_T *this_var;
Bram Moolenaara7043832005-01-21 11:56:39 +000016771 int todo;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016772 char *s;
Bram Moolenaar81bf7082005-02-12 14:31:42 +000016773 char_u *p;
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016774 char_u *tofree;
Bram Moolenaar8a283e52005-01-06 23:28:25 +000016775 char_u numbuf[NUMBUFLEN];
Bram Moolenaar071d4272004-06-13 20:20:40 +000016776
16777 if (find_viminfo_parameter('!') == NULL)
16778 return;
16779
16780 fprintf(fp, _("\n# global variables:\n"));
Bram Moolenaara7043832005-01-21 11:56:39 +000016781
Bram Moolenaar33570922005-01-25 22:26:29 +000016782 todo = globvarht.ht_used;
16783 for (hi = globvarht.ht_array; todo > 0; ++hi)
Bram Moolenaar071d4272004-06-13 20:20:40 +000016784 {
Bram Moolenaara7043832005-01-21 11:56:39 +000016785 if (!HASHITEM_EMPTY(hi))
Bram Moolenaar071d4272004-06-13 20:20:40 +000016786 {
Bram Moolenaara7043832005-01-21 11:56:39 +000016787 --todo;
Bram Moolenaar33570922005-01-25 22:26:29 +000016788 this_var = HI2DI(hi);
16789 if (var_flavour(this_var->di_key) == VAR_FLAVOUR_VIMINFO)
Bram Moolenaarc70646c2005-01-04 21:52:38 +000016790 {
Bram Moolenaar33570922005-01-25 22:26:29 +000016791 switch (this_var->di_tv.v_type)
Bram Moolenaara7043832005-01-21 11:56:39 +000016792 {
16793 case VAR_STRING: s = "STR"; break;
16794 case VAR_NUMBER: s = "NUM"; break;
16795 default: continue;
16796 }
Bram Moolenaar33570922005-01-25 22:26:29 +000016797 fprintf(fp, "!%s\t%s\t", this_var->di_key, s);
Bram Moolenaar81bf7082005-02-12 14:31:42 +000016798 p = echo_string(&this_var->di_tv, &tofree, numbuf);
16799 if (p != NULL)
16800 viminfo_writestring(fp, p);
Bram Moolenaara7043832005-01-21 11:56:39 +000016801 vim_free(tofree);
16802 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000016803 }
16804 }
16805}
16806#endif
16807
16808#if defined(FEAT_SESSION) || defined(PROTO)
16809 int
16810store_session_globals(fd)
16811 FILE *fd;
16812{
Bram Moolenaar33570922005-01-25 22:26:29 +000016813 hashitem_T *hi;
16814 dictitem_T *this_var;
Bram Moolenaara7043832005-01-21 11:56:39 +000016815 int todo;
Bram Moolenaar071d4272004-06-13 20:20:40 +000016816 char_u *p, *t;
16817
Bram Moolenaar33570922005-01-25 22:26:29 +000016818 todo = globvarht.ht_used;
16819 for (hi = globvarht.ht_array; todo > 0; ++hi)
Bram Moolenaar071d4272004-06-13 20:20:40 +000016820 {
Bram Moolenaara7043832005-01-21 11:56:39 +000016821 if (!HASHITEM_EMPTY(hi))
Bram Moolenaar071d4272004-06-13 20:20:40 +000016822 {
Bram Moolenaara7043832005-01-21 11:56:39 +000016823 --todo;
Bram Moolenaar33570922005-01-25 22:26:29 +000016824 this_var = HI2DI(hi);
16825 if ((this_var->di_tv.v_type == VAR_NUMBER
16826 || this_var->di_tv.v_type == VAR_STRING)
16827 && var_flavour(this_var->di_key) == VAR_FLAVOUR_SESSION)
Bram Moolenaar3d60ec22005-01-05 22:19:46 +000016828 {
Bram Moolenaara7043832005-01-21 11:56:39 +000016829 /* Escape special characters with a backslash. Turn a LF and
16830 * CR into \n and \r. */
Bram Moolenaar33570922005-01-25 22:26:29 +000016831 p = vim_strsave_escaped(get_tv_string(&this_var->di_tv),
Bram Moolenaara7043832005-01-21 11:56:39 +000016832 (char_u *)"\\\"\n\r");
16833 if (p == NULL) /* out of memory */
16834 break;
16835 for (t = p; *t != NUL; ++t)
16836 if (*t == '\n')
16837 *t = 'n';
16838 else if (*t == '\r')
16839 *t = 'r';
16840 if ((fprintf(fd, "let %s = %c%s%c",
Bram Moolenaar33570922005-01-25 22:26:29 +000016841 this_var->di_key,
16842 (this_var->di_tv.v_type == VAR_STRING) ? '"'
16843 : ' ',
16844 p,
16845 (this_var->di_tv.v_type == VAR_STRING) ? '"'
16846 : ' ') < 0)
Bram Moolenaara7043832005-01-21 11:56:39 +000016847 || put_eol(fd) == FAIL)
16848 {
16849 vim_free(p);
16850 return FAIL;
16851 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000016852 vim_free(p);
16853 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000016854 }
16855 }
16856 return OK;
16857}
16858#endif
16859
16860#endif /* FEAT_EVAL */
16861
16862#if defined(FEAT_MODIFY_FNAME) || defined(FEAT_EVAL) || defined(PROTO)
16863
16864
16865#ifdef WIN3264
16866/*
16867 * Functions for ":8" filename modifier: get 8.3 version of a filename.
16868 */
16869static int get_short_pathname __ARGS((char_u **fnamep, char_u **bufp, int *fnamelen));
16870static int shortpath_for_invalid_fname __ARGS((char_u **fname, char_u **bufp, int *fnamelen));
16871static int shortpath_for_partial __ARGS((char_u **fnamep, char_u **bufp, int *fnamelen));
16872
16873/*
16874 * Get the short pathname of a file.
16875 * Returns 1 on success. *fnamelen is 0 for nonexistant path.
16876 */
16877 static int
16878get_short_pathname(fnamep, bufp, fnamelen)
16879 char_u **fnamep;
16880 char_u **bufp;
16881 int *fnamelen;
16882{
16883 int l,len;
16884 char_u *newbuf;
16885
16886 len = *fnamelen;
16887
16888 l = GetShortPathName(*fnamep, *fnamep, len);
16889 if (l > len - 1)
16890 {
16891 /* If that doesn't work (not enough space), then save the string
16892 * and try again with a new buffer big enough
16893 */
16894 newbuf = vim_strnsave(*fnamep, l);
16895 if (newbuf == NULL)
16896 return 0;
16897
16898 vim_free(*bufp);
16899 *fnamep = *bufp = newbuf;
16900
16901 l = GetShortPathName(*fnamep,*fnamep,l+1);
16902
16903 /* Really should always succeed, as the buffer is big enough */
16904 }
16905
16906 *fnamelen = l;
16907 return 1;
16908}
16909
16910/*
16911 * Create a short path name. Returns the length of the buffer it needs.
16912 * Doesn't copy over the end of the buffer passed in.
16913 */
16914 static int
16915shortpath_for_invalid_fname(fname, bufp, fnamelen)
16916 char_u **fname;
16917 char_u **bufp;
16918 int *fnamelen;
16919{
16920 char_u *s, *p, *pbuf2, *pbuf3;
16921 char_u ch;
16922 int l,len,len2,plen,slen;
16923
16924 /* Make a copy */
16925 len2 = *fnamelen;
16926 pbuf2 = vim_strnsave(*fname, len2);
16927 pbuf3 = NULL;
16928
16929 s = pbuf2 + len2 - 1; /* Find the end */
16930 slen = 1;
16931 plen = len2;
16932
16933 l = 0;
Bram Moolenaar1cd871b2004-12-19 22:46:22 +000016934 if (after_pathsep(pbuf2, s + 1))
Bram Moolenaar071d4272004-06-13 20:20:40 +000016935 {
16936 --s;
16937 ++slen;
16938 --plen;
16939 }
16940
16941 do
16942 {
16943 /* Go back one path-seperator */
Bram Moolenaar1cd871b2004-12-19 22:46:22 +000016944 while (s > pbuf2 && !after_pathsep(pbuf2, s + 1))
Bram Moolenaar071d4272004-06-13 20:20:40 +000016945 {
16946 --s;
16947 ++slen;
16948 --plen;
16949 }
16950 if (s <= pbuf2)
16951 break;
16952
16953 /* Remeber the character that is about to be blatted */
16954 ch = *s;
16955 *s = 0; /* get_short_pathname requires a null-terminated string */
16956
16957 /* Try it in situ */
16958 p = pbuf2;
16959 if (!get_short_pathname(&p, &pbuf3, &plen))
16960 {
16961 vim_free(pbuf2);
16962 return -1;
16963 }
16964 *s = ch; /* Preserve the string */
16965 } while (plen == 0);
16966
16967 if (plen > 0)
16968 {
16969 /* Remeber the length of the new string. */
16970 *fnamelen = len = plen + slen;
16971 vim_free(*bufp);
16972 if (len > len2)
16973 {
16974 /* If there's not enough space in the currently allocated string,
16975 * then copy it to a buffer big enough.
16976 */
16977 *fname= *bufp = vim_strnsave(p, len);
16978 if (*fname == NULL)
16979 return -1;
16980 }
16981 else
16982 {
16983 /* Transfer pbuf2 to being the main buffer (it's big enough) */
16984 *fname = *bufp = pbuf2;
16985 if (p != pbuf2)
16986 strncpy(*fname, p, plen);
16987 pbuf2 = NULL;
16988 }
16989 /* Concat the next bit */
16990 strncpy(*fname + plen, s, slen);
16991 (*fname)[len] = '\0';
16992 }
16993 vim_free(pbuf3);
16994 vim_free(pbuf2);
16995 return 0;
16996}
16997
16998/*
16999 * Get a pathname for a partial path.
17000 */
17001 static int
17002shortpath_for_partial(fnamep, bufp, fnamelen)
17003 char_u **fnamep;
17004 char_u **bufp;
17005 int *fnamelen;
17006{
17007 int sepcount, len, tflen;
17008 char_u *p;
17009 char_u *pbuf, *tfname;
17010 int hasTilde;
17011
17012 /* Count up the path seperators from the RHS.. so we know which part
17013 * of the path to return.
17014 */
17015 sepcount = 0;
Bram Moolenaar1cd871b2004-12-19 22:46:22 +000017016 for (p = *fnamep; p < *fnamep + *fnamelen; mb_ptr_adv(p))
Bram Moolenaar071d4272004-06-13 20:20:40 +000017017 if (vim_ispathsep(*p))
17018 ++sepcount;
17019
17020 /* Need full path first (use expand_env() to remove a "~/") */
17021 hasTilde = (**fnamep == '~');
17022 if (hasTilde)
17023 pbuf = tfname = expand_env_save(*fnamep);
17024 else
17025 pbuf = tfname = FullName_save(*fnamep, FALSE);
17026
17027 len = tflen = STRLEN(tfname);
17028
17029 if (!get_short_pathname(&tfname, &pbuf, &len))
17030 return -1;
17031
17032 if (len == 0)
17033 {
17034 /* Don't have a valid filename, so shorten the rest of the
17035 * path if we can. This CAN give us invalid 8.3 filenames, but
17036 * there's not a lot of point in guessing what it might be.
17037 */
17038 len = tflen;
17039 if (shortpath_for_invalid_fname(&tfname, &pbuf, &len) == -1)
17040 return -1;
17041 }
17042
17043 /* Count the paths backward to find the beginning of the desired string. */
17044 for (p = tfname + len - 1; p >= tfname; --p)
Bram Moolenaar1cd871b2004-12-19 22:46:22 +000017045 {
17046#ifdef FEAT_MBYTE
17047 if (has_mbyte)
17048 p -= mb_head_off(tfname, p);
17049#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000017050 if (vim_ispathsep(*p))
17051 {
17052 if (sepcount == 0 || (hasTilde && sepcount == 1))
17053 break;
17054 else
17055 sepcount --;
17056 }
Bram Moolenaar1cd871b2004-12-19 22:46:22 +000017057 }
Bram Moolenaar071d4272004-06-13 20:20:40 +000017058 if (hasTilde)
17059 {
17060 --p;
17061 if (p >= tfname)
17062 *p = '~';
17063 else
17064 return -1;
17065 }
17066 else
17067 ++p;
17068
17069 /* Copy in the string - p indexes into tfname - allocated at pbuf */
17070 vim_free(*bufp);
17071 *fnamelen = (int)STRLEN(p);
17072 *bufp = pbuf;
17073 *fnamep = p;
17074
17075 return 0;
17076}
17077#endif /* WIN3264 */
17078
17079/*
17080 * Adjust a filename, according to a string of modifiers.
17081 * *fnamep must be NUL terminated when called. When returning, the length is
17082 * determined by *fnamelen.
17083 * Returns valid flags.
17084 * When there is an error, *fnamep is set to NULL.
17085 */
17086 int
17087modify_fname(src, usedlen, fnamep, bufp, fnamelen)
17088 char_u *src; /* string with modifiers */
17089 int *usedlen; /* characters after src that are used */
17090 char_u **fnamep; /* file name so far */
17091 char_u **bufp; /* buffer for allocated file name or NULL */
17092 int *fnamelen; /* length of fnamep */
17093{
17094 int valid = 0;
17095 char_u *tail;
17096 char_u *s, *p, *pbuf;
17097 char_u dirname[MAXPATHL];
17098 int c;
17099 int has_fullname = 0;
17100#ifdef WIN3264
17101 int has_shortname = 0;
17102#endif
17103
17104repeat:
17105 /* ":p" - full path/file_name */
17106 if (src[*usedlen] == ':' && src[*usedlen + 1] == 'p')
17107 {
17108 has_fullname = 1;
17109
17110 valid |= VALID_PATH;
17111 *usedlen += 2;
17112
17113 /* Expand "~/path" for all systems and "~user/path" for Unix and VMS */
17114 if ((*fnamep)[0] == '~'
17115#if !defined(UNIX) && !(defined(VMS) && defined(USER_HOME))
17116 && ((*fnamep)[1] == '/'
17117# ifdef BACKSLASH_IN_FILENAME
17118 || (*fnamep)[1] == '\\'
17119# endif
17120 || (*fnamep)[1] == NUL)
17121
17122#endif
17123 )
17124 {
17125 *fnamep = expand_env_save(*fnamep);
17126 vim_free(*bufp); /* free any allocated file name */
17127 *bufp = *fnamep;
17128 if (*fnamep == NULL)
17129 return -1;
17130 }
17131
17132 /* When "/." or "/.." is used: force expansion to get rid of it. */
Bram Moolenaar1cd871b2004-12-19 22:46:22 +000017133 for (p = *fnamep; *p != NUL; mb_ptr_adv(p))
Bram Moolenaar071d4272004-06-13 20:20:40 +000017134 {
17135 if (vim_ispathsep(*p)
17136 && p[1] == '.'
17137 && (p[2] == NUL
17138 || vim_ispathsep(p[2])
17139 || (p[2] == '.'
17140 && (p[3] == NUL || vim_ispathsep(p[3])))))
17141 break;
17142 }
17143
17144 /* FullName_save() is slow, don't use it when not needed. */
17145 if (*p != NUL || !vim_isAbsName(*fnamep))
17146 {
17147 *fnamep = FullName_save(*fnamep, *p != NUL);
17148 vim_free(*bufp); /* free any allocated file name */
17149 *bufp = *fnamep;
17150 if (*fnamep == NULL)
17151 return -1;
17152 }
17153
17154 /* Append a path separator to a directory. */
17155 if (mch_isdir(*fnamep))
17156 {
17157 /* Make room for one or two extra characters. */
17158 *fnamep = vim_strnsave(*fnamep, (int)STRLEN(*fnamep) + 2);
17159 vim_free(*bufp); /* free any allocated file name */
17160 *bufp = *fnamep;
17161 if (*fnamep == NULL)
17162 return -1;
17163 add_pathsep(*fnamep);
17164 }
17165 }
17166
17167 /* ":." - path relative to the current directory */
17168 /* ":~" - path relative to the home directory */
17169 /* ":8" - shortname path - postponed till after */
17170 while (src[*usedlen] == ':'
17171 && ((c = src[*usedlen + 1]) == '.' || c == '~' || c == '8'))
17172 {
17173 *usedlen += 2;
17174 if (c == '8')
17175 {
17176#ifdef WIN3264
17177 has_shortname = 1; /* Postpone this. */
17178#endif
17179 continue;
17180 }
17181 pbuf = NULL;
17182 /* Need full path first (use expand_env() to remove a "~/") */
17183 if (!has_fullname)
17184 {
17185 if (c == '.' && **fnamep == '~')
17186 p = pbuf = expand_env_save(*fnamep);
17187 else
17188 p = pbuf = FullName_save(*fnamep, FALSE);
17189 }
17190 else
17191 p = *fnamep;
17192
17193 has_fullname = 0;
17194
17195 if (p != NULL)
17196 {
17197 if (c == '.')
17198 {
17199 mch_dirname(dirname, MAXPATHL);
17200 s = shorten_fname(p, dirname);
17201 if (s != NULL)
17202 {
17203 *fnamep = s;
17204 if (pbuf != NULL)
17205 {
17206 vim_free(*bufp); /* free any allocated file name */
17207 *bufp = pbuf;
17208 pbuf = NULL;
17209 }
17210 }
17211 }
17212 else
17213 {
17214 home_replace(NULL, p, dirname, MAXPATHL, TRUE);
17215 /* Only replace it when it starts with '~' */
17216 if (*dirname == '~')
17217 {
17218 s = vim_strsave(dirname);
17219 if (s != NULL)
17220 {
17221 *fnamep = s;
17222 vim_free(*bufp);
17223 *bufp = s;
17224 }
17225 }
17226 }
17227 vim_free(pbuf);
17228 }
17229 }
17230
17231 tail = gettail(*fnamep);
17232 *fnamelen = (int)STRLEN(*fnamep);
17233
17234 /* ":h" - head, remove "/file_name", can be repeated */
17235 /* Don't remove the first "/" or "c:\" */
17236 while (src[*usedlen] == ':' && src[*usedlen + 1] == 'h')
17237 {
17238 valid |= VALID_HEAD;
17239 *usedlen += 2;
17240 s = get_past_head(*fnamep);
Bram Moolenaar1cd871b2004-12-19 22:46:22 +000017241 while (tail > s && after_pathsep(s, tail))
Bram Moolenaar071d4272004-06-13 20:20:40 +000017242 --tail;
17243 *fnamelen = (int)(tail - *fnamep);
17244#ifdef VMS
17245 if (*fnamelen > 0)
17246 *fnamelen += 1; /* the path separator is part of the path */
17247#endif
Bram Moolenaar1cd871b2004-12-19 22:46:22 +000017248 while (tail > s && !after_pathsep(s, tail))
17249 mb_ptr_back(*fnamep, tail);
Bram Moolenaar071d4272004-06-13 20:20:40 +000017250 }
17251
17252 /* ":8" - shortname */
17253 if (src[*usedlen] == ':' && src[*usedlen + 1] == '8')
17254 {
17255 *usedlen += 2;
17256#ifdef WIN3264
17257 has_shortname = 1;
17258#endif
17259 }
17260
17261#ifdef WIN3264
17262 /* Check shortname after we have done 'heads' and before we do 'tails'
17263 */
17264 if (has_shortname)
17265 {
17266 pbuf = NULL;
17267 /* Copy the string if it is shortened by :h */
17268 if (*fnamelen < (int)STRLEN(*fnamep))
17269 {
17270 p = vim_strnsave(*fnamep, *fnamelen);
17271 if (p == 0)
17272 return -1;
17273 vim_free(*bufp);
17274 *bufp = *fnamep = p;
17275 }
17276
17277 /* Split into two implementations - makes it easier. First is where
17278 * there isn't a full name already, second is where there is.
17279 */
17280 if (!has_fullname && !vim_isAbsName(*fnamep))
17281 {
17282 if (shortpath_for_partial(fnamep, bufp, fnamelen) == -1)
17283 return -1;
17284 }
17285 else
17286 {
17287 int l;
17288
17289 /* Simple case, already have the full-name
17290 * Nearly always shorter, so try first time. */
17291 l = *fnamelen;
17292 if (!get_short_pathname(fnamep, bufp, &l))
17293 return -1;
17294
17295 if (l == 0)
17296 {
17297 /* Couldn't find the filename.. search the paths.
17298 */
17299 l = *fnamelen;
17300 if (shortpath_for_invalid_fname(fnamep, bufp, &l ) == -1)
17301 return -1;
17302 }
17303 *fnamelen = l;
17304 }
17305 }
17306#endif /* WIN3264 */
17307
17308 /* ":t" - tail, just the basename */
17309 if (src[*usedlen] == ':' && src[*usedlen + 1] == 't')
17310 {
17311 *usedlen += 2;
17312 *fnamelen -= (int)(tail - *fnamep);
17313 *fnamep = tail;
17314 }
17315
17316 /* ":e" - extension, can be repeated */
17317 /* ":r" - root, without extension, can be repeated */
17318 while (src[*usedlen] == ':'
17319 && (src[*usedlen + 1] == 'e' || src[*usedlen + 1] == 'r'))
17320 {
17321 /* find a '.' in the tail:
17322 * - for second :e: before the current fname
17323 * - otherwise: The last '.'
17324 */
17325 if (src[*usedlen + 1] == 'e' && *fnamep > tail)
17326 s = *fnamep - 2;
17327 else
17328 s = *fnamep + *fnamelen - 1;
17329 for ( ; s > tail; --s)
17330 if (s[0] == '.')
17331 break;
17332 if (src[*usedlen + 1] == 'e') /* :e */
17333 {
17334 if (s > tail)
17335 {
17336 *fnamelen += (int)(*fnamep - (s + 1));
17337 *fnamep = s + 1;
17338#ifdef VMS
17339 /* cut version from the extension */
17340 s = *fnamep + *fnamelen - 1;
17341 for ( ; s > *fnamep; --s)
17342 if (s[0] == ';')
17343 break;
17344 if (s > *fnamep)
17345 *fnamelen = s - *fnamep;
17346#endif
17347 }
17348 else if (*fnamep <= tail)
17349 *fnamelen = 0;
17350 }
17351 else /* :r */
17352 {
17353 if (s > tail) /* remove one extension */
17354 *fnamelen = (int)(s - *fnamep);
17355 }
17356 *usedlen += 2;
17357 }
17358
17359 /* ":s?pat?foo?" - substitute */
17360 /* ":gs?pat?foo?" - global substitute */
17361 if (src[*usedlen] == ':'
17362 && (src[*usedlen + 1] == 's'
17363 || (src[*usedlen + 1] == 'g' && src[*usedlen + 2] == 's')))
17364 {
17365 char_u *str;
17366 char_u *pat;
17367 char_u *sub;
17368 int sep;
17369 char_u *flags;
17370 int didit = FALSE;
17371
17372 flags = (char_u *)"";
17373 s = src + *usedlen + 2;
17374 if (src[*usedlen + 1] == 'g')
17375 {
17376 flags = (char_u *)"g";
17377 ++s;
17378 }
17379
17380 sep = *s++;
17381 if (sep)
17382 {
17383 /* find end of pattern */
17384 p = vim_strchr(s, sep);
17385 if (p != NULL)
17386 {
17387 pat = vim_strnsave(s, (int)(p - s));
17388 if (pat != NULL)
17389 {
17390 s = p + 1;
17391 /* find end of substitution */
17392 p = vim_strchr(s, sep);
17393 if (p != NULL)
17394 {
17395 sub = vim_strnsave(s, (int)(p - s));
17396 str = vim_strnsave(*fnamep, *fnamelen);
17397 if (sub != NULL && str != NULL)
17398 {
17399 *usedlen = (int)(p + 1 - src);
17400 s = do_string_sub(str, pat, sub, flags);
17401 if (s != NULL)
17402 {
17403 *fnamep = s;
17404 *fnamelen = (int)STRLEN(s);
17405 vim_free(*bufp);
17406 *bufp = s;
17407 didit = TRUE;
17408 }
17409 }
17410 vim_free(sub);
17411 vim_free(str);
17412 }
17413 vim_free(pat);
17414 }
17415 }
17416 /* after using ":s", repeat all the modifiers */
17417 if (didit)
17418 goto repeat;
17419 }
17420 }
17421
17422 return valid;
17423}
17424
17425/*
17426 * Perform a substitution on "str" with pattern "pat" and substitute "sub".
17427 * "flags" can be "g" to do a global substitute.
17428 * Returns an allocated string, NULL for error.
17429 */
17430 char_u *
17431do_string_sub(str, pat, sub, flags)
17432 char_u *str;
17433 char_u *pat;
17434 char_u *sub;
17435 char_u *flags;
17436{
17437 int sublen;
17438 regmatch_T regmatch;
17439 int i;
17440 int do_all;
17441 char_u *tail;
17442 garray_T ga;
17443 char_u *ret;
17444 char_u *save_cpo;
17445
17446 /* Make 'cpoptions' empty, so that the 'l' flag doesn't work here */
17447 save_cpo = p_cpo;
17448 p_cpo = (char_u *)"";
17449
17450 ga_init2(&ga, 1, 200);
17451
17452 do_all = (flags[0] == 'g');
17453
17454 regmatch.rm_ic = p_ic;
17455 regmatch.regprog = vim_regcomp(pat, RE_MAGIC + RE_STRING);
17456 if (regmatch.regprog != NULL)
17457 {
17458 tail = str;
17459 while (vim_regexec_nl(&regmatch, str, (colnr_T)(tail - str)))
17460 {
17461 /*
17462 * Get some space for a temporary buffer to do the substitution
17463 * into. It will contain:
17464 * - The text up to where the match is.
17465 * - The substituted text.
17466 * - The text after the match.
17467 */
17468 sublen = vim_regsub(&regmatch, sub, tail, FALSE, TRUE, FALSE);
17469 if (ga_grow(&ga, (int)(STRLEN(tail) + sublen -
17470 (regmatch.endp[0] - regmatch.startp[0]))) == FAIL)
17471 {
17472 ga_clear(&ga);
17473 break;
17474 }
17475
17476 /* copy the text up to where the match is */
17477 i = (int)(regmatch.startp[0] - tail);
17478 mch_memmove((char_u *)ga.ga_data + ga.ga_len, tail, (size_t)i);
17479 /* add the substituted text */
17480 (void)vim_regsub(&regmatch, sub, (char_u *)ga.ga_data
17481 + ga.ga_len + i, TRUE, TRUE, FALSE);
17482 ga.ga_len += i + sublen - 1;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017483 /* avoid getting stuck on a match with an empty string */
17484 if (tail == regmatch.endp[0])
17485 {
17486 if (*tail == NUL)
17487 break;
17488 *((char_u *)ga.ga_data + ga.ga_len) = *tail++;
17489 ++ga.ga_len;
Bram Moolenaar071d4272004-06-13 20:20:40 +000017490 }
17491 else
17492 {
17493 tail = regmatch.endp[0];
17494 if (*tail == NUL)
17495 break;
17496 }
17497 if (!do_all)
17498 break;
17499 }
17500
17501 if (ga.ga_data != NULL)
17502 STRCPY((char *)ga.ga_data + ga.ga_len, tail);
17503
17504 vim_free(regmatch.regprog);
17505 }
17506
17507 ret = vim_strsave(ga.ga_data == NULL ? str : (char_u *)ga.ga_data);
17508 ga_clear(&ga);
17509 p_cpo = save_cpo;
17510
17511 return ret;
17512}
17513
17514#endif /* defined(FEAT_MODIFY_FNAME) || defined(FEAT_EVAL) */