1 /* 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 #define USING_FLOAT_STUFF 14 15 #include "vim.h" 16 17 #if defined(FEAT_EVAL) || defined(PROTO) 18 19 #ifdef AMIGA 20 # include <time.h> /* for strftime() */ 21 #endif 22 23 #ifdef VMS 24 # include <float.h> 25 #endif 26 27 #ifdef MACOS 28 # include <time.h> /* for time_t */ 29 #endif 30 31 #define DICT_MAXNEST 100 /* maximum nesting of lists and dicts */ 32 33 #define DO_NOT_FREE_CNT 99999 /* refcount for dict or list that should not 34 be freed. */ 35 36 /* 37 * In a hashtab item "hi_key" points to "di_key" in a dictitem. 38 * This avoids adding a pointer to the hashtab item. 39 * DI2HIKEY() converts a dictitem pointer to a hashitem key pointer. 40 * HIKEY2DI() converts a hashitem key pointer to a dictitem pointer. 41 * HI2DI() converts a hashitem pointer to a dictitem pointer. 42 */ 43 static dictitem_T dumdi; 44 #define DI2HIKEY(di) ((di)->di_key) 45 #define HIKEY2DI(p) ((dictitem_T *)(p - (dumdi.di_key - (char_u *)&dumdi))) 46 #define HI2DI(hi) HIKEY2DI((hi)->hi_key) 47 48 /* 49 * Structure returned by get_lval() and used by set_var_lval(). 50 * For a plain name: 51 * "name" points to the variable name. 52 * "exp_name" is NULL. 53 * "tv" is NULL 54 * For a magic braces name: 55 * "name" points to the expanded variable name. 56 * "exp_name" is non-NULL, to be freed later. 57 * "tv" is NULL 58 * For an index in a list: 59 * "name" points to the (expanded) variable name. 60 * "exp_name" NULL or non-NULL, to be freed later. 61 * "tv" points to the (first) list item value 62 * "li" points to the (first) list item 63 * "range", "n1", "n2" and "empty2" indicate what items are used. 64 * For an existing Dict item: 65 * "name" points to the (expanded) variable name. 66 * "exp_name" NULL or non-NULL, to be freed later. 67 * "tv" points to the dict item value 68 * "newkey" is NULL 69 * For a non-existing Dict item: 70 * "name" points to the (expanded) variable name. 71 * "exp_name" NULL or non-NULL, to be freed later. 72 * "tv" points to the Dictionary typval_T 73 * "newkey" is the key for the new item. 74 */ 75 typedef struct lval_S 76 { 77 char_u *ll_name; /* start of variable name (can be NULL) */ 78 char_u *ll_exp_name; /* NULL or expanded name in allocated memory. */ 79 typval_T *ll_tv; /* Typeval of item being used. If "newkey" 80 isn't NULL it's the Dict to which to add 81 the item. */ 82 listitem_T *ll_li; /* The list item or NULL. */ 83 list_T *ll_list; /* The list or NULL. */ 84 int ll_range; /* TRUE when a [i:j] range was used */ 85 long ll_n1; /* First index for list */ 86 long ll_n2; /* Second index for list range */ 87 int ll_empty2; /* Second index is empty: [i:] */ 88 dict_T *ll_dict; /* The Dictionary or NULL */ 89 dictitem_T *ll_di; /* The dictitem or NULL */ 90 char_u *ll_newkey; /* New key for Dict in alloc. mem or NULL. */ 91 } lval_T; 92 93 static char *e_letunexp = N_("E18: Unexpected characters in :let"); 94 static char *e_listidx = N_("E684: list index out of range: %ld"); 95 static char *e_undefvar = N_("E121: Undefined variable: %s"); 96 static char *e_missbrac = N_("E111: Missing ']'"); 97 static char *e_listarg = N_("E686: Argument of %s must be a List"); 98 static char *e_listdictarg = N_("E712: Argument of %s must be a List or Dictionary"); 99 static char *e_listreq = N_("E714: List required"); 100 static char *e_dictreq = N_("E715: Dictionary required"); 101 #ifdef FEAT_QUICKFIX 102 static char *e_stringreq = N_("E928: String required"); 103 #endif 104 static char *e_toomanyarg = N_("E118: Too many arguments for function: %s"); 105 static char *e_dictkey = N_("E716: Key not present in Dictionary: %s"); 106 static char *e_funcexts = N_("E122: Function %s already exists, add ! to replace it"); 107 static char *e_funcdict = N_("E717: Dictionary entry already exists"); 108 static char *e_funcref = N_("E718: Funcref required"); 109 static char *e_dictrange = N_("E719: Cannot use [:] with a Dictionary"); 110 static char *e_letwrong = N_("E734: Wrong variable type for %s="); 111 static char *e_nofunc = N_("E130: Unknown function: %s"); 112 static char *e_illvar = N_("E461: Illegal variable name: %s"); 113 #ifdef FEAT_FLOAT 114 static char *e_float_as_string = N_("E806: using Float as a String"); 115 #endif 116 117 #define NAMESPACE_CHAR (char_u *)"abglstvw" 118 119 static dictitem_T globvars_var; /* variable used for g: */ 120 #define globvarht globvardict.dv_hashtab 121 122 /* 123 * Old Vim variables such as "v:version" are also available without the "v:". 124 * Also in functions. We need a special hashtable for them. 125 */ 126 static hashtab_T compat_hashtab; 127 128 /* 129 * When recursively copying lists and dicts we need to remember which ones we 130 * have done to avoid endless recursiveness. This unique ID is used for that. 131 * The last bit is used for previous_funccal, ignored when comparing. 132 */ 133 static int current_copyID = 0; 134 #define COPYID_INC 2 135 #define COPYID_MASK (~0x1) 136 137 /* Abort conversion to string after a recursion error. */ 138 static int did_echo_string_emsg = FALSE; 139 140 /* 141 * Array to hold the hashtab with variables local to each sourced script. 142 * Each item holds a variable (nameless) that points to the dict_T. 143 */ 144 typedef struct 145 { 146 dictitem_T sv_var; 147 dict_T sv_dict; 148 } scriptvar_T; 149 150 static garray_T ga_scripts = {0, 0, sizeof(scriptvar_T *), 4, NULL}; 151 #define SCRIPT_SV(id) (((scriptvar_T **)ga_scripts.ga_data)[(id) - 1]) 152 #define SCRIPT_VARS(id) (SCRIPT_SV(id)->sv_dict.dv_hashtab) 153 154 static int echo_attr = 0; /* attributes used for ":echo" */ 155 156 /* Values for trans_function_name() argument: */ 157 #define TFN_INT 1 /* internal function name OK */ 158 #define TFN_QUIET 2 /* no error messages */ 159 #define TFN_NO_AUTOLOAD 4 /* do not use script autoloading */ 160 161 /* Values for get_lval() flags argument: */ 162 #define GLV_QUIET TFN_QUIET /* no error messages */ 163 #define GLV_NO_AUTOLOAD TFN_NO_AUTOLOAD /* do not use script autoloading */ 164 165 /* 166 * Structure to hold info for a user function. 167 */ 168 typedef struct ufunc ufunc_T; 169 170 struct ufunc 171 { 172 int uf_varargs; /* variable nr of arguments */ 173 int uf_flags; 174 int uf_calls; /* nr of active calls */ 175 garray_T uf_args; /* arguments */ 176 garray_T uf_lines; /* function lines */ 177 #ifdef FEAT_PROFILE 178 int uf_profiling; /* TRUE when func is being profiled */ 179 /* profiling the function as a whole */ 180 int uf_tm_count; /* nr of calls */ 181 proftime_T uf_tm_total; /* time spent in function + children */ 182 proftime_T uf_tm_self; /* time spent in function itself */ 183 proftime_T uf_tm_children; /* time spent in children this call */ 184 /* profiling the function per line */ 185 int *uf_tml_count; /* nr of times line was executed */ 186 proftime_T *uf_tml_total; /* time spent in a line + children */ 187 proftime_T *uf_tml_self; /* time spent in a line itself */ 188 proftime_T uf_tml_start; /* start time for current line */ 189 proftime_T uf_tml_children; /* time spent in children for this line */ 190 proftime_T uf_tml_wait; /* start wait time for current line */ 191 int uf_tml_idx; /* index of line being timed; -1 if none */ 192 int uf_tml_execed; /* line being timed was executed */ 193 #endif 194 scid_T uf_script_ID; /* ID of script where function was defined, 195 used for s: variables */ 196 int uf_refcount; /* for numbered function: reference count */ 197 char_u uf_name[1]; /* name of function (actually longer); can 198 start with <SNR>123_ (<SNR> is K_SPECIAL 199 KS_EXTRA KE_SNR) */ 200 }; 201 202 /* function flags */ 203 #define FC_ABORT 1 /* abort function on error */ 204 #define FC_RANGE 2 /* function accepts range */ 205 #define FC_DICT 4 /* Dict function, uses "self" */ 206 207 /* 208 * All user-defined functions are found in this hashtable. 209 */ 210 static hashtab_T func_hashtab; 211 212 /* The names of packages that once were loaded are remembered. */ 213 static garray_T ga_loaded = {0, 0, sizeof(char_u *), 4, NULL}; 214 215 /* List heads for garbage collection. Although there can be a reference loop 216 * from partial to dict to partial, we don't need to keep track of the partial, 217 * since it will get freed when the dict is unused and gets freed. */ 218 static dict_T *first_dict = NULL; /* list of all dicts */ 219 static list_T *first_list = NULL; /* list of all lists */ 220 221 /* From user function to hashitem and back. */ 222 static ufunc_T dumuf; 223 #define UF2HIKEY(fp) ((fp)->uf_name) 224 #define HIKEY2UF(p) ((ufunc_T *)(p - (dumuf.uf_name - (char_u *)&dumuf))) 225 #define HI2UF(hi) HIKEY2UF((hi)->hi_key) 226 227 #define FUNCARG(fp, j) ((char_u **)(fp->uf_args.ga_data))[j] 228 #define FUNCLINE(fp, j) ((char_u **)(fp->uf_lines.ga_data))[j] 229 230 #define MAX_FUNC_ARGS 20 /* maximum number of function arguments */ 231 #define VAR_SHORT_LEN 20 /* short variable name length */ 232 #define FIXVAR_CNT 12 /* number of fixed variables */ 233 234 /* structure to hold info for a function that is currently being executed. */ 235 typedef struct funccall_S funccall_T; 236 237 struct funccall_S 238 { 239 ufunc_T *func; /* function being called */ 240 int linenr; /* next line to be executed */ 241 int returned; /* ":return" used */ 242 struct /* fixed variables for arguments */ 243 { 244 dictitem_T var; /* variable (without room for name) */ 245 char_u room[VAR_SHORT_LEN]; /* room for the name */ 246 } fixvar[FIXVAR_CNT]; 247 dict_T l_vars; /* l: local function variables */ 248 dictitem_T l_vars_var; /* variable for l: scope */ 249 dict_T l_avars; /* a: argument variables */ 250 dictitem_T l_avars_var; /* variable for a: scope */ 251 list_T l_varlist; /* list for a:000 */ 252 listitem_T l_listitems[MAX_FUNC_ARGS]; /* listitems for a:000 */ 253 typval_T *rettv; /* return value */ 254 linenr_T breakpoint; /* next line with breakpoint or zero */ 255 int dbg_tick; /* debug_tick when breakpoint was set */ 256 int level; /* top nesting level of executed function */ 257 #ifdef FEAT_PROFILE 258 proftime_T prof_child; /* time spent in a child */ 259 #endif 260 funccall_T *caller; /* calling function or NULL */ 261 }; 262 263 /* 264 * Info used by a ":for" loop. 265 */ 266 typedef struct 267 { 268 int fi_semicolon; /* TRUE if ending in '; var]' */ 269 int fi_varcount; /* nr of variables in the list */ 270 listwatch_T fi_lw; /* keep an eye on the item used. */ 271 list_T *fi_list; /* list being used */ 272 } forinfo_T; 273 274 /* 275 * Struct used by trans_function_name() 276 */ 277 typedef struct 278 { 279 dict_T *fd_dict; /* Dictionary used */ 280 char_u *fd_newkey; /* new key in "dict" in allocated memory */ 281 dictitem_T *fd_di; /* Dictionary item used */ 282 } funcdict_T; 283 284 285 /* 286 * Array to hold the value of v: variables. 287 * The value is in a dictitem, so that it can also be used in the v: scope. 288 * The reason to use this table anyway is for very quick access to the 289 * variables with the VV_ defines. 290 */ 291 #include "version.h" 292 293 /* values for vv_flags: */ 294 #define VV_COMPAT 1 /* compatible, also used without "v:" */ 295 #define VV_RO 2 /* read-only */ 296 #define VV_RO_SBX 4 /* read-only in the sandbox */ 297 298 #define VV_NAME(s, t) s, {{t, 0, {0}}, 0, {0}} 299 300 static struct vimvar 301 { 302 char *vv_name; /* name of variable, without v: */ 303 dictitem16_T vv_di; /* value and name for key (max 16 chars!) */ 304 char vv_flags; /* VV_COMPAT, VV_RO, VV_RO_SBX */ 305 } vimvars[VV_LEN] = 306 { 307 /* 308 * The order here must match the VV_ defines in vim.h! 309 * Initializing a union does not work, leave tv.vval empty to get zero's. 310 */ 311 {VV_NAME("count", VAR_NUMBER), VV_COMPAT+VV_RO}, 312 {VV_NAME("count1", VAR_NUMBER), VV_RO}, 313 {VV_NAME("prevcount", VAR_NUMBER), VV_RO}, 314 {VV_NAME("errmsg", VAR_STRING), VV_COMPAT}, 315 {VV_NAME("warningmsg", VAR_STRING), 0}, 316 {VV_NAME("statusmsg", VAR_STRING), 0}, 317 {VV_NAME("shell_error", VAR_NUMBER), VV_COMPAT+VV_RO}, 318 {VV_NAME("this_session", VAR_STRING), VV_COMPAT}, 319 {VV_NAME("version", VAR_NUMBER), VV_COMPAT+VV_RO}, 320 {VV_NAME("lnum", VAR_NUMBER), VV_RO_SBX}, 321 {VV_NAME("termresponse", VAR_STRING), VV_RO}, 322 {VV_NAME("fname", VAR_STRING), VV_RO}, 323 {VV_NAME("lang", VAR_STRING), VV_RO}, 324 {VV_NAME("lc_time", VAR_STRING), VV_RO}, 325 {VV_NAME("ctype", VAR_STRING), VV_RO}, 326 {VV_NAME("charconvert_from", VAR_STRING), VV_RO}, 327 {VV_NAME("charconvert_to", VAR_STRING), VV_RO}, 328 {VV_NAME("fname_in", VAR_STRING), VV_RO}, 329 {VV_NAME("fname_out", VAR_STRING), VV_RO}, 330 {VV_NAME("fname_new", VAR_STRING), VV_RO}, 331 {VV_NAME("fname_diff", VAR_STRING), VV_RO}, 332 {VV_NAME("cmdarg", VAR_STRING), VV_RO}, 333 {VV_NAME("foldstart", VAR_NUMBER), VV_RO_SBX}, 334 {VV_NAME("foldend", VAR_NUMBER), VV_RO_SBX}, 335 {VV_NAME("folddashes", VAR_STRING), VV_RO_SBX}, 336 {VV_NAME("foldlevel", VAR_NUMBER), VV_RO_SBX}, 337 {VV_NAME("progname", VAR_STRING), VV_RO}, 338 {VV_NAME("servername", VAR_STRING), VV_RO}, 339 {VV_NAME("dying", VAR_NUMBER), VV_RO}, 340 {VV_NAME("exception", VAR_STRING), VV_RO}, 341 {VV_NAME("throwpoint", VAR_STRING), VV_RO}, 342 {VV_NAME("register", VAR_STRING), VV_RO}, 343 {VV_NAME("cmdbang", VAR_NUMBER), VV_RO}, 344 {VV_NAME("insertmode", VAR_STRING), VV_RO}, 345 {VV_NAME("val", VAR_UNKNOWN), VV_RO}, 346 {VV_NAME("key", VAR_UNKNOWN), VV_RO}, 347 {VV_NAME("profiling", VAR_NUMBER), VV_RO}, 348 {VV_NAME("fcs_reason", VAR_STRING), VV_RO}, 349 {VV_NAME("fcs_choice", VAR_STRING), 0}, 350 {VV_NAME("beval_bufnr", VAR_NUMBER), VV_RO}, 351 {VV_NAME("beval_winnr", VAR_NUMBER), VV_RO}, 352 {VV_NAME("beval_lnum", VAR_NUMBER), VV_RO}, 353 {VV_NAME("beval_col", VAR_NUMBER), VV_RO}, 354 {VV_NAME("beval_text", VAR_STRING), VV_RO}, 355 {VV_NAME("scrollstart", VAR_STRING), 0}, 356 {VV_NAME("swapname", VAR_STRING), VV_RO}, 357 {VV_NAME("swapchoice", VAR_STRING), 0}, 358 {VV_NAME("swapcommand", VAR_STRING), VV_RO}, 359 {VV_NAME("char", VAR_STRING), 0}, 360 {VV_NAME("mouse_win", VAR_NUMBER), 0}, 361 {VV_NAME("mouse_lnum", VAR_NUMBER), 0}, 362 {VV_NAME("mouse_col", VAR_NUMBER), 0}, 363 {VV_NAME("operator", VAR_STRING), VV_RO}, 364 {VV_NAME("searchforward", VAR_NUMBER), 0}, 365 {VV_NAME("hlsearch", VAR_NUMBER), 0}, 366 {VV_NAME("oldfiles", VAR_LIST), 0}, 367 {VV_NAME("windowid", VAR_NUMBER), VV_RO}, 368 {VV_NAME("progpath", VAR_STRING), VV_RO}, 369 {VV_NAME("completed_item", VAR_DICT), VV_RO}, 370 {VV_NAME("option_new", VAR_STRING), VV_RO}, 371 {VV_NAME("option_old", VAR_STRING), VV_RO}, 372 {VV_NAME("option_type", VAR_STRING), VV_RO}, 373 {VV_NAME("errors", VAR_LIST), 0}, 374 {VV_NAME("false", VAR_SPECIAL), VV_RO}, 375 {VV_NAME("true", VAR_SPECIAL), VV_RO}, 376 {VV_NAME("null", VAR_SPECIAL), VV_RO}, 377 {VV_NAME("none", VAR_SPECIAL), VV_RO}, 378 {VV_NAME("vim_did_enter", VAR_NUMBER), VV_RO}, 379 {VV_NAME("testing", VAR_NUMBER), 0}, 380 }; 381 382 /* shorthand */ 383 #define vv_type vv_di.di_tv.v_type 384 #define vv_nr vv_di.di_tv.vval.v_number 385 #define vv_float vv_di.di_tv.vval.v_float 386 #define vv_str vv_di.di_tv.vval.v_string 387 #define vv_list vv_di.di_tv.vval.v_list 388 #define vv_dict vv_di.di_tv.vval.v_dict 389 #define vv_tv vv_di.di_tv 390 391 static dictitem_T vimvars_var; /* variable used for v: */ 392 #define vimvarht vimvardict.dv_hashtab 393 394 static void prepare_vimvar(int idx, typval_T *save_tv); 395 static void restore_vimvar(int idx, typval_T *save_tv); 396 static int ex_let_vars(char_u *arg, typval_T *tv, int copy, int semicolon, int var_count, char_u *nextchars); 397 static char_u *skip_var_list(char_u *arg, int *var_count, int *semicolon); 398 static char_u *skip_var_one(char_u *arg); 399 static void list_hashtable_vars(hashtab_T *ht, char_u *prefix, int empty, int *first); 400 static void list_glob_vars(int *first); 401 static void list_buf_vars(int *first); 402 static void list_win_vars(int *first); 403 #ifdef FEAT_WINDOWS 404 static void list_tab_vars(int *first); 405 #endif 406 static void list_vim_vars(int *first); 407 static void list_script_vars(int *first); 408 static void list_func_vars(int *first); 409 static char_u *list_arg_vars(exarg_T *eap, char_u *arg, int *first); 410 static char_u *ex_let_one(char_u *arg, typval_T *tv, int copy, char_u *endchars, char_u *op); 411 static int check_changedtick(char_u *arg); 412 static char_u *get_lval(char_u *name, typval_T *rettv, lval_T *lp, int unlet, int skip, int flags, int fne_flags); 413 static void clear_lval(lval_T *lp); 414 static void set_var_lval(lval_T *lp, char_u *endp, typval_T *rettv, int copy, char_u *op); 415 static int tv_op(typval_T *tv1, typval_T *tv2, char_u *op); 416 static void list_fix_watch(list_T *l, listitem_T *item); 417 static void ex_unletlock(exarg_T *eap, char_u *argstart, int deep); 418 static int do_unlet_var(lval_T *lp, char_u *name_end, int forceit); 419 static int do_lock_var(lval_T *lp, char_u *name_end, int deep, int lock); 420 static void item_lock(typval_T *tv, int deep, int lock); 421 static int tv_islocked(typval_T *tv); 422 423 static int eval0(char_u *arg, typval_T *rettv, char_u **nextcmd, int evaluate); 424 static int eval1(char_u **arg, typval_T *rettv, int evaluate); 425 static int eval2(char_u **arg, typval_T *rettv, int evaluate); 426 static int eval3(char_u **arg, typval_T *rettv, int evaluate); 427 static int eval4(char_u **arg, typval_T *rettv, int evaluate); 428 static int eval5(char_u **arg, typval_T *rettv, int evaluate); 429 static int eval6(char_u **arg, typval_T *rettv, int evaluate, int want_string); 430 static int eval7(char_u **arg, typval_T *rettv, int evaluate, int want_string); 431 432 static int eval_index(char_u **arg, typval_T *rettv, int evaluate, int verbose); 433 static int get_option_tv(char_u **arg, typval_T *rettv, int evaluate); 434 static int get_string_tv(char_u **arg, typval_T *rettv, int evaluate); 435 static int get_lit_string_tv(char_u **arg, typval_T *rettv, int evaluate); 436 static int get_list_tv(char_u **arg, typval_T *rettv, int evaluate); 437 static void list_free_contents(list_T *l); 438 static void list_free_list(list_T *l); 439 static long list_len(list_T *l); 440 static int list_equal(list_T *l1, list_T *l2, int ic, int recursive); 441 static int dict_equal(dict_T *d1, dict_T *d2, int ic, int recursive); 442 static int tv_equal(typval_T *tv1, typval_T *tv2, int ic, int recursive); 443 static long list_find_nr(list_T *l, long idx, int *errorp); 444 static long list_idx_of_item(list_T *l, listitem_T *item); 445 static int list_extend(list_T *l1, list_T *l2, listitem_T *bef); 446 static int list_concat(list_T *l1, list_T *l2, typval_T *tv); 447 static list_T *list_copy(list_T *orig, int deep, int copyID); 448 static char_u *list2string(typval_T *tv, int copyID, int restore_copyID); 449 static int list_join_inner(garray_T *gap, list_T *l, char_u *sep, int echo_style, int restore_copyID, int copyID, garray_T *join_gap); 450 static int list_join(garray_T *gap, list_T *l, char_u *sep, int echo_style, int restore_copyID, int copyID); 451 static int free_unref_items(int copyID); 452 static dictitem_T *dictitem_copy(dictitem_T *org); 453 static void dictitem_remove(dict_T *dict, dictitem_T *item); 454 static dict_T *dict_copy(dict_T *orig, int deep, int copyID); 455 static long dict_len(dict_T *d); 456 static char_u *dict2string(typval_T *tv, int copyID, int restore_copyID); 457 static int get_dict_tv(char_u **arg, typval_T *rettv, int evaluate); 458 static char_u *echo_string_core(typval_T *tv, char_u **tofree, char_u *numbuf, int copyID, int echo_style, int restore_copyID, int dict_val); 459 static char_u *echo_string(typval_T *tv, char_u **tofree, char_u *numbuf, int copyID); 460 static char_u *string_quote(char_u *str, int function); 461 static int get_env_tv(char_u **arg, typval_T *rettv, int evaluate); 462 static int find_internal_func(char_u *name); 463 static char_u *deref_func_name(char_u *name, int *lenp, partial_T **partial, int no_autoload); 464 static int get_func_tv(char_u *name, int len, typval_T *rettv, char_u **arg, linenr_T firstline, linenr_T lastline, int *doesrange, int evaluate, partial_T *partial, dict_T *selfdict); 465 static void emsg_funcname(char *ermsg, char_u *name); 466 static int non_zero_arg(typval_T *argvars); 467 468 static void dict_free_contents(dict_T *d); 469 static void dict_free_dict(dict_T *d); 470 471 #ifdef FEAT_FLOAT 472 static void f_abs(typval_T *argvars, typval_T *rettv); 473 static void f_acos(typval_T *argvars, typval_T *rettv); 474 #endif 475 static void f_add(typval_T *argvars, typval_T *rettv); 476 static void f_and(typval_T *argvars, typval_T *rettv); 477 static void f_append(typval_T *argvars, typval_T *rettv); 478 static void f_argc(typval_T *argvars, typval_T *rettv); 479 static void f_argidx(typval_T *argvars, typval_T *rettv); 480 static void f_arglistid(typval_T *argvars, typval_T *rettv); 481 static void f_argv(typval_T *argvars, typval_T *rettv); 482 static void f_assert_equal(typval_T *argvars, typval_T *rettv); 483 static void f_assert_exception(typval_T *argvars, typval_T *rettv); 484 static void f_assert_fails(typval_T *argvars, typval_T *rettv); 485 static void f_assert_false(typval_T *argvars, typval_T *rettv); 486 static void f_assert_match(typval_T *argvars, typval_T *rettv); 487 static void f_assert_notequal(typval_T *argvars, typval_T *rettv); 488 static void f_assert_notmatch(typval_T *argvars, typval_T *rettv); 489 static void f_assert_true(typval_T *argvars, typval_T *rettv); 490 #ifdef FEAT_FLOAT 491 static void f_asin(typval_T *argvars, typval_T *rettv); 492 static void f_atan(typval_T *argvars, typval_T *rettv); 493 static void f_atan2(typval_T *argvars, typval_T *rettv); 494 #endif 495 static void f_browse(typval_T *argvars, typval_T *rettv); 496 static void f_browsedir(typval_T *argvars, typval_T *rettv); 497 static void f_bufexists(typval_T *argvars, typval_T *rettv); 498 static void f_buflisted(typval_T *argvars, typval_T *rettv); 499 static void f_bufloaded(typval_T *argvars, typval_T *rettv); 500 static void f_bufname(typval_T *argvars, typval_T *rettv); 501 static void f_bufnr(typval_T *argvars, typval_T *rettv); 502 static void f_bufwinnr(typval_T *argvars, typval_T *rettv); 503 static void f_byte2line(typval_T *argvars, typval_T *rettv); 504 static void byteidx(typval_T *argvars, typval_T *rettv, int comp); 505 static void f_byteidx(typval_T *argvars, typval_T *rettv); 506 static void f_byteidxcomp(typval_T *argvars, typval_T *rettv); 507 static void f_call(typval_T *argvars, typval_T *rettv); 508 #ifdef FEAT_FLOAT 509 static void f_ceil(typval_T *argvars, typval_T *rettv); 510 #endif 511 #ifdef FEAT_JOB_CHANNEL 512 static void f_ch_close(typval_T *argvars, typval_T *rettv); 513 static void f_ch_evalexpr(typval_T *argvars, typval_T *rettv); 514 static void f_ch_evalraw(typval_T *argvars, typval_T *rettv); 515 static void f_ch_getbufnr(typval_T *argvars, typval_T *rettv); 516 static void f_ch_getjob(typval_T *argvars, typval_T *rettv); 517 static void f_ch_info(typval_T *argvars, typval_T *rettv); 518 static void f_ch_log(typval_T *argvars, typval_T *rettv); 519 static void f_ch_logfile(typval_T *argvars, typval_T *rettv); 520 static void f_ch_open(typval_T *argvars, typval_T *rettv); 521 static void f_ch_read(typval_T *argvars, typval_T *rettv); 522 static void f_ch_readraw(typval_T *argvars, typval_T *rettv); 523 static void f_ch_sendexpr(typval_T *argvars, typval_T *rettv); 524 static void f_ch_sendraw(typval_T *argvars, typval_T *rettv); 525 static void f_ch_setoptions(typval_T *argvars, typval_T *rettv); 526 static void f_ch_status(typval_T *argvars, typval_T *rettv); 527 #endif 528 static void f_changenr(typval_T *argvars, typval_T *rettv); 529 static void f_char2nr(typval_T *argvars, typval_T *rettv); 530 static void f_cindent(typval_T *argvars, typval_T *rettv); 531 static void f_clearmatches(typval_T *argvars, typval_T *rettv); 532 static void f_col(typval_T *argvars, typval_T *rettv); 533 #if defined(FEAT_INS_EXPAND) 534 static void f_complete(typval_T *argvars, typval_T *rettv); 535 static void f_complete_add(typval_T *argvars, typval_T *rettv); 536 static void f_complete_check(typval_T *argvars, typval_T *rettv); 537 #endif 538 static void f_confirm(typval_T *argvars, typval_T *rettv); 539 static void f_copy(typval_T *argvars, typval_T *rettv); 540 #ifdef FEAT_FLOAT 541 static void f_cos(typval_T *argvars, typval_T *rettv); 542 static void f_cosh(typval_T *argvars, typval_T *rettv); 543 #endif 544 static void f_count(typval_T *argvars, typval_T *rettv); 545 static void f_cscope_connection(typval_T *argvars, typval_T *rettv); 546 static void f_cursor(typval_T *argsvars, typval_T *rettv); 547 static void f_deepcopy(typval_T *argvars, typval_T *rettv); 548 static void f_delete(typval_T *argvars, typval_T *rettv); 549 static void f_did_filetype(typval_T *argvars, typval_T *rettv); 550 static void f_diff_filler(typval_T *argvars, typval_T *rettv); 551 static void f_diff_hlID(typval_T *argvars, typval_T *rettv); 552 static void f_empty(typval_T *argvars, typval_T *rettv); 553 static void f_escape(typval_T *argvars, typval_T *rettv); 554 static void f_eval(typval_T *argvars, typval_T *rettv); 555 static void f_eventhandler(typval_T *argvars, typval_T *rettv); 556 static void f_executable(typval_T *argvars, typval_T *rettv); 557 static void f_exepath(typval_T *argvars, typval_T *rettv); 558 static void f_exists(typval_T *argvars, typval_T *rettv); 559 #ifdef FEAT_FLOAT 560 static void f_exp(typval_T *argvars, typval_T *rettv); 561 #endif 562 static void f_expand(typval_T *argvars, typval_T *rettv); 563 static void f_extend(typval_T *argvars, typval_T *rettv); 564 static void f_feedkeys(typval_T *argvars, typval_T *rettv); 565 static void f_filereadable(typval_T *argvars, typval_T *rettv); 566 static void f_filewritable(typval_T *argvars, typval_T *rettv); 567 static void f_filter(typval_T *argvars, typval_T *rettv); 568 static void f_finddir(typval_T *argvars, typval_T *rettv); 569 static void f_findfile(typval_T *argvars, typval_T *rettv); 570 #ifdef FEAT_FLOAT 571 static void f_float2nr(typval_T *argvars, typval_T *rettv); 572 static void f_floor(typval_T *argvars, typval_T *rettv); 573 static void f_fmod(typval_T *argvars, typval_T *rettv); 574 #endif 575 static void f_fnameescape(typval_T *argvars, typval_T *rettv); 576 static void f_fnamemodify(typval_T *argvars, typval_T *rettv); 577 static void f_foldclosed(typval_T *argvars, typval_T *rettv); 578 static void f_foldclosedend(typval_T *argvars, typval_T *rettv); 579 static void f_foldlevel(typval_T *argvars, typval_T *rettv); 580 static void f_foldtext(typval_T *argvars, typval_T *rettv); 581 static void f_foldtextresult(typval_T *argvars, typval_T *rettv); 582 static void f_foreground(typval_T *argvars, typval_T *rettv); 583 static void f_function(typval_T *argvars, typval_T *rettv); 584 static void f_garbagecollect(typval_T *argvars, typval_T *rettv); 585 static void f_get(typval_T *argvars, typval_T *rettv); 586 static void f_getbufline(typval_T *argvars, typval_T *rettv); 587 static void f_getbufvar(typval_T *argvars, typval_T *rettv); 588 static void f_getchar(typval_T *argvars, typval_T *rettv); 589 static void f_getcharmod(typval_T *argvars, typval_T *rettv); 590 static void f_getcharsearch(typval_T *argvars, typval_T *rettv); 591 static void f_getcmdline(typval_T *argvars, typval_T *rettv); 592 static void f_getcmdpos(typval_T *argvars, typval_T *rettv); 593 static void f_getcmdtype(typval_T *argvars, typval_T *rettv); 594 static void f_getcmdwintype(typval_T *argvars, typval_T *rettv); 595 static void f_getcwd(typval_T *argvars, typval_T *rettv); 596 static void f_getfontname(typval_T *argvars, typval_T *rettv); 597 static void f_getfperm(typval_T *argvars, typval_T *rettv); 598 static void f_getfsize(typval_T *argvars, typval_T *rettv); 599 static void f_getftime(typval_T *argvars, typval_T *rettv); 600 static void f_getftype(typval_T *argvars, typval_T *rettv); 601 static void f_getline(typval_T *argvars, typval_T *rettv); 602 static void f_getmatches(typval_T *argvars, typval_T *rettv); 603 static void f_getpid(typval_T *argvars, typval_T *rettv); 604 static void f_getcurpos(typval_T *argvars, typval_T *rettv); 605 static void f_getpos(typval_T *argvars, typval_T *rettv); 606 static void f_getqflist(typval_T *argvars, typval_T *rettv); 607 static void f_getreg(typval_T *argvars, typval_T *rettv); 608 static void f_getregtype(typval_T *argvars, typval_T *rettv); 609 static void f_gettabvar(typval_T *argvars, typval_T *rettv); 610 static void f_gettabwinvar(typval_T *argvars, typval_T *rettv); 611 static void f_getwinposx(typval_T *argvars, typval_T *rettv); 612 static void f_getwinposy(typval_T *argvars, typval_T *rettv); 613 static void f_getwinvar(typval_T *argvars, typval_T *rettv); 614 static void f_glob(typval_T *argvars, typval_T *rettv); 615 static void f_globpath(typval_T *argvars, typval_T *rettv); 616 static void f_glob2regpat(typval_T *argvars, typval_T *rettv); 617 static void f_has(typval_T *argvars, typval_T *rettv); 618 static void f_has_key(typval_T *argvars, typval_T *rettv); 619 static void f_haslocaldir(typval_T *argvars, typval_T *rettv); 620 static void f_hasmapto(typval_T *argvars, typval_T *rettv); 621 static void f_histadd(typval_T *argvars, typval_T *rettv); 622 static void f_histdel(typval_T *argvars, typval_T *rettv); 623 static void f_histget(typval_T *argvars, typval_T *rettv); 624 static void f_histnr(typval_T *argvars, typval_T *rettv); 625 static void f_hlID(typval_T *argvars, typval_T *rettv); 626 static void f_hlexists(typval_T *argvars, typval_T *rettv); 627 static void f_hostname(typval_T *argvars, typval_T *rettv); 628 static void f_iconv(typval_T *argvars, typval_T *rettv); 629 static void f_indent(typval_T *argvars, typval_T *rettv); 630 static void f_index(typval_T *argvars, typval_T *rettv); 631 static void f_input(typval_T *argvars, typval_T *rettv); 632 static void f_inputdialog(typval_T *argvars, typval_T *rettv); 633 static void f_inputlist(typval_T *argvars, typval_T *rettv); 634 static void f_inputrestore(typval_T *argvars, typval_T *rettv); 635 static void f_inputsave(typval_T *argvars, typval_T *rettv); 636 static void f_inputsecret(typval_T *argvars, typval_T *rettv); 637 static void f_insert(typval_T *argvars, typval_T *rettv); 638 static void f_invert(typval_T *argvars, typval_T *rettv); 639 static void f_isdirectory(typval_T *argvars, typval_T *rettv); 640 static void f_islocked(typval_T *argvars, typval_T *rettv); 641 #if defined(FEAT_FLOAT) && defined(HAVE_MATH_H) 642 static void f_isnan(typval_T *argvars, typval_T *rettv); 643 #endif 644 static void f_items(typval_T *argvars, typval_T *rettv); 645 #ifdef FEAT_JOB_CHANNEL 646 static void f_job_getchannel(typval_T *argvars, typval_T *rettv); 647 static void f_job_info(typval_T *argvars, typval_T *rettv); 648 static void f_job_setoptions(typval_T *argvars, typval_T *rettv); 649 static void f_job_start(typval_T *argvars, typval_T *rettv); 650 static void f_job_stop(typval_T *argvars, typval_T *rettv); 651 static void f_job_status(typval_T *argvars, typval_T *rettv); 652 #endif 653 static void f_join(typval_T *argvars, typval_T *rettv); 654 static void f_js_decode(typval_T *argvars, typval_T *rettv); 655 static void f_js_encode(typval_T *argvars, typval_T *rettv); 656 static void f_json_decode(typval_T *argvars, typval_T *rettv); 657 static void f_json_encode(typval_T *argvars, typval_T *rettv); 658 static void f_keys(typval_T *argvars, typval_T *rettv); 659 static void f_last_buffer_nr(typval_T *argvars, typval_T *rettv); 660 static void f_len(typval_T *argvars, typval_T *rettv); 661 static void f_libcall(typval_T *argvars, typval_T *rettv); 662 static void f_libcallnr(typval_T *argvars, typval_T *rettv); 663 static void f_line(typval_T *argvars, typval_T *rettv); 664 static void f_line2byte(typval_T *argvars, typval_T *rettv); 665 static void f_lispindent(typval_T *argvars, typval_T *rettv); 666 static void f_localtime(typval_T *argvars, typval_T *rettv); 667 #ifdef FEAT_FLOAT 668 static void f_log(typval_T *argvars, typval_T *rettv); 669 static void f_log10(typval_T *argvars, typval_T *rettv); 670 #endif 671 #ifdef FEAT_LUA 672 static void f_luaeval(typval_T *argvars, typval_T *rettv); 673 #endif 674 static void f_map(typval_T *argvars, typval_T *rettv); 675 static void f_maparg(typval_T *argvars, typval_T *rettv); 676 static void f_mapcheck(typval_T *argvars, typval_T *rettv); 677 static void f_match(typval_T *argvars, typval_T *rettv); 678 static void f_matchadd(typval_T *argvars, typval_T *rettv); 679 static void f_matchaddpos(typval_T *argvars, typval_T *rettv); 680 static void f_matcharg(typval_T *argvars, typval_T *rettv); 681 static void f_matchdelete(typval_T *argvars, typval_T *rettv); 682 static void f_matchend(typval_T *argvars, typval_T *rettv); 683 static void f_matchlist(typval_T *argvars, typval_T *rettv); 684 static void f_matchstr(typval_T *argvars, typval_T *rettv); 685 static void f_matchstrpos(typval_T *argvars, typval_T *rettv); 686 static void f_max(typval_T *argvars, typval_T *rettv); 687 static void f_min(typval_T *argvars, typval_T *rettv); 688 #ifdef vim_mkdir 689 static void f_mkdir(typval_T *argvars, typval_T *rettv); 690 #endif 691 static void f_mode(typval_T *argvars, typval_T *rettv); 692 #ifdef FEAT_MZSCHEME 693 static void f_mzeval(typval_T *argvars, typval_T *rettv); 694 #endif 695 static void f_nextnonblank(typval_T *argvars, typval_T *rettv); 696 static void f_nr2char(typval_T *argvars, typval_T *rettv); 697 static void f_or(typval_T *argvars, typval_T *rettv); 698 static void f_pathshorten(typval_T *argvars, typval_T *rettv); 699 #ifdef FEAT_PERL 700 static void f_perleval(typval_T *argvars, typval_T *rettv); 701 #endif 702 #ifdef FEAT_FLOAT 703 static void f_pow(typval_T *argvars, typval_T *rettv); 704 #endif 705 static void f_prevnonblank(typval_T *argvars, typval_T *rettv); 706 static void f_printf(typval_T *argvars, typval_T *rettv); 707 static void f_pumvisible(typval_T *argvars, typval_T *rettv); 708 #ifdef FEAT_PYTHON3 709 static void f_py3eval(typval_T *argvars, typval_T *rettv); 710 #endif 711 #ifdef FEAT_PYTHON 712 static void f_pyeval(typval_T *argvars, typval_T *rettv); 713 #endif 714 static void f_range(typval_T *argvars, typval_T *rettv); 715 static void f_readfile(typval_T *argvars, typval_T *rettv); 716 static void f_reltime(typval_T *argvars, typval_T *rettv); 717 #ifdef FEAT_FLOAT 718 static void f_reltimefloat(typval_T *argvars, typval_T *rettv); 719 #endif 720 static void f_reltimestr(typval_T *argvars, typval_T *rettv); 721 static void f_remote_expr(typval_T *argvars, typval_T *rettv); 722 static void f_remote_foreground(typval_T *argvars, typval_T *rettv); 723 static void f_remote_peek(typval_T *argvars, typval_T *rettv); 724 static void f_remote_read(typval_T *argvars, typval_T *rettv); 725 static void f_remote_send(typval_T *argvars, typval_T *rettv); 726 static void f_remove(typval_T *argvars, typval_T *rettv); 727 static void f_rename(typval_T *argvars, typval_T *rettv); 728 static void f_repeat(typval_T *argvars, typval_T *rettv); 729 static void f_resolve(typval_T *argvars, typval_T *rettv); 730 static void f_reverse(typval_T *argvars, typval_T *rettv); 731 #ifdef FEAT_FLOAT 732 static void f_round(typval_T *argvars, typval_T *rettv); 733 #endif 734 static void f_screenattr(typval_T *argvars, typval_T *rettv); 735 static void f_screenchar(typval_T *argvars, typval_T *rettv); 736 static void f_screencol(typval_T *argvars, typval_T *rettv); 737 static void f_screenrow(typval_T *argvars, typval_T *rettv); 738 static void f_search(typval_T *argvars, typval_T *rettv); 739 static void f_searchdecl(typval_T *argvars, typval_T *rettv); 740 static void f_searchpair(typval_T *argvars, typval_T *rettv); 741 static void f_searchpairpos(typval_T *argvars, typval_T *rettv); 742 static void f_searchpos(typval_T *argvars, typval_T *rettv); 743 static void f_server2client(typval_T *argvars, typval_T *rettv); 744 static void f_serverlist(typval_T *argvars, typval_T *rettv); 745 static void f_setbufvar(typval_T *argvars, typval_T *rettv); 746 static void f_setcharsearch(typval_T *argvars, typval_T *rettv); 747 static void f_setcmdpos(typval_T *argvars, typval_T *rettv); 748 static void f_setfperm(typval_T *argvars, typval_T *rettv); 749 static void f_setline(typval_T *argvars, typval_T *rettv); 750 static void f_setloclist(typval_T *argvars, typval_T *rettv); 751 static void f_setmatches(typval_T *argvars, typval_T *rettv); 752 static void f_setpos(typval_T *argvars, typval_T *rettv); 753 static void f_setqflist(typval_T *argvars, typval_T *rettv); 754 static void f_setreg(typval_T *argvars, typval_T *rettv); 755 static void f_settabvar(typval_T *argvars, typval_T *rettv); 756 static void f_settabwinvar(typval_T *argvars, typval_T *rettv); 757 static void f_setwinvar(typval_T *argvars, typval_T *rettv); 758 #ifdef FEAT_CRYPT 759 static void f_sha256(typval_T *argvars, typval_T *rettv); 760 #endif /* FEAT_CRYPT */ 761 static void f_shellescape(typval_T *argvars, typval_T *rettv); 762 static void f_shiftwidth(typval_T *argvars, typval_T *rettv); 763 static void f_simplify(typval_T *argvars, typval_T *rettv); 764 #ifdef FEAT_FLOAT 765 static void f_sin(typval_T *argvars, typval_T *rettv); 766 static void f_sinh(typval_T *argvars, typval_T *rettv); 767 #endif 768 static void f_sort(typval_T *argvars, typval_T *rettv); 769 static void f_soundfold(typval_T *argvars, typval_T *rettv); 770 static void f_spellbadword(typval_T *argvars, typval_T *rettv); 771 static void f_spellsuggest(typval_T *argvars, typval_T *rettv); 772 static void f_split(typval_T *argvars, typval_T *rettv); 773 #ifdef FEAT_FLOAT 774 static void f_sqrt(typval_T *argvars, typval_T *rettv); 775 static void f_str2float(typval_T *argvars, typval_T *rettv); 776 #endif 777 static void f_str2nr(typval_T *argvars, typval_T *rettv); 778 static void f_strchars(typval_T *argvars, typval_T *rettv); 779 #ifdef HAVE_STRFTIME 780 static void f_strftime(typval_T *argvars, typval_T *rettv); 781 #endif 782 static void f_strgetchar(typval_T *argvars, typval_T *rettv); 783 static void f_stridx(typval_T *argvars, typval_T *rettv); 784 static void f_string(typval_T *argvars, typval_T *rettv); 785 static void f_strlen(typval_T *argvars, typval_T *rettv); 786 static void f_strcharpart(typval_T *argvars, typval_T *rettv); 787 static void f_strpart(typval_T *argvars, typval_T *rettv); 788 static void f_strridx(typval_T *argvars, typval_T *rettv); 789 static void f_strtrans(typval_T *argvars, typval_T *rettv); 790 static void f_strdisplaywidth(typval_T *argvars, typval_T *rettv); 791 static void f_strwidth(typval_T *argvars, typval_T *rettv); 792 static void f_submatch(typval_T *argvars, typval_T *rettv); 793 static void f_substitute(typval_T *argvars, typval_T *rettv); 794 static void f_synID(typval_T *argvars, typval_T *rettv); 795 static void f_synIDattr(typval_T *argvars, typval_T *rettv); 796 static void f_synIDtrans(typval_T *argvars, typval_T *rettv); 797 static void f_synstack(typval_T *argvars, typval_T *rettv); 798 static void f_synconcealed(typval_T *argvars, typval_T *rettv); 799 static void f_system(typval_T *argvars, typval_T *rettv); 800 static void f_systemlist(typval_T *argvars, typval_T *rettv); 801 static void f_tabpagebuflist(typval_T *argvars, typval_T *rettv); 802 static void f_tabpagenr(typval_T *argvars, typval_T *rettv); 803 static void f_tabpagewinnr(typval_T *argvars, typval_T *rettv); 804 static void f_taglist(typval_T *argvars, typval_T *rettv); 805 static void f_tagfiles(typval_T *argvars, typval_T *rettv); 806 static void f_tempname(typval_T *argvars, typval_T *rettv); 807 static void f_test_alloc_fail(typval_T *argvars, typval_T *rettv); 808 static void f_test_disable_char_avail(typval_T *argvars, typval_T *rettv); 809 static void f_test_garbagecollect_now(typval_T *argvars, typval_T *rettv); 810 #ifdef FEAT_JOB_CHANNEL 811 static void f_test_null_channel(typval_T *argvars, typval_T *rettv); 812 #endif 813 static void f_test_null_dict(typval_T *argvars, typval_T *rettv); 814 #ifdef FEAT_JOB_CHANNEL 815 static void f_test_null_job(typval_T *argvars, typval_T *rettv); 816 #endif 817 static void f_test_null_list(typval_T *argvars, typval_T *rettv); 818 static void f_test_null_partial(typval_T *argvars, typval_T *rettv); 819 static void f_test_null_string(typval_T *argvars, typval_T *rettv); 820 #ifdef FEAT_FLOAT 821 static void f_tan(typval_T *argvars, typval_T *rettv); 822 static void f_tanh(typval_T *argvars, typval_T *rettv); 823 #endif 824 #ifdef FEAT_TIMERS 825 static void f_timer_start(typval_T *argvars, typval_T *rettv); 826 static void f_timer_stop(typval_T *argvars, typval_T *rettv); 827 #endif 828 static void f_tolower(typval_T *argvars, typval_T *rettv); 829 static void f_toupper(typval_T *argvars, typval_T *rettv); 830 static void f_tr(typval_T *argvars, typval_T *rettv); 831 #ifdef FEAT_FLOAT 832 static void f_trunc(typval_T *argvars, typval_T *rettv); 833 #endif 834 static void f_type(typval_T *argvars, typval_T *rettv); 835 static void f_undofile(typval_T *argvars, typval_T *rettv); 836 static void f_undotree(typval_T *argvars, typval_T *rettv); 837 static void f_uniq(typval_T *argvars, typval_T *rettv); 838 static void f_values(typval_T *argvars, typval_T *rettv); 839 static void f_virtcol(typval_T *argvars, typval_T *rettv); 840 static void f_visualmode(typval_T *argvars, typval_T *rettv); 841 static void f_wildmenumode(typval_T *argvars, typval_T *rettv); 842 static void f_win_findbuf(typval_T *argvars, typval_T *rettv); 843 static void f_win_getid(typval_T *argvars, typval_T *rettv); 844 static void f_win_gotoid(typval_T *argvars, typval_T *rettv); 845 static void f_win_id2tabwin(typval_T *argvars, typval_T *rettv); 846 static void f_win_id2win(typval_T *argvars, typval_T *rettv); 847 static void f_winbufnr(typval_T *argvars, typval_T *rettv); 848 static void f_wincol(typval_T *argvars, typval_T *rettv); 849 static void f_winheight(typval_T *argvars, typval_T *rettv); 850 static void f_winline(typval_T *argvars, typval_T *rettv); 851 static void f_winnr(typval_T *argvars, typval_T *rettv); 852 static void f_winrestcmd(typval_T *argvars, typval_T *rettv); 853 static void f_winrestview(typval_T *argvars, typval_T *rettv); 854 static void f_winsaveview(typval_T *argvars, typval_T *rettv); 855 static void f_winwidth(typval_T *argvars, typval_T *rettv); 856 static void f_writefile(typval_T *argvars, typval_T *rettv); 857 static void f_wordcount(typval_T *argvars, typval_T *rettv); 858 static void f_xor(typval_T *argvars, typval_T *rettv); 859 860 static int list2fpos(typval_T *arg, pos_T *posp, int *fnump, colnr_T *curswantp); 861 static pos_T *var2fpos(typval_T *varp, int dollar_lnum, int *fnum); 862 static int get_env_len(char_u **arg); 863 static int get_id_len(char_u **arg); 864 static int get_name_len(char_u **arg, char_u **alias, int evaluate, int verbose); 865 static char_u *find_name_end(char_u *arg, char_u **expr_start, char_u **expr_end, int flags); 866 #define FNE_INCL_BR 1 /* find_name_end(): include [] in name */ 867 #define FNE_CHECK_START 2 /* find_name_end(): check name starts with 868 valid character */ 869 static char_u * make_expanded_name(char_u *in_start, char_u *expr_start, char_u *expr_end, char_u *in_end); 870 static int eval_isnamec(int c); 871 static int eval_isnamec1(int c); 872 static int get_var_tv(char_u *name, int len, typval_T *rettv, dictitem_T **dip, int verbose, int no_autoload); 873 static int handle_subscript(char_u **arg, typval_T *rettv, int evaluate, int verbose); 874 static typval_T *alloc_string_tv(char_u *string); 875 static void init_tv(typval_T *varp); 876 #ifdef FEAT_FLOAT 877 static float_T get_tv_float(typval_T *varp); 878 #endif 879 static linenr_T get_tv_lnum(typval_T *argvars); 880 static linenr_T get_tv_lnum_buf(typval_T *argvars, buf_T *buf); 881 static dictitem_T *find_var(char_u *name, hashtab_T **htp, int no_autoload); 882 static dictitem_T *find_var_in_ht(hashtab_T *ht, int htname, char_u *varname, int no_autoload); 883 static hashtab_T *find_var_ht(char_u *name, char_u **varname); 884 static funccall_T *get_funccal(void); 885 static void vars_clear_ext(hashtab_T *ht, int free_val); 886 static void delete_var(hashtab_T *ht, hashitem_T *hi); 887 static void list_one_var(dictitem_T *v, char_u *prefix, int *first); 888 static void list_one_var_a(char_u *prefix, char_u *name, int type, char_u *string, int *first); 889 static void set_var(char_u *name, typval_T *varp, int copy); 890 static int var_check_ro(int flags, char_u *name, int use_gettext); 891 static int var_check_fixed(int flags, char_u *name, int use_gettext); 892 static int var_check_func_name(char_u *name, int new_var); 893 static int valid_varname(char_u *varname); 894 static int tv_check_lock(int lock, char_u *name, int use_gettext); 895 static int item_copy(typval_T *from, typval_T *to, int deep, int copyID); 896 static char_u *find_option_end(char_u **arg, int *opt_flags); 897 static char_u *trans_function_name(char_u **pp, int skip, int flags, funcdict_T *fd, partial_T **partial); 898 static int eval_fname_script(char_u *p); 899 static int eval_fname_sid(char_u *p); 900 static void list_func_head(ufunc_T *fp, int indent); 901 static ufunc_T *find_func(char_u *name); 902 static int function_exists(char_u *name); 903 static int builtin_function(char_u *name, int len); 904 #ifdef FEAT_PROFILE 905 static void func_do_profile(ufunc_T *fp); 906 static void prof_sort_list(FILE *fd, ufunc_T **sorttab, int st_len, char *title, int prefer_self); 907 static void prof_func_line(FILE *fd, int count, proftime_T *total, proftime_T *self, int prefer_self); 908 static int 909 # ifdef __BORLANDC__ 910 _RTLENTRYF 911 # endif 912 prof_total_cmp(const void *s1, const void *s2); 913 static int 914 # ifdef __BORLANDC__ 915 _RTLENTRYF 916 # endif 917 prof_self_cmp(const void *s1, const void *s2); 918 #endif 919 static int script_autoload(char_u *name, int reload); 920 static char_u *autoload_name(char_u *name); 921 static void cat_func_name(char_u *buf, ufunc_T *fp); 922 static void func_free(ufunc_T *fp); 923 static void call_user_func(ufunc_T *fp, int argcount, typval_T *argvars, typval_T *rettv, linenr_T firstline, linenr_T lastline, dict_T *selfdict); 924 static int can_free_funccal(funccall_T *fc, int copyID) ; 925 static void free_funccal(funccall_T *fc, int free_val); 926 static void add_nr_var(dict_T *dp, dictitem_T *v, char *name, varnumber_T nr); 927 static win_T *find_win_by_nr(typval_T *vp, tabpage_T *tp); 928 static win_T *find_tabwin(typval_T *wvp, typval_T *tvp); 929 static void getwinvar(typval_T *argvars, typval_T *rettv, int off); 930 static int searchpair_cmn(typval_T *argvars, pos_T *match_pos); 931 static int search_cmn(typval_T *argvars, pos_T *match_pos, int *flagsp); 932 static void setwinvar(typval_T *argvars, typval_T *rettv, int off); 933 static int write_list(FILE *fd, list_T *list, int binary); 934 static void get_cmd_output_as_rettv(typval_T *argvars, typval_T *rettv, int retlist); 935 936 937 #ifdef EBCDIC 938 static int compare_func_name(const void *s1, const void *s2); 939 static void sortFunctions(); 940 #endif 941 942 /* 943 * Initialize the global and v: variables. 944 */ 945 void 946 eval_init(void) 947 { 948 int i; 949 struct vimvar *p; 950 951 init_var_dict(&globvardict, &globvars_var, VAR_DEF_SCOPE); 952 init_var_dict(&vimvardict, &vimvars_var, VAR_SCOPE); 953 vimvardict.dv_lock = VAR_FIXED; 954 hash_init(&compat_hashtab); 955 hash_init(&func_hashtab); 956 957 for (i = 0; i < VV_LEN; ++i) 958 { 959 p = &vimvars[i]; 960 if (STRLEN(p->vv_name) > 16) 961 { 962 EMSG("INTERNAL: name too long, increase size of dictitem16_T"); 963 getout(1); 964 } 965 STRCPY(p->vv_di.di_key, p->vv_name); 966 if (p->vv_flags & VV_RO) 967 p->vv_di.di_flags = DI_FLAGS_RO | DI_FLAGS_FIX; 968 else if (p->vv_flags & VV_RO_SBX) 969 p->vv_di.di_flags = DI_FLAGS_RO_SBX | DI_FLAGS_FIX; 970 else 971 p->vv_di.di_flags = DI_FLAGS_FIX; 972 973 /* add to v: scope dict, unless the value is not always available */ 974 if (p->vv_type != VAR_UNKNOWN) 975 hash_add(&vimvarht, p->vv_di.di_key); 976 if (p->vv_flags & VV_COMPAT) 977 /* add to compat scope dict */ 978 hash_add(&compat_hashtab, p->vv_di.di_key); 979 } 980 vimvars[VV_VERSION].vv_nr = VIM_VERSION_100; 981 982 set_vim_var_nr(VV_SEARCHFORWARD, 1L); 983 set_vim_var_nr(VV_HLSEARCH, 1L); 984 set_vim_var_dict(VV_COMPLETED_ITEM, dict_alloc()); 985 set_vim_var_list(VV_ERRORS, list_alloc()); 986 987 set_vim_var_nr(VV_FALSE, VVAL_FALSE); 988 set_vim_var_nr(VV_TRUE, VVAL_TRUE); 989 set_vim_var_nr(VV_NONE, VVAL_NONE); 990 set_vim_var_nr(VV_NULL, VVAL_NULL); 991 992 set_reg_var(0); /* default for v:register is not 0 but '"' */ 993 994 #ifdef EBCDIC 995 /* 996 * Sort the function table, to enable binary search. 997 */ 998 sortFunctions(); 999 #endif 1000 } 1001 1002 #if defined(EXITFREE) || defined(PROTO) 1003 void 1004 eval_clear(void) 1005 { 1006 int i; 1007 struct vimvar *p; 1008 1009 for (i = 0; i < VV_LEN; ++i) 1010 { 1011 p = &vimvars[i]; 1012 if (p->vv_di.di_tv.v_type == VAR_STRING) 1013 { 1014 vim_free(p->vv_str); 1015 p->vv_str = NULL; 1016 } 1017 else if (p->vv_di.di_tv.v_type == VAR_LIST) 1018 { 1019 list_unref(p->vv_list); 1020 p->vv_list = NULL; 1021 } 1022 } 1023 hash_clear(&vimvarht); 1024 hash_init(&vimvarht); /* garbage_collect() will access it */ 1025 hash_clear(&compat_hashtab); 1026 1027 free_scriptnames(); 1028 # if defined(FEAT_CMDL_COMPL) 1029 free_locales(); 1030 # endif 1031 1032 /* global variables */ 1033 vars_clear(&globvarht); 1034 1035 /* autoloaded script names */ 1036 ga_clear_strings(&ga_loaded); 1037 1038 /* Script-local variables. First clear all the variables and in a second 1039 * loop free the scriptvar_T, because a variable in one script might hold 1040 * a reference to the whole scope of another script. */ 1041 for (i = 1; i <= ga_scripts.ga_len; ++i) 1042 vars_clear(&SCRIPT_VARS(i)); 1043 for (i = 1; i <= ga_scripts.ga_len; ++i) 1044 vim_free(SCRIPT_SV(i)); 1045 ga_clear(&ga_scripts); 1046 1047 /* unreferenced lists and dicts */ 1048 (void)garbage_collect(FALSE); 1049 1050 /* functions */ 1051 free_all_functions(); 1052 hash_clear(&func_hashtab); 1053 } 1054 #endif 1055 1056 /* 1057 * Return the name of the executed function. 1058 */ 1059 char_u * 1060 func_name(void *cookie) 1061 { 1062 return ((funccall_T *)cookie)->func->uf_name; 1063 } 1064 1065 /* 1066 * Return the address holding the next breakpoint line for a funccall cookie. 1067 */ 1068 linenr_T * 1069 func_breakpoint(void *cookie) 1070 { 1071 return &((funccall_T *)cookie)->breakpoint; 1072 } 1073 1074 /* 1075 * Return the address holding the debug tick for a funccall cookie. 1076 */ 1077 int * 1078 func_dbg_tick(void *cookie) 1079 { 1080 return &((funccall_T *)cookie)->dbg_tick; 1081 } 1082 1083 /* 1084 * Return the nesting level for a funccall cookie. 1085 */ 1086 int 1087 func_level(void *cookie) 1088 { 1089 return ((funccall_T *)cookie)->level; 1090 } 1091 1092 /* pointer to funccal for currently active function */ 1093 funccall_T *current_funccal = NULL; 1094 1095 /* pointer to list of previously used funccal, still around because some 1096 * item in it is still being used. */ 1097 funccall_T *previous_funccal = NULL; 1098 1099 /* 1100 * Return TRUE when a function was ended by a ":return" command. 1101 */ 1102 int 1103 current_func_returned(void) 1104 { 1105 return current_funccal->returned; 1106 } 1107 1108 1109 /* 1110 * Set an internal variable to a string value. Creates the variable if it does 1111 * not already exist. 1112 */ 1113 void 1114 set_internal_string_var(char_u *name, char_u *value) 1115 { 1116 char_u *val; 1117 typval_T *tvp; 1118 1119 val = vim_strsave(value); 1120 if (val != NULL) 1121 { 1122 tvp = alloc_string_tv(val); 1123 if (tvp != NULL) 1124 { 1125 set_var(name, tvp, FALSE); 1126 free_tv(tvp); 1127 } 1128 } 1129 } 1130 1131 static lval_T *redir_lval = NULL; 1132 static garray_T redir_ga; /* only valid when redir_lval is not NULL */ 1133 static char_u *redir_endp = NULL; 1134 static char_u *redir_varname = NULL; 1135 1136 /* 1137 * Start recording command output to a variable 1138 * When "append" is TRUE append to an existing variable. 1139 * Returns OK if successfully completed the setup. FAIL otherwise. 1140 */ 1141 int 1142 var_redir_start(char_u *name, int append) 1143 { 1144 int save_emsg; 1145 int err; 1146 typval_T tv; 1147 1148 /* Catch a bad name early. */ 1149 if (!eval_isnamec1(*name)) 1150 { 1151 EMSG(_(e_invarg)); 1152 return FAIL; 1153 } 1154 1155 /* Make a copy of the name, it is used in redir_lval until redir ends. */ 1156 redir_varname = vim_strsave(name); 1157 if (redir_varname == NULL) 1158 return FAIL; 1159 1160 redir_lval = (lval_T *)alloc_clear((unsigned)sizeof(lval_T)); 1161 if (redir_lval == NULL) 1162 { 1163 var_redir_stop(); 1164 return FAIL; 1165 } 1166 1167 /* The output is stored in growarray "redir_ga" until redirection ends. */ 1168 ga_init2(&redir_ga, (int)sizeof(char), 500); 1169 1170 /* Parse the variable name (can be a dict or list entry). */ 1171 redir_endp = get_lval(redir_varname, NULL, redir_lval, FALSE, FALSE, 0, 1172 FNE_CHECK_START); 1173 if (redir_endp == NULL || redir_lval->ll_name == NULL || *redir_endp != NUL) 1174 { 1175 clear_lval(redir_lval); 1176 if (redir_endp != NULL && *redir_endp != NUL) 1177 /* Trailing characters are present after the variable name */ 1178 EMSG(_(e_trailing)); 1179 else 1180 EMSG(_(e_invarg)); 1181 redir_endp = NULL; /* don't store a value, only cleanup */ 1182 var_redir_stop(); 1183 return FAIL; 1184 } 1185 1186 /* check if we can write to the variable: set it to or append an empty 1187 * string */ 1188 save_emsg = did_emsg; 1189 did_emsg = FALSE; 1190 tv.v_type = VAR_STRING; 1191 tv.vval.v_string = (char_u *)""; 1192 if (append) 1193 set_var_lval(redir_lval, redir_endp, &tv, TRUE, (char_u *)"."); 1194 else 1195 set_var_lval(redir_lval, redir_endp, &tv, TRUE, (char_u *)"="); 1196 clear_lval(redir_lval); 1197 err = did_emsg; 1198 did_emsg |= save_emsg; 1199 if (err) 1200 { 1201 redir_endp = NULL; /* don't store a value, only cleanup */ 1202 var_redir_stop(); 1203 return FAIL; 1204 } 1205 1206 return OK; 1207 } 1208 1209 /* 1210 * Append "value[value_len]" to the variable set by var_redir_start(). 1211 * The actual appending is postponed until redirection ends, because the value 1212 * appended may in fact be the string we write to, changing it may cause freed 1213 * memory to be used: 1214 * :redir => foo 1215 * :let foo 1216 * :redir END 1217 */ 1218 void 1219 var_redir_str(char_u *value, int value_len) 1220 { 1221 int len; 1222 1223 if (redir_lval == NULL) 1224 return; 1225 1226 if (value_len == -1) 1227 len = (int)STRLEN(value); /* Append the entire string */ 1228 else 1229 len = value_len; /* Append only "value_len" characters */ 1230 1231 if (ga_grow(&redir_ga, len) == OK) 1232 { 1233 mch_memmove((char *)redir_ga.ga_data + redir_ga.ga_len, value, len); 1234 redir_ga.ga_len += len; 1235 } 1236 else 1237 var_redir_stop(); 1238 } 1239 1240 /* 1241 * Stop redirecting command output to a variable. 1242 * Frees the allocated memory. 1243 */ 1244 void 1245 var_redir_stop(void) 1246 { 1247 typval_T tv; 1248 1249 if (redir_lval != NULL) 1250 { 1251 /* If there was no error: assign the text to the variable. */ 1252 if (redir_endp != NULL) 1253 { 1254 ga_append(&redir_ga, NUL); /* Append the trailing NUL. */ 1255 tv.v_type = VAR_STRING; 1256 tv.vval.v_string = redir_ga.ga_data; 1257 /* Call get_lval() again, if it's inside a Dict or List it may 1258 * have changed. */ 1259 redir_endp = get_lval(redir_varname, NULL, redir_lval, 1260 FALSE, FALSE, 0, FNE_CHECK_START); 1261 if (redir_endp != NULL && redir_lval->ll_name != NULL) 1262 set_var_lval(redir_lval, redir_endp, &tv, FALSE, (char_u *)"."); 1263 clear_lval(redir_lval); 1264 } 1265 1266 /* free the collected output */ 1267 vim_free(redir_ga.ga_data); 1268 redir_ga.ga_data = NULL; 1269 1270 vim_free(redir_lval); 1271 redir_lval = NULL; 1272 } 1273 vim_free(redir_varname); 1274 redir_varname = NULL; 1275 } 1276 1277 # if defined(FEAT_MBYTE) || defined(PROTO) 1278 int 1279 eval_charconvert( 1280 char_u *enc_from, 1281 char_u *enc_to, 1282 char_u *fname_from, 1283 char_u *fname_to) 1284 { 1285 int err = FALSE; 1286 1287 set_vim_var_string(VV_CC_FROM, enc_from, -1); 1288 set_vim_var_string(VV_CC_TO, enc_to, -1); 1289 set_vim_var_string(VV_FNAME_IN, fname_from, -1); 1290 set_vim_var_string(VV_FNAME_OUT, fname_to, -1); 1291 if (eval_to_bool(p_ccv, &err, NULL, FALSE)) 1292 err = TRUE; 1293 set_vim_var_string(VV_CC_FROM, NULL, -1); 1294 set_vim_var_string(VV_CC_TO, NULL, -1); 1295 set_vim_var_string(VV_FNAME_IN, NULL, -1); 1296 set_vim_var_string(VV_FNAME_OUT, NULL, -1); 1297 1298 if (err) 1299 return FAIL; 1300 return OK; 1301 } 1302 # endif 1303 1304 # if defined(FEAT_POSTSCRIPT) || defined(PROTO) 1305 int 1306 eval_printexpr(char_u *fname, char_u *args) 1307 { 1308 int err = FALSE; 1309 1310 set_vim_var_string(VV_FNAME_IN, fname, -1); 1311 set_vim_var_string(VV_CMDARG, args, -1); 1312 if (eval_to_bool(p_pexpr, &err, NULL, FALSE)) 1313 err = TRUE; 1314 set_vim_var_string(VV_FNAME_IN, NULL, -1); 1315 set_vim_var_string(VV_CMDARG, NULL, -1); 1316 1317 if (err) 1318 { 1319 mch_remove(fname); 1320 return FAIL; 1321 } 1322 return OK; 1323 } 1324 # endif 1325 1326 # if defined(FEAT_DIFF) || defined(PROTO) 1327 void 1328 eval_diff( 1329 char_u *origfile, 1330 char_u *newfile, 1331 char_u *outfile) 1332 { 1333 int err = FALSE; 1334 1335 set_vim_var_string(VV_FNAME_IN, origfile, -1); 1336 set_vim_var_string(VV_FNAME_NEW, newfile, -1); 1337 set_vim_var_string(VV_FNAME_OUT, outfile, -1); 1338 (void)eval_to_bool(p_dex, &err, NULL, FALSE); 1339 set_vim_var_string(VV_FNAME_IN, NULL, -1); 1340 set_vim_var_string(VV_FNAME_NEW, NULL, -1); 1341 set_vim_var_string(VV_FNAME_OUT, NULL, -1); 1342 } 1343 1344 void 1345 eval_patch( 1346 char_u *origfile, 1347 char_u *difffile, 1348 char_u *outfile) 1349 { 1350 int err; 1351 1352 set_vim_var_string(VV_FNAME_IN, origfile, -1); 1353 set_vim_var_string(VV_FNAME_DIFF, difffile, -1); 1354 set_vim_var_string(VV_FNAME_OUT, outfile, -1); 1355 (void)eval_to_bool(p_pex, &err, NULL, FALSE); 1356 set_vim_var_string(VV_FNAME_IN, NULL, -1); 1357 set_vim_var_string(VV_FNAME_DIFF, NULL, -1); 1358 set_vim_var_string(VV_FNAME_OUT, NULL, -1); 1359 } 1360 # endif 1361 1362 /* 1363 * Top level evaluation function, returning a boolean. 1364 * Sets "error" to TRUE if there was an error. 1365 * Return TRUE or FALSE. 1366 */ 1367 int 1368 eval_to_bool( 1369 char_u *arg, 1370 int *error, 1371 char_u **nextcmd, 1372 int skip) /* only parse, don't execute */ 1373 { 1374 typval_T tv; 1375 int retval = FALSE; 1376 1377 if (skip) 1378 ++emsg_skip; 1379 if (eval0(arg, &tv, nextcmd, !skip) == FAIL) 1380 *error = TRUE; 1381 else 1382 { 1383 *error = FALSE; 1384 if (!skip) 1385 { 1386 retval = (get_tv_number_chk(&tv, error) != 0); 1387 clear_tv(&tv); 1388 } 1389 } 1390 if (skip) 1391 --emsg_skip; 1392 1393 return retval; 1394 } 1395 1396 /* 1397 * Top level evaluation function, returning a string. If "skip" is TRUE, 1398 * only parsing to "nextcmd" is done, without reporting errors. Return 1399 * pointer to allocated memory, or NULL for failure or when "skip" is TRUE. 1400 */ 1401 char_u * 1402 eval_to_string_skip( 1403 char_u *arg, 1404 char_u **nextcmd, 1405 int skip) /* only parse, don't execute */ 1406 { 1407 typval_T tv; 1408 char_u *retval; 1409 1410 if (skip) 1411 ++emsg_skip; 1412 if (eval0(arg, &tv, nextcmd, !skip) == FAIL || skip) 1413 retval = NULL; 1414 else 1415 { 1416 retval = vim_strsave(get_tv_string(&tv)); 1417 clear_tv(&tv); 1418 } 1419 if (skip) 1420 --emsg_skip; 1421 1422 return retval; 1423 } 1424 1425 /* 1426 * Skip over an expression at "*pp". 1427 * Return FAIL for an error, OK otherwise. 1428 */ 1429 int 1430 skip_expr(char_u **pp) 1431 { 1432 typval_T rettv; 1433 1434 *pp = skipwhite(*pp); 1435 return eval1(pp, &rettv, FALSE); 1436 } 1437 1438 /* 1439 * Top level evaluation function, returning a string. 1440 * When "convert" is TRUE convert a List into a sequence of lines and convert 1441 * a Float to a String. 1442 * Return pointer to allocated memory, or NULL for failure. 1443 */ 1444 char_u * 1445 eval_to_string( 1446 char_u *arg, 1447 char_u **nextcmd, 1448 int convert) 1449 { 1450 typval_T tv; 1451 char_u *retval; 1452 garray_T ga; 1453 #ifdef FEAT_FLOAT 1454 char_u numbuf[NUMBUFLEN]; 1455 #endif 1456 1457 if (eval0(arg, &tv, nextcmd, TRUE) == FAIL) 1458 retval = NULL; 1459 else 1460 { 1461 if (convert && tv.v_type == VAR_LIST) 1462 { 1463 ga_init2(&ga, (int)sizeof(char), 80); 1464 if (tv.vval.v_list != NULL) 1465 { 1466 list_join(&ga, tv.vval.v_list, (char_u *)"\n", TRUE, FALSE, 0); 1467 if (tv.vval.v_list->lv_len > 0) 1468 ga_append(&ga, NL); 1469 } 1470 ga_append(&ga, NUL); 1471 retval = (char_u *)ga.ga_data; 1472 } 1473 #ifdef FEAT_FLOAT 1474 else if (convert && tv.v_type == VAR_FLOAT) 1475 { 1476 vim_snprintf((char *)numbuf, NUMBUFLEN, "%g", tv.vval.v_float); 1477 retval = vim_strsave(numbuf); 1478 } 1479 #endif 1480 else 1481 retval = vim_strsave(get_tv_string(&tv)); 1482 clear_tv(&tv); 1483 } 1484 1485 return retval; 1486 } 1487 1488 /* 1489 * Call eval_to_string() without using current local variables and using 1490 * textlock. When "use_sandbox" is TRUE use the sandbox. 1491 */ 1492 char_u * 1493 eval_to_string_safe( 1494 char_u *arg, 1495 char_u **nextcmd, 1496 int use_sandbox) 1497 { 1498 char_u *retval; 1499 void *save_funccalp; 1500 1501 save_funccalp = save_funccal(); 1502 if (use_sandbox) 1503 ++sandbox; 1504 ++textlock; 1505 retval = eval_to_string(arg, nextcmd, FALSE); 1506 if (use_sandbox) 1507 --sandbox; 1508 --textlock; 1509 restore_funccal(save_funccalp); 1510 return retval; 1511 } 1512 1513 /* 1514 * Top level evaluation function, returning a number. 1515 * Evaluates "expr" silently. 1516 * Returns -1 for an error. 1517 */ 1518 int 1519 eval_to_number(char_u *expr) 1520 { 1521 typval_T rettv; 1522 int retval; 1523 char_u *p = skipwhite(expr); 1524 1525 ++emsg_off; 1526 1527 if (eval1(&p, &rettv, TRUE) == FAIL) 1528 retval = -1; 1529 else 1530 { 1531 retval = get_tv_number_chk(&rettv, NULL); 1532 clear_tv(&rettv); 1533 } 1534 --emsg_off; 1535 1536 return retval; 1537 } 1538 1539 /* 1540 * Prepare v: variable "idx" to be used. 1541 * Save the current typeval in "save_tv". 1542 * When not used yet add the variable to the v: hashtable. 1543 */ 1544 static void 1545 prepare_vimvar(int idx, typval_T *save_tv) 1546 { 1547 *save_tv = vimvars[idx].vv_tv; 1548 if (vimvars[idx].vv_type == VAR_UNKNOWN) 1549 hash_add(&vimvarht, vimvars[idx].vv_di.di_key); 1550 } 1551 1552 /* 1553 * Restore v: variable "idx" to typeval "save_tv". 1554 * When no longer defined, remove the variable from the v: hashtable. 1555 */ 1556 static void 1557 restore_vimvar(int idx, typval_T *save_tv) 1558 { 1559 hashitem_T *hi; 1560 1561 vimvars[idx].vv_tv = *save_tv; 1562 if (vimvars[idx].vv_type == VAR_UNKNOWN) 1563 { 1564 hi = hash_find(&vimvarht, vimvars[idx].vv_di.di_key); 1565 if (HASHITEM_EMPTY(hi)) 1566 EMSG2(_(e_intern2), "restore_vimvar()"); 1567 else 1568 hash_remove(&vimvarht, hi); 1569 } 1570 } 1571 1572 #if defined(FEAT_SPELL) || defined(PROTO) 1573 /* 1574 * Evaluate an expression to a list with suggestions. 1575 * For the "expr:" part of 'spellsuggest'. 1576 * Returns NULL when there is an error. 1577 */ 1578 list_T * 1579 eval_spell_expr(char_u *badword, char_u *expr) 1580 { 1581 typval_T save_val; 1582 typval_T rettv; 1583 list_T *list = NULL; 1584 char_u *p = skipwhite(expr); 1585 1586 /* Set "v:val" to the bad word. */ 1587 prepare_vimvar(VV_VAL, &save_val); 1588 vimvars[VV_VAL].vv_type = VAR_STRING; 1589 vimvars[VV_VAL].vv_str = badword; 1590 if (p_verbose == 0) 1591 ++emsg_off; 1592 1593 if (eval1(&p, &rettv, TRUE) == OK) 1594 { 1595 if (rettv.v_type != VAR_LIST) 1596 clear_tv(&rettv); 1597 else 1598 list = rettv.vval.v_list; 1599 } 1600 1601 if (p_verbose == 0) 1602 --emsg_off; 1603 restore_vimvar(VV_VAL, &save_val); 1604 1605 return list; 1606 } 1607 1608 /* 1609 * "list" is supposed to contain two items: a word and a number. Return the 1610 * word in "pp" and the number as the return value. 1611 * Return -1 if anything isn't right. 1612 * Used to get the good word and score from the eval_spell_expr() result. 1613 */ 1614 int 1615 get_spellword(list_T *list, char_u **pp) 1616 { 1617 listitem_T *li; 1618 1619 li = list->lv_first; 1620 if (li == NULL) 1621 return -1; 1622 *pp = get_tv_string(&li->li_tv); 1623 1624 li = li->li_next; 1625 if (li == NULL) 1626 return -1; 1627 return get_tv_number(&li->li_tv); 1628 } 1629 #endif 1630 1631 /* 1632 * Top level evaluation function. 1633 * Returns an allocated typval_T with the result. 1634 * Returns NULL when there is an error. 1635 */ 1636 typval_T * 1637 eval_expr(char_u *arg, char_u **nextcmd) 1638 { 1639 typval_T *tv; 1640 1641 tv = (typval_T *)alloc(sizeof(typval_T)); 1642 if (tv != NULL && eval0(arg, tv, nextcmd, TRUE) == FAIL) 1643 { 1644 vim_free(tv); 1645 tv = NULL; 1646 } 1647 1648 return tv; 1649 } 1650 1651 1652 /* 1653 * Call some vimL function and return the result in "*rettv". 1654 * Uses argv[argc] for the function arguments. Only Number and String 1655 * arguments are currently supported. 1656 * Returns OK or FAIL. 1657 */ 1658 int 1659 call_vim_function( 1660 char_u *func, 1661 int argc, 1662 char_u **argv, 1663 int safe, /* use the sandbox */ 1664 int str_arg_only, /* all arguments are strings */ 1665 typval_T *rettv) 1666 { 1667 typval_T *argvars; 1668 long n; 1669 int len; 1670 int i; 1671 int doesrange; 1672 void *save_funccalp = NULL; 1673 int ret; 1674 1675 argvars = (typval_T *)alloc((unsigned)((argc + 1) * sizeof(typval_T))); 1676 if (argvars == NULL) 1677 return FAIL; 1678 1679 for (i = 0; i < argc; i++) 1680 { 1681 /* Pass a NULL or empty argument as an empty string */ 1682 if (argv[i] == NULL || *argv[i] == NUL) 1683 { 1684 argvars[i].v_type = VAR_STRING; 1685 argvars[i].vval.v_string = (char_u *)""; 1686 continue; 1687 } 1688 1689 if (str_arg_only) 1690 len = 0; 1691 else 1692 /* Recognize a number argument, the others must be strings. */ 1693 vim_str2nr(argv[i], NULL, &len, STR2NR_ALL, &n, NULL, 0); 1694 if (len != 0 && len == (int)STRLEN(argv[i])) 1695 { 1696 argvars[i].v_type = VAR_NUMBER; 1697 argvars[i].vval.v_number = n; 1698 } 1699 else 1700 { 1701 argvars[i].v_type = VAR_STRING; 1702 argvars[i].vval.v_string = argv[i]; 1703 } 1704 } 1705 1706 if (safe) 1707 { 1708 save_funccalp = save_funccal(); 1709 ++sandbox; 1710 } 1711 1712 rettv->v_type = VAR_UNKNOWN; /* clear_tv() uses this */ 1713 ret = call_func(func, (int)STRLEN(func), rettv, argc, argvars, 1714 curwin->w_cursor.lnum, curwin->w_cursor.lnum, 1715 &doesrange, TRUE, NULL, NULL); 1716 if (safe) 1717 { 1718 --sandbox; 1719 restore_funccal(save_funccalp); 1720 } 1721 vim_free(argvars); 1722 1723 if (ret == FAIL) 1724 clear_tv(rettv); 1725 1726 return ret; 1727 } 1728 1729 /* 1730 * Call vimL function "func" and return the result as a number. 1731 * Returns -1 when calling the function fails. 1732 * Uses argv[argc] for the function arguments. 1733 */ 1734 long 1735 call_func_retnr( 1736 char_u *func, 1737 int argc, 1738 char_u **argv, 1739 int safe) /* use the sandbox */ 1740 { 1741 typval_T rettv; 1742 long retval; 1743 1744 /* All arguments are passed as strings, no conversion to number. */ 1745 if (call_vim_function(func, argc, argv, safe, TRUE, &rettv) == FAIL) 1746 return -1; 1747 1748 retval = get_tv_number_chk(&rettv, NULL); 1749 clear_tv(&rettv); 1750 return retval; 1751 } 1752 1753 #if (defined(FEAT_USR_CMDS) && defined(FEAT_CMDL_COMPL)) \ 1754 || defined(FEAT_COMPL_FUNC) || defined(PROTO) 1755 1756 # if (defined(FEAT_USR_CMDS) && defined(FEAT_CMDL_COMPL)) || defined(PROTO) 1757 /* 1758 * Call vimL function "func" and return the result as a string. 1759 * Returns NULL when calling the function fails. 1760 * Uses argv[argc] for the function arguments. 1761 */ 1762 void * 1763 call_func_retstr( 1764 char_u *func, 1765 int argc, 1766 char_u **argv, 1767 int safe) /* use the sandbox */ 1768 { 1769 typval_T rettv; 1770 char_u *retval; 1771 1772 /* All arguments are passed as strings, no conversion to number. */ 1773 if (call_vim_function(func, argc, argv, safe, TRUE, &rettv) == FAIL) 1774 return NULL; 1775 1776 retval = vim_strsave(get_tv_string(&rettv)); 1777 clear_tv(&rettv); 1778 return retval; 1779 } 1780 # endif 1781 1782 /* 1783 * Call vimL function "func" and return the result as a List. 1784 * Uses argv[argc] for the function arguments. 1785 * Returns NULL when there is something wrong. 1786 */ 1787 void * 1788 call_func_retlist( 1789 char_u *func, 1790 int argc, 1791 char_u **argv, 1792 int safe) /* use the sandbox */ 1793 { 1794 typval_T rettv; 1795 1796 /* All arguments are passed as strings, no conversion to number. */ 1797 if (call_vim_function(func, argc, argv, safe, TRUE, &rettv) == FAIL) 1798 return NULL; 1799 1800 if (rettv.v_type != VAR_LIST) 1801 { 1802 clear_tv(&rettv); 1803 return NULL; 1804 } 1805 1806 return rettv.vval.v_list; 1807 } 1808 #endif 1809 1810 /* 1811 * Save the current function call pointer, and set it to NULL. 1812 * Used when executing autocommands and for ":source". 1813 */ 1814 void * 1815 save_funccal(void) 1816 { 1817 funccall_T *fc = current_funccal; 1818 1819 current_funccal = NULL; 1820 return (void *)fc; 1821 } 1822 1823 void 1824 restore_funccal(void *vfc) 1825 { 1826 funccall_T *fc = (funccall_T *)vfc; 1827 1828 current_funccal = fc; 1829 } 1830 1831 #if defined(FEAT_PROFILE) || defined(PROTO) 1832 /* 1833 * Prepare profiling for entering a child or something else that is not 1834 * counted for the script/function itself. 1835 * Should always be called in pair with prof_child_exit(). 1836 */ 1837 void 1838 prof_child_enter( 1839 proftime_T *tm) /* place to store waittime */ 1840 { 1841 funccall_T *fc = current_funccal; 1842 1843 if (fc != NULL && fc->func->uf_profiling) 1844 profile_start(&fc->prof_child); 1845 script_prof_save(tm); 1846 } 1847 1848 /* 1849 * Take care of time spent in a child. 1850 * Should always be called after prof_child_enter(). 1851 */ 1852 void 1853 prof_child_exit( 1854 proftime_T *tm) /* where waittime was stored */ 1855 { 1856 funccall_T *fc = current_funccal; 1857 1858 if (fc != NULL && fc->func->uf_profiling) 1859 { 1860 profile_end(&fc->prof_child); 1861 profile_sub_wait(tm, &fc->prof_child); /* don't count waiting time */ 1862 profile_add(&fc->func->uf_tm_children, &fc->prof_child); 1863 profile_add(&fc->func->uf_tml_children, &fc->prof_child); 1864 } 1865 script_prof_restore(tm); 1866 } 1867 #endif 1868 1869 1870 #ifdef FEAT_FOLDING 1871 /* 1872 * Evaluate 'foldexpr'. Returns the foldlevel, and any character preceding 1873 * it in "*cp". Doesn't give error messages. 1874 */ 1875 int 1876 eval_foldexpr(char_u *arg, int *cp) 1877 { 1878 typval_T tv; 1879 int retval; 1880 char_u *s; 1881 int use_sandbox = was_set_insecurely((char_u *)"foldexpr", 1882 OPT_LOCAL); 1883 1884 ++emsg_off; 1885 if (use_sandbox) 1886 ++sandbox; 1887 ++textlock; 1888 *cp = NUL; 1889 if (eval0(arg, &tv, NULL, TRUE) == FAIL) 1890 retval = 0; 1891 else 1892 { 1893 /* If the result is a number, just return the number. */ 1894 if (tv.v_type == VAR_NUMBER) 1895 retval = tv.vval.v_number; 1896 else if (tv.v_type != VAR_STRING || tv.vval.v_string == NULL) 1897 retval = 0; 1898 else 1899 { 1900 /* If the result is a string, check if there is a non-digit before 1901 * the number. */ 1902 s = tv.vval.v_string; 1903 if (!VIM_ISDIGIT(*s) && *s != '-') 1904 *cp = *s++; 1905 retval = atol((char *)s); 1906 } 1907 clear_tv(&tv); 1908 } 1909 --emsg_off; 1910 if (use_sandbox) 1911 --sandbox; 1912 --textlock; 1913 1914 return retval; 1915 } 1916 #endif 1917 1918 /* 1919 * ":let" list all variable values 1920 * ":let var1 var2" list variable values 1921 * ":let var = expr" assignment command. 1922 * ":let var += expr" assignment command. 1923 * ":let var -= expr" assignment command. 1924 * ":let var .= expr" assignment command. 1925 * ":let [var1, var2] = expr" unpack list. 1926 */ 1927 void 1928 ex_let(exarg_T *eap) 1929 { 1930 char_u *arg = eap->arg; 1931 char_u *expr = NULL; 1932 typval_T rettv; 1933 int i; 1934 int var_count = 0; 1935 int semicolon = 0; 1936 char_u op[2]; 1937 char_u *argend; 1938 int first = TRUE; 1939 1940 argend = skip_var_list(arg, &var_count, &semicolon); 1941 if (argend == NULL) 1942 return; 1943 if (argend > arg && argend[-1] == '.') /* for var.='str' */ 1944 --argend; 1945 expr = skipwhite(argend); 1946 if (*expr != '=' && !(vim_strchr((char_u *)"+-.", *expr) != NULL 1947 && expr[1] == '=')) 1948 { 1949 /* 1950 * ":let" without "=": list variables 1951 */ 1952 if (*arg == '[') 1953 EMSG(_(e_invarg)); 1954 else if (!ends_excmd(*arg)) 1955 /* ":let var1 var2" */ 1956 arg = list_arg_vars(eap, arg, &first); 1957 else if (!eap->skip) 1958 { 1959 /* ":let" */ 1960 list_glob_vars(&first); 1961 list_buf_vars(&first); 1962 list_win_vars(&first); 1963 #ifdef FEAT_WINDOWS 1964 list_tab_vars(&first); 1965 #endif 1966 list_script_vars(&first); 1967 list_func_vars(&first); 1968 list_vim_vars(&first); 1969 } 1970 eap->nextcmd = check_nextcmd(arg); 1971 } 1972 else 1973 { 1974 op[0] = '='; 1975 op[1] = NUL; 1976 if (*expr != '=') 1977 { 1978 if (vim_strchr((char_u *)"+-.", *expr) != NULL) 1979 op[0] = *expr; /* +=, -= or .= */ 1980 expr = skipwhite(expr + 2); 1981 } 1982 else 1983 expr = skipwhite(expr + 1); 1984 1985 if (eap->skip) 1986 ++emsg_skip; 1987 i = eval0(expr, &rettv, &eap->nextcmd, !eap->skip); 1988 if (eap->skip) 1989 { 1990 if (i != FAIL) 1991 clear_tv(&rettv); 1992 --emsg_skip; 1993 } 1994 else if (i != FAIL) 1995 { 1996 (void)ex_let_vars(eap->arg, &rettv, FALSE, semicolon, var_count, 1997 op); 1998 clear_tv(&rettv); 1999 } 2000 } 2001 } 2002 2003 /* 2004 * Assign the typevalue "tv" to the variable or variables at "arg_start". 2005 * Handles both "var" with any type and "[var, var; var]" with a list type. 2006 * When "nextchars" is not NULL it points to a string with characters that 2007 * must appear after the variable(s). Use "+", "-" or "." for add, subtract 2008 * or concatenate. 2009 * Returns OK or FAIL; 2010 */ 2011 static int 2012 ex_let_vars( 2013 char_u *arg_start, 2014 typval_T *tv, 2015 int copy, /* copy values from "tv", don't move */ 2016 int semicolon, /* from skip_var_list() */ 2017 int var_count, /* from skip_var_list() */ 2018 char_u *nextchars) 2019 { 2020 char_u *arg = arg_start; 2021 list_T *l; 2022 int i; 2023 listitem_T *item; 2024 typval_T ltv; 2025 2026 if (*arg != '[') 2027 { 2028 /* 2029 * ":let var = expr" or ":for var in list" 2030 */ 2031 if (ex_let_one(arg, tv, copy, nextchars, nextchars) == NULL) 2032 return FAIL; 2033 return OK; 2034 } 2035 2036 /* 2037 * ":let [v1, v2] = list" or ":for [v1, v2] in listlist" 2038 */ 2039 if (tv->v_type != VAR_LIST || (l = tv->vval.v_list) == NULL) 2040 { 2041 EMSG(_(e_listreq)); 2042 return FAIL; 2043 } 2044 2045 i = list_len(l); 2046 if (semicolon == 0 && var_count < i) 2047 { 2048 EMSG(_("E687: Less targets than List items")); 2049 return FAIL; 2050 } 2051 if (var_count - semicolon > i) 2052 { 2053 EMSG(_("E688: More targets than List items")); 2054 return FAIL; 2055 } 2056 2057 item = l->lv_first; 2058 while (*arg != ']') 2059 { 2060 arg = skipwhite(arg + 1); 2061 arg = ex_let_one(arg, &item->li_tv, TRUE, (char_u *)",;]", nextchars); 2062 item = item->li_next; 2063 if (arg == NULL) 2064 return FAIL; 2065 2066 arg = skipwhite(arg); 2067 if (*arg == ';') 2068 { 2069 /* Put the rest of the list (may be empty) in the var after ';'. 2070 * Create a new list for this. */ 2071 l = list_alloc(); 2072 if (l == NULL) 2073 return FAIL; 2074 while (item != NULL) 2075 { 2076 list_append_tv(l, &item->li_tv); 2077 item = item->li_next; 2078 } 2079 2080 ltv.v_type = VAR_LIST; 2081 ltv.v_lock = 0; 2082 ltv.vval.v_list = l; 2083 l->lv_refcount = 1; 2084 2085 arg = ex_let_one(skipwhite(arg + 1), <v, FALSE, 2086 (char_u *)"]", nextchars); 2087 clear_tv(<v); 2088 if (arg == NULL) 2089 return FAIL; 2090 break; 2091 } 2092 else if (*arg != ',' && *arg != ']') 2093 { 2094 EMSG2(_(e_intern2), "ex_let_vars()"); 2095 return FAIL; 2096 } 2097 } 2098 2099 return OK; 2100 } 2101 2102 /* 2103 * Skip over assignable variable "var" or list of variables "[var, var]". 2104 * Used for ":let varvar = expr" and ":for varvar in expr". 2105 * For "[var, var]" increment "*var_count" for each variable. 2106 * for "[var, var; var]" set "semicolon". 2107 * Return NULL for an error. 2108 */ 2109 static char_u * 2110 skip_var_list( 2111 char_u *arg, 2112 int *var_count, 2113 int *semicolon) 2114 { 2115 char_u *p, *s; 2116 2117 if (*arg == '[') 2118 { 2119 /* "[var, var]": find the matching ']'. */ 2120 p = arg; 2121 for (;;) 2122 { 2123 p = skipwhite(p + 1); /* skip whites after '[', ';' or ',' */ 2124 s = skip_var_one(p); 2125 if (s == p) 2126 { 2127 EMSG2(_(e_invarg2), p); 2128 return NULL; 2129 } 2130 ++*var_count; 2131 2132 p = skipwhite(s); 2133 if (*p == ']') 2134 break; 2135 else if (*p == ';') 2136 { 2137 if (*semicolon == 1) 2138 { 2139 EMSG(_("Double ; in list of variables")); 2140 return NULL; 2141 } 2142 *semicolon = 1; 2143 } 2144 else if (*p != ',') 2145 { 2146 EMSG2(_(e_invarg2), p); 2147 return NULL; 2148 } 2149 } 2150 return p + 1; 2151 } 2152 else 2153 return skip_var_one(arg); 2154 } 2155 2156 /* 2157 * Skip one (assignable) variable name, including @r, $VAR, &option, d.key, 2158 * l[idx]. 2159 */ 2160 static char_u * 2161 skip_var_one(char_u *arg) 2162 { 2163 if (*arg == '@' && arg[1] != NUL) 2164 return arg + 2; 2165 return find_name_end(*arg == '$' || *arg == '&' ? arg + 1 : arg, 2166 NULL, NULL, FNE_INCL_BR | FNE_CHECK_START); 2167 } 2168 2169 /* 2170 * List variables for hashtab "ht" with prefix "prefix". 2171 * If "empty" is TRUE also list NULL strings as empty strings. 2172 */ 2173 static void 2174 list_hashtable_vars( 2175 hashtab_T *ht, 2176 char_u *prefix, 2177 int empty, 2178 int *first) 2179 { 2180 hashitem_T *hi; 2181 dictitem_T *di; 2182 int todo; 2183 2184 todo = (int)ht->ht_used; 2185 for (hi = ht->ht_array; todo > 0 && !got_int; ++hi) 2186 { 2187 if (!HASHITEM_EMPTY(hi)) 2188 { 2189 --todo; 2190 di = HI2DI(hi); 2191 if (empty || di->di_tv.v_type != VAR_STRING 2192 || di->di_tv.vval.v_string != NULL) 2193 list_one_var(di, prefix, first); 2194 } 2195 } 2196 } 2197 2198 /* 2199 * List global variables. 2200 */ 2201 static void 2202 list_glob_vars(int *first) 2203 { 2204 list_hashtable_vars(&globvarht, (char_u *)"", TRUE, first); 2205 } 2206 2207 /* 2208 * List buffer variables. 2209 */ 2210 static void 2211 list_buf_vars(int *first) 2212 { 2213 char_u numbuf[NUMBUFLEN]; 2214 2215 list_hashtable_vars(&curbuf->b_vars->dv_hashtab, (char_u *)"b:", 2216 TRUE, first); 2217 2218 sprintf((char *)numbuf, "%ld", (long)curbuf->b_changedtick); 2219 list_one_var_a((char_u *)"b:", (char_u *)"changedtick", VAR_NUMBER, 2220 numbuf, first); 2221 } 2222 2223 /* 2224 * List window variables. 2225 */ 2226 static void 2227 list_win_vars(int *first) 2228 { 2229 list_hashtable_vars(&curwin->w_vars->dv_hashtab, 2230 (char_u *)"w:", TRUE, first); 2231 } 2232 2233 #ifdef FEAT_WINDOWS 2234 /* 2235 * List tab page variables. 2236 */ 2237 static void 2238 list_tab_vars(int *first) 2239 { 2240 list_hashtable_vars(&curtab->tp_vars->dv_hashtab, 2241 (char_u *)"t:", TRUE, first); 2242 } 2243 #endif 2244 2245 /* 2246 * List Vim variables. 2247 */ 2248 static void 2249 list_vim_vars(int *first) 2250 { 2251 list_hashtable_vars(&vimvarht, (char_u *)"v:", FALSE, first); 2252 } 2253 2254 /* 2255 * List script-local variables, if there is a script. 2256 */ 2257 static void 2258 list_script_vars(int *first) 2259 { 2260 if (current_SID > 0 && current_SID <= ga_scripts.ga_len) 2261 list_hashtable_vars(&SCRIPT_VARS(current_SID), 2262 (char_u *)"s:", FALSE, first); 2263 } 2264 2265 /* 2266 * List function variables, if there is a function. 2267 */ 2268 static void 2269 list_func_vars(int *first) 2270 { 2271 if (current_funccal != NULL) 2272 list_hashtable_vars(¤t_funccal->l_vars.dv_hashtab, 2273 (char_u *)"l:", FALSE, first); 2274 } 2275 2276 /* 2277 * List variables in "arg". 2278 */ 2279 static char_u * 2280 list_arg_vars(exarg_T *eap, char_u *arg, int *first) 2281 { 2282 int error = FALSE; 2283 int len; 2284 char_u *name; 2285 char_u *name_start; 2286 char_u *arg_subsc; 2287 char_u *tofree; 2288 typval_T tv; 2289 2290 while (!ends_excmd(*arg) && !got_int) 2291 { 2292 if (error || eap->skip) 2293 { 2294 arg = find_name_end(arg, NULL, NULL, FNE_INCL_BR | FNE_CHECK_START); 2295 if (!vim_iswhite(*arg) && !ends_excmd(*arg)) 2296 { 2297 emsg_severe = TRUE; 2298 EMSG(_(e_trailing)); 2299 break; 2300 } 2301 } 2302 else 2303 { 2304 /* get_name_len() takes care of expanding curly braces */ 2305 name_start = name = arg; 2306 len = get_name_len(&arg, &tofree, TRUE, TRUE); 2307 if (len <= 0) 2308 { 2309 /* This is mainly to keep test 49 working: when expanding 2310 * curly braces fails overrule the exception error message. */ 2311 if (len < 0 && !aborting()) 2312 { 2313 emsg_severe = TRUE; 2314 EMSG2(_(e_invarg2), arg); 2315 break; 2316 } 2317 error = TRUE; 2318 } 2319 else 2320 { 2321 if (tofree != NULL) 2322 name = tofree; 2323 if (get_var_tv(name, len, &tv, NULL, TRUE, FALSE) == FAIL) 2324 error = TRUE; 2325 else 2326 { 2327 /* handle d.key, l[idx], f(expr) */ 2328 arg_subsc = arg; 2329 if (handle_subscript(&arg, &tv, TRUE, TRUE) == FAIL) 2330 error = TRUE; 2331 else 2332 { 2333 if (arg == arg_subsc && len == 2 && name[1] == ':') 2334 { 2335 switch (*name) 2336 { 2337 case 'g': list_glob_vars(first); break; 2338 case 'b': list_buf_vars(first); break; 2339 case 'w': list_win_vars(first); break; 2340 #ifdef FEAT_WINDOWS 2341 case 't': list_tab_vars(first); break; 2342 #endif 2343 case 'v': list_vim_vars(first); break; 2344 case 's': list_script_vars(first); break; 2345 case 'l': list_func_vars(first); break; 2346 default: 2347 EMSG2(_("E738: Can't list variables for %s"), name); 2348 } 2349 } 2350 else 2351 { 2352 char_u numbuf[NUMBUFLEN]; 2353 char_u *tf; 2354 int c; 2355 char_u *s; 2356 2357 s = echo_string(&tv, &tf, numbuf, 0); 2358 c = *arg; 2359 *arg = NUL; 2360 list_one_var_a((char_u *)"", 2361 arg == arg_subsc ? name : name_start, 2362 tv.v_type, 2363 s == NULL ? (char_u *)"" : s, 2364 first); 2365 *arg = c; 2366 vim_free(tf); 2367 } 2368 clear_tv(&tv); 2369 } 2370 } 2371 } 2372 2373 vim_free(tofree); 2374 } 2375 2376 arg = skipwhite(arg); 2377 } 2378 2379 return arg; 2380 } 2381 2382 /* 2383 * Set one item of ":let var = expr" or ":let [v1, v2] = list" to its value. 2384 * Returns a pointer to the char just after the var name. 2385 * Returns NULL if there is an error. 2386 */ 2387 static char_u * 2388 ex_let_one( 2389 char_u *arg, /* points to variable name */ 2390 typval_T *tv, /* value to assign to variable */ 2391 int copy, /* copy value from "tv" */ 2392 char_u *endchars, /* valid chars after variable name or NULL */ 2393 char_u *op) /* "+", "-", "." or NULL*/ 2394 { 2395 int c1; 2396 char_u *name; 2397 char_u *p; 2398 char_u *arg_end = NULL; 2399 int len; 2400 int opt_flags; 2401 char_u *tofree = NULL; 2402 2403 /* 2404 * ":let $VAR = expr": Set environment variable. 2405 */ 2406 if (*arg == '$') 2407 { 2408 /* Find the end of the name. */ 2409 ++arg; 2410 name = arg; 2411 len = get_env_len(&arg); 2412 if (len == 0) 2413 EMSG2(_(e_invarg2), name - 1); 2414 else 2415 { 2416 if (op != NULL && (*op == '+' || *op == '-')) 2417 EMSG2(_(e_letwrong), op); 2418 else if (endchars != NULL 2419 && vim_strchr(endchars, *skipwhite(arg)) == NULL) 2420 EMSG(_(e_letunexp)); 2421 else if (!check_secure()) 2422 { 2423 c1 = name[len]; 2424 name[len] = NUL; 2425 p = get_tv_string_chk(tv); 2426 if (p != NULL && op != NULL && *op == '.') 2427 { 2428 int mustfree = FALSE; 2429 char_u *s = vim_getenv(name, &mustfree); 2430 2431 if (s != NULL) 2432 { 2433 p = tofree = concat_str(s, p); 2434 if (mustfree) 2435 vim_free(s); 2436 } 2437 } 2438 if (p != NULL) 2439 { 2440 vim_setenv(name, p); 2441 if (STRICMP(name, "HOME") == 0) 2442 init_homedir(); 2443 else if (didset_vim && STRICMP(name, "VIM") == 0) 2444 didset_vim = FALSE; 2445 else if (didset_vimruntime 2446 && STRICMP(name, "VIMRUNTIME") == 0) 2447 didset_vimruntime = FALSE; 2448 arg_end = arg; 2449 } 2450 name[len] = c1; 2451 vim_free(tofree); 2452 } 2453 } 2454 } 2455 2456 /* 2457 * ":let &option = expr": Set option value. 2458 * ":let &l:option = expr": Set local option value. 2459 * ":let &g:option = expr": Set global option value. 2460 */ 2461 else if (*arg == '&') 2462 { 2463 /* Find the end of the name. */ 2464 p = find_option_end(&arg, &opt_flags); 2465 if (p == NULL || (endchars != NULL 2466 && vim_strchr(endchars, *skipwhite(p)) == NULL)) 2467 EMSG(_(e_letunexp)); 2468 else 2469 { 2470 long n; 2471 int opt_type; 2472 long numval; 2473 char_u *stringval = NULL; 2474 char_u *s; 2475 2476 c1 = *p; 2477 *p = NUL; 2478 2479 n = get_tv_number(tv); 2480 s = get_tv_string_chk(tv); /* != NULL if number or string */ 2481 if (s != NULL && op != NULL && *op != '=') 2482 { 2483 opt_type = get_option_value(arg, &numval, 2484 &stringval, opt_flags); 2485 if ((opt_type == 1 && *op == '.') 2486 || (opt_type == 0 && *op != '.')) 2487 EMSG2(_(e_letwrong), op); 2488 else 2489 { 2490 if (opt_type == 1) /* number */ 2491 { 2492 if (*op == '+') 2493 n = numval + n; 2494 else 2495 n = numval - n; 2496 } 2497 else if (opt_type == 0 && stringval != NULL) /* string */ 2498 { 2499 s = concat_str(stringval, s); 2500 vim_free(stringval); 2501 stringval = s; 2502 } 2503 } 2504 } 2505 if (s != NULL) 2506 { 2507 set_option_value(arg, n, s, opt_flags); 2508 arg_end = p; 2509 } 2510 *p = c1; 2511 vim_free(stringval); 2512 } 2513 } 2514 2515 /* 2516 * ":let @r = expr": Set register contents. 2517 */ 2518 else if (*arg == '@') 2519 { 2520 ++arg; 2521 if (op != NULL && (*op == '+' || *op == '-')) 2522 EMSG2(_(e_letwrong), op); 2523 else if (endchars != NULL 2524 && vim_strchr(endchars, *skipwhite(arg + 1)) == NULL) 2525 EMSG(_(e_letunexp)); 2526 else 2527 { 2528 char_u *ptofree = NULL; 2529 char_u *s; 2530 2531 p = get_tv_string_chk(tv); 2532 if (p != NULL && op != NULL && *op == '.') 2533 { 2534 s = get_reg_contents(*arg == '@' ? '"' : *arg, GREG_EXPR_SRC); 2535 if (s != NULL) 2536 { 2537 p = ptofree = concat_str(s, p); 2538 vim_free(s); 2539 } 2540 } 2541 if (p != NULL) 2542 { 2543 write_reg_contents(*arg == '@' ? '"' : *arg, p, -1, FALSE); 2544 arg_end = arg + 1; 2545 } 2546 vim_free(ptofree); 2547 } 2548 } 2549 2550 /* 2551 * ":let var = expr": Set internal variable. 2552 * ":let {expr} = expr": Idem, name made with curly braces 2553 */ 2554 else if (eval_isnamec1(*arg) || *arg == '{') 2555 { 2556 lval_T lv; 2557 2558 p = get_lval(arg, tv, &lv, FALSE, FALSE, 0, FNE_CHECK_START); 2559 if (p != NULL && lv.ll_name != NULL) 2560 { 2561 if (endchars != NULL && vim_strchr(endchars, *skipwhite(p)) == NULL) 2562 EMSG(_(e_letunexp)); 2563 else 2564 { 2565 set_var_lval(&lv, p, tv, copy, op); 2566 arg_end = p; 2567 } 2568 } 2569 clear_lval(&lv); 2570 } 2571 2572 else 2573 EMSG2(_(e_invarg2), arg); 2574 2575 return arg_end; 2576 } 2577 2578 /* 2579 * If "arg" is equal to "b:changedtick" give an error and return TRUE. 2580 */ 2581 static int 2582 check_changedtick(char_u *arg) 2583 { 2584 if (STRNCMP(arg, "b:changedtick", 13) == 0 && !eval_isnamec(arg[13])) 2585 { 2586 EMSG2(_(e_readonlyvar), arg); 2587 return TRUE; 2588 } 2589 return FALSE; 2590 } 2591 2592 /* 2593 * Get an lval: variable, Dict item or List item that can be assigned a value 2594 * to: "name", "na{me}", "name[expr]", "name[expr:expr]", "name[expr][expr]", 2595 * "name.key", "name.key[expr]" etc. 2596 * Indexing only works if "name" is an existing List or Dictionary. 2597 * "name" points to the start of the name. 2598 * If "rettv" is not NULL it points to the value to be assigned. 2599 * "unlet" is TRUE for ":unlet": slightly different behavior when something is 2600 * wrong; must end in space or cmd separator. 2601 * 2602 * flags: 2603 * GLV_QUIET: do not give error messages 2604 * GLV_NO_AUTOLOAD: do not use script autoloading 2605 * 2606 * Returns a pointer to just after the name, including indexes. 2607 * When an evaluation error occurs "lp->ll_name" is NULL; 2608 * Returns NULL for a parsing error. Still need to free items in "lp"! 2609 */ 2610 static char_u * 2611 get_lval( 2612 char_u *name, 2613 typval_T *rettv, 2614 lval_T *lp, 2615 int unlet, 2616 int skip, 2617 int flags, /* GLV_ values */ 2618 int fne_flags) /* flags for find_name_end() */ 2619 { 2620 char_u *p; 2621 char_u *expr_start, *expr_end; 2622 int cc; 2623 dictitem_T *v; 2624 typval_T var1; 2625 typval_T var2; 2626 int empty1 = FALSE; 2627 listitem_T *ni; 2628 char_u *key = NULL; 2629 int len; 2630 hashtab_T *ht; 2631 int quiet = flags & GLV_QUIET; 2632 2633 /* Clear everything in "lp". */ 2634 vim_memset(lp, 0, sizeof(lval_T)); 2635 2636 if (skip) 2637 { 2638 /* When skipping just find the end of the name. */ 2639 lp->ll_name = name; 2640 return find_name_end(name, NULL, NULL, FNE_INCL_BR | fne_flags); 2641 } 2642 2643 /* Find the end of the name. */ 2644 p = find_name_end(name, &expr_start, &expr_end, fne_flags); 2645 if (expr_start != NULL) 2646 { 2647 /* Don't expand the name when we already know there is an error. */ 2648 if (unlet && !vim_iswhite(*p) && !ends_excmd(*p) 2649 && *p != '[' && *p != '.') 2650 { 2651 EMSG(_(e_trailing)); 2652 return NULL; 2653 } 2654 2655 lp->ll_exp_name = make_expanded_name(name, expr_start, expr_end, p); 2656 if (lp->ll_exp_name == NULL) 2657 { 2658 /* Report an invalid expression in braces, unless the 2659 * expression evaluation has been cancelled due to an 2660 * aborting error, an interrupt, or an exception. */ 2661 if (!aborting() && !quiet) 2662 { 2663 emsg_severe = TRUE; 2664 EMSG2(_(e_invarg2), name); 2665 return NULL; 2666 } 2667 } 2668 lp->ll_name = lp->ll_exp_name; 2669 } 2670 else 2671 lp->ll_name = name; 2672 2673 /* Without [idx] or .key we are done. */ 2674 if ((*p != '[' && *p != '.') || lp->ll_name == NULL) 2675 return p; 2676 2677 cc = *p; 2678 *p = NUL; 2679 v = find_var(lp->ll_name, &ht, flags & GLV_NO_AUTOLOAD); 2680 if (v == NULL && !quiet) 2681 EMSG2(_(e_undefvar), lp->ll_name); 2682 *p = cc; 2683 if (v == NULL) 2684 return NULL; 2685 2686 /* 2687 * Loop until no more [idx] or .key is following. 2688 */ 2689 lp->ll_tv = &v->di_tv; 2690 while (*p == '[' || (*p == '.' && lp->ll_tv->v_type == VAR_DICT)) 2691 { 2692 if (!(lp->ll_tv->v_type == VAR_LIST && lp->ll_tv->vval.v_list != NULL) 2693 && !(lp->ll_tv->v_type == VAR_DICT 2694 && lp->ll_tv->vval.v_dict != NULL)) 2695 { 2696 if (!quiet) 2697 EMSG(_("E689: Can only index a List or Dictionary")); 2698 return NULL; 2699 } 2700 if (lp->ll_range) 2701 { 2702 if (!quiet) 2703 EMSG(_("E708: [:] must come last")); 2704 return NULL; 2705 } 2706 2707 len = -1; 2708 if (*p == '.') 2709 { 2710 key = p + 1; 2711 for (len = 0; ASCII_ISALNUM(key[len]) || key[len] == '_'; ++len) 2712 ; 2713 if (len == 0) 2714 { 2715 if (!quiet) 2716 EMSG(_(e_emptykey)); 2717 return NULL; 2718 } 2719 p = key + len; 2720 } 2721 else 2722 { 2723 /* Get the index [expr] or the first index [expr: ]. */ 2724 p = skipwhite(p + 1); 2725 if (*p == ':') 2726 empty1 = TRUE; 2727 else 2728 { 2729 empty1 = FALSE; 2730 if (eval1(&p, &var1, TRUE) == FAIL) /* recursive! */ 2731 return NULL; 2732 if (get_tv_string_chk(&var1) == NULL) 2733 { 2734 /* not a number or string */ 2735 clear_tv(&var1); 2736 return NULL; 2737 } 2738 } 2739 2740 /* Optionally get the second index [ :expr]. */ 2741 if (*p == ':') 2742 { 2743 if (lp->ll_tv->v_type == VAR_DICT) 2744 { 2745 if (!quiet) 2746 EMSG(_(e_dictrange)); 2747 if (!empty1) 2748 clear_tv(&var1); 2749 return NULL; 2750 } 2751 if (rettv != NULL && (rettv->v_type != VAR_LIST 2752 || rettv->vval.v_list == NULL)) 2753 { 2754 if (!quiet) 2755 EMSG(_("E709: [:] requires a List value")); 2756 if (!empty1) 2757 clear_tv(&var1); 2758 return NULL; 2759 } 2760 p = skipwhite(p + 1); 2761 if (*p == ']') 2762 lp->ll_empty2 = TRUE; 2763 else 2764 { 2765 lp->ll_empty2 = FALSE; 2766 if (eval1(&p, &var2, TRUE) == FAIL) /* recursive! */ 2767 { 2768 if (!empty1) 2769 clear_tv(&var1); 2770 return NULL; 2771 } 2772 if (get_tv_string_chk(&var2) == NULL) 2773 { 2774 /* not a number or string */ 2775 if (!empty1) 2776 clear_tv(&var1); 2777 clear_tv(&var2); 2778 return NULL; 2779 } 2780 } 2781 lp->ll_range = TRUE; 2782 } 2783 else 2784 lp->ll_range = FALSE; 2785 2786 if (*p != ']') 2787 { 2788 if (!quiet) 2789 EMSG(_(e_missbrac)); 2790 if (!empty1) 2791 clear_tv(&var1); 2792 if (lp->ll_range && !lp->ll_empty2) 2793 clear_tv(&var2); 2794 return NULL; 2795 } 2796 2797 /* Skip to past ']'. */ 2798 ++p; 2799 } 2800 2801 if (lp->ll_tv->v_type == VAR_DICT) 2802 { 2803 if (len == -1) 2804 { 2805 /* "[key]": get key from "var1" */ 2806 key = get_tv_string_chk(&var1); /* is number or string */ 2807 if (key == NULL) 2808 { 2809 clear_tv(&var1); 2810 return NULL; 2811 } 2812 } 2813 lp->ll_list = NULL; 2814 lp->ll_dict = lp->ll_tv->vval.v_dict; 2815 lp->ll_di = dict_find(lp->ll_dict, key, len); 2816 2817 /* When assigning to a scope dictionary check that a function and 2818 * variable name is valid (only variable name unless it is l: or 2819 * g: dictionary). Disallow overwriting a builtin function. */ 2820 if (rettv != NULL && lp->ll_dict->dv_scope != 0) 2821 { 2822 int prevval; 2823 int wrong; 2824 2825 if (len != -1) 2826 { 2827 prevval = key[len]; 2828 key[len] = NUL; 2829 } 2830 else 2831 prevval = 0; /* avoid compiler warning */ 2832 wrong = (lp->ll_dict->dv_scope == VAR_DEF_SCOPE 2833 && rettv->v_type == VAR_FUNC 2834 && var_check_func_name(key, lp->ll_di == NULL)) 2835 || !valid_varname(key); 2836 if (len != -1) 2837 key[len] = prevval; 2838 if (wrong) 2839 return NULL; 2840 } 2841 2842 if (lp->ll_di == NULL) 2843 { 2844 /* Can't add "v:" variable. */ 2845 if (lp->ll_dict == &vimvardict) 2846 { 2847 EMSG2(_(e_illvar), name); 2848 return NULL; 2849 } 2850 2851 /* Key does not exist in dict: may need to add it. */ 2852 if (*p == '[' || *p == '.' || unlet) 2853 { 2854 if (!quiet) 2855 EMSG2(_(e_dictkey), key); 2856 if (len == -1) 2857 clear_tv(&var1); 2858 return NULL; 2859 } 2860 if (len == -1) 2861 lp->ll_newkey = vim_strsave(key); 2862 else 2863 lp->ll_newkey = vim_strnsave(key, len); 2864 if (len == -1) 2865 clear_tv(&var1); 2866 if (lp->ll_newkey == NULL) 2867 p = NULL; 2868 break; 2869 } 2870 /* existing variable, need to check if it can be changed */ 2871 else if (var_check_ro(lp->ll_di->di_flags, name, FALSE)) 2872 return NULL; 2873 2874 if (len == -1) 2875 clear_tv(&var1); 2876 lp->ll_tv = &lp->ll_di->di_tv; 2877 } 2878 else 2879 { 2880 /* 2881 * Get the number and item for the only or first index of the List. 2882 */ 2883 if (empty1) 2884 lp->ll_n1 = 0; 2885 else 2886 { 2887 lp->ll_n1 = get_tv_number(&var1); /* is number or string */ 2888 clear_tv(&var1); 2889 } 2890 lp->ll_dict = NULL; 2891 lp->ll_list = lp->ll_tv->vval.v_list; 2892 lp->ll_li = list_find(lp->ll_list, lp->ll_n1); 2893 if (lp->ll_li == NULL) 2894 { 2895 if (lp->ll_n1 < 0) 2896 { 2897 lp->ll_n1 = 0; 2898 lp->ll_li = list_find(lp->ll_list, lp->ll_n1); 2899 } 2900 } 2901 if (lp->ll_li == NULL) 2902 { 2903 if (lp->ll_range && !lp->ll_empty2) 2904 clear_tv(&var2); 2905 if (!quiet) 2906 EMSGN(_(e_listidx), lp->ll_n1); 2907 return NULL; 2908 } 2909 2910 /* 2911 * May need to find the item or absolute index for the second 2912 * index of a range. 2913 * When no index given: "lp->ll_empty2" is TRUE. 2914 * Otherwise "lp->ll_n2" is set to the second index. 2915 */ 2916 if (lp->ll_range && !lp->ll_empty2) 2917 { 2918 lp->ll_n2 = get_tv_number(&var2); /* is number or string */ 2919 clear_tv(&var2); 2920 if (lp->ll_n2 < 0) 2921 { 2922 ni = list_find(lp->ll_list, lp->ll_n2); 2923 if (ni == NULL) 2924 { 2925 if (!quiet) 2926 EMSGN(_(e_listidx), lp->ll_n2); 2927 return NULL; 2928 } 2929 lp->ll_n2 = list_idx_of_item(lp->ll_list, ni); 2930 } 2931 2932 /* Check that lp->ll_n2 isn't before lp->ll_n1. */ 2933 if (lp->ll_n1 < 0) 2934 lp->ll_n1 = list_idx_of_item(lp->ll_list, lp->ll_li); 2935 if (lp->ll_n2 < lp->ll_n1) 2936 { 2937 if (!quiet) 2938 EMSGN(_(e_listidx), lp->ll_n2); 2939 return NULL; 2940 } 2941 } 2942 2943 lp->ll_tv = &lp->ll_li->li_tv; 2944 } 2945 } 2946 2947 return p; 2948 } 2949 2950 /* 2951 * Clear lval "lp" that was filled by get_lval(). 2952 */ 2953 static void 2954 clear_lval(lval_T *lp) 2955 { 2956 vim_free(lp->ll_exp_name); 2957 vim_free(lp->ll_newkey); 2958 } 2959 2960 /* 2961 * Set a variable that was parsed by get_lval() to "rettv". 2962 * "endp" points to just after the parsed name. 2963 * "op" is NULL, "+" for "+=", "-" for "-=", "." for ".=" or "=" for "=". 2964 */ 2965 static void 2966 set_var_lval( 2967 lval_T *lp, 2968 char_u *endp, 2969 typval_T *rettv, 2970 int copy, 2971 char_u *op) 2972 { 2973 int cc; 2974 listitem_T *ri; 2975 dictitem_T *di; 2976 2977 if (lp->ll_tv == NULL) 2978 { 2979 if (!check_changedtick(lp->ll_name)) 2980 { 2981 cc = *endp; 2982 *endp = NUL; 2983 if (op != NULL && *op != '=') 2984 { 2985 typval_T tv; 2986 2987 /* handle +=, -= and .= */ 2988 di = NULL; 2989 if (get_var_tv(lp->ll_name, (int)STRLEN(lp->ll_name), 2990 &tv, &di, TRUE, FALSE) == OK) 2991 { 2992 if ((di == NULL 2993 || (!var_check_ro(di->di_flags, lp->ll_name, FALSE) 2994 && !tv_check_lock(di->di_tv.v_lock, lp->ll_name, 2995 FALSE))) 2996 && tv_op(&tv, rettv, op) == OK) 2997 set_var(lp->ll_name, &tv, FALSE); 2998 clear_tv(&tv); 2999 } 3000 } 3001 else 3002 set_var(lp->ll_name, rettv, copy); 3003 *endp = cc; 3004 } 3005 } 3006 else if (tv_check_lock(lp->ll_newkey == NULL 3007 ? lp->ll_tv->v_lock 3008 : lp->ll_tv->vval.v_dict->dv_lock, lp->ll_name, FALSE)) 3009 ; 3010 else if (lp->ll_range) 3011 { 3012 listitem_T *ll_li = lp->ll_li; 3013 int ll_n1 = lp->ll_n1; 3014 3015 /* 3016 * Check whether any of the list items is locked 3017 */ 3018 for (ri = rettv->vval.v_list->lv_first; ri != NULL && ll_li != NULL; ) 3019 { 3020 if (tv_check_lock(ll_li->li_tv.v_lock, lp->ll_name, FALSE)) 3021 return; 3022 ri = ri->li_next; 3023 if (ri == NULL || (!lp->ll_empty2 && lp->ll_n2 == ll_n1)) 3024 break; 3025 ll_li = ll_li->li_next; 3026 ++ll_n1; 3027 } 3028 3029 /* 3030 * Assign the List values to the list items. 3031 */ 3032 for (ri = rettv->vval.v_list->lv_first; ri != NULL; ) 3033 { 3034 if (op != NULL && *op != '=') 3035 tv_op(&lp->ll_li->li_tv, &ri->li_tv, op); 3036 else 3037 { 3038 clear_tv(&lp->ll_li->li_tv); 3039 copy_tv(&ri->li_tv, &lp->ll_li->li_tv); 3040 } 3041 ri = ri->li_next; 3042 if (ri == NULL || (!lp->ll_empty2 && lp->ll_n2 == lp->ll_n1)) 3043 break; 3044 if (lp->ll_li->li_next == NULL) 3045 { 3046 /* Need to add an empty item. */ 3047 if (list_append_number(lp->ll_list, 0) == FAIL) 3048 { 3049 ri = NULL; 3050 break; 3051 } 3052 } 3053 lp->ll_li = lp->ll_li->li_next; 3054 ++lp->ll_n1; 3055 } 3056 if (ri != NULL) 3057 EMSG(_("E710: List value has more items than target")); 3058 else if (lp->ll_empty2 3059 ? (lp->ll_li != NULL && lp->ll_li->li_next != NULL) 3060 : lp->ll_n1 != lp->ll_n2) 3061 EMSG(_("E711: List value has not enough items")); 3062 } 3063 else 3064 { 3065 /* 3066 * Assign to a List or Dictionary item. 3067 */ 3068 if (lp->ll_newkey != NULL) 3069 { 3070 if (op != NULL && *op != '=') 3071 { 3072 EMSG2(_(e_letwrong), op); 3073 return; 3074 } 3075 3076 /* Need to add an item to the Dictionary. */ 3077 di = dictitem_alloc(lp->ll_newkey); 3078 if (di == NULL) 3079 return; 3080 if (dict_add(lp->ll_tv->vval.v_dict, di) == FAIL) 3081 { 3082 vim_free(di); 3083 return; 3084 } 3085 lp->ll_tv = &di->di_tv; 3086 } 3087 else if (op != NULL && *op != '=') 3088 { 3089 tv_op(lp->ll_tv, rettv, op); 3090 return; 3091 } 3092 else 3093 clear_tv(lp->ll_tv); 3094 3095 /* 3096 * Assign the value to the variable or list item. 3097 */ 3098 if (copy) 3099 copy_tv(rettv, lp->ll_tv); 3100 else 3101 { 3102 *lp->ll_tv = *rettv; 3103 lp->ll_tv->v_lock = 0; 3104 init_tv(rettv); 3105 } 3106 } 3107 } 3108 3109 /* 3110 * Handle "tv1 += tv2", "tv1 -= tv2" and "tv1 .= tv2" 3111 * Returns OK or FAIL. 3112 */ 3113 static int 3114 tv_op(typval_T *tv1, typval_T *tv2, char_u *op) 3115 { 3116 long n; 3117 char_u numbuf[NUMBUFLEN]; 3118 char_u *s; 3119 3120 /* Can't do anything with a Funcref, Dict, v:true on the right. */ 3121 if (tv2->v_type != VAR_FUNC && tv2->v_type != VAR_DICT 3122 && tv2->v_type != VAR_SPECIAL) 3123 { 3124 switch (tv1->v_type) 3125 { 3126 case VAR_UNKNOWN: 3127 case VAR_DICT: 3128 case VAR_FUNC: 3129 case VAR_PARTIAL: 3130 case VAR_SPECIAL: 3131 case VAR_JOB: 3132 case VAR_CHANNEL: 3133 break; 3134 3135 case VAR_LIST: 3136 if (*op != '+' || tv2->v_type != VAR_LIST) 3137 break; 3138 /* List += List */ 3139 if (tv1->vval.v_list != NULL && tv2->vval.v_list != NULL) 3140 list_extend(tv1->vval.v_list, tv2->vval.v_list, NULL); 3141 return OK; 3142 3143 case VAR_NUMBER: 3144 case VAR_STRING: 3145 if (tv2->v_type == VAR_LIST) 3146 break; 3147 if (*op == '+' || *op == '-') 3148 { 3149 /* nr += nr or nr -= nr*/ 3150 n = get_tv_number(tv1); 3151 #ifdef FEAT_FLOAT 3152 if (tv2->v_type == VAR_FLOAT) 3153 { 3154 float_T f = n; 3155 3156 if (*op == '+') 3157 f += tv2->vval.v_float; 3158 else 3159 f -= tv2->vval.v_float; 3160 clear_tv(tv1); 3161 tv1->v_type = VAR_FLOAT; 3162 tv1->vval.v_float = f; 3163 } 3164 else 3165 #endif 3166 { 3167 if (*op == '+') 3168 n += get_tv_number(tv2); 3169 else 3170 n -= get_tv_number(tv2); 3171 clear_tv(tv1); 3172 tv1->v_type = VAR_NUMBER; 3173 tv1->vval.v_number = n; 3174 } 3175 } 3176 else 3177 { 3178 if (tv2->v_type == VAR_FLOAT) 3179 break; 3180 3181 /* str .= str */ 3182 s = get_tv_string(tv1); 3183 s = concat_str(s, get_tv_string_buf(tv2, numbuf)); 3184 clear_tv(tv1); 3185 tv1->v_type = VAR_STRING; 3186 tv1->vval.v_string = s; 3187 } 3188 return OK; 3189 3190 case VAR_FLOAT: 3191 #ifdef FEAT_FLOAT 3192 { 3193 float_T f; 3194 3195 if (*op == '.' || (tv2->v_type != VAR_FLOAT 3196 && tv2->v_type != VAR_NUMBER 3197 && tv2->v_type != VAR_STRING)) 3198 break; 3199 if (tv2->v_type == VAR_FLOAT) 3200 f = tv2->vval.v_float; 3201 else 3202 f = get_tv_number(tv2); 3203 if (*op == '+') 3204 tv1->vval.v_float += f; 3205 else 3206 tv1->vval.v_float -= f; 3207 } 3208 #endif 3209 return OK; 3210 } 3211 } 3212 3213 EMSG2(_(e_letwrong), op); 3214 return FAIL; 3215 } 3216 3217 /* 3218 * Add a watcher to a list. 3219 */ 3220 void 3221 list_add_watch(list_T *l, listwatch_T *lw) 3222 { 3223 lw->lw_next = l->lv_watch; 3224 l->lv_watch = lw; 3225 } 3226 3227 /* 3228 * Remove a watcher from a list. 3229 * No warning when it isn't found... 3230 */ 3231 void 3232 list_rem_watch(list_T *l, listwatch_T *lwrem) 3233 { 3234 listwatch_T *lw, **lwp; 3235 3236 lwp = &l->lv_watch; 3237 for (lw = l->lv_watch; lw != NULL; lw = lw->lw_next) 3238 { 3239 if (lw == lwrem) 3240 { 3241 *lwp = lw->lw_next; 3242 break; 3243 } 3244 lwp = &lw->lw_next; 3245 } 3246 } 3247 3248 /* 3249 * Just before removing an item from a list: advance watchers to the next 3250 * item. 3251 */ 3252 static void 3253 list_fix_watch(list_T *l, listitem_T *item) 3254 { 3255 listwatch_T *lw; 3256 3257 for (lw = l->lv_watch; lw != NULL; lw = lw->lw_next) 3258 if (lw->lw_item == item) 3259 lw->lw_item = item->li_next; 3260 } 3261 3262 /* 3263 * Evaluate the expression used in a ":for var in expr" command. 3264 * "arg" points to "var". 3265 * Set "*errp" to TRUE for an error, FALSE otherwise; 3266 * Return a pointer that holds the info. Null when there is an error. 3267 */ 3268 void * 3269 eval_for_line( 3270 char_u *arg, 3271 int *errp, 3272 char_u **nextcmdp, 3273 int skip) 3274 { 3275 forinfo_T *fi; 3276 char_u *expr; 3277 typval_T tv; 3278 list_T *l; 3279 3280 *errp = TRUE; /* default: there is an error */ 3281 3282 fi = (forinfo_T *)alloc_clear(sizeof(forinfo_T)); 3283 if (fi == NULL) 3284 return NULL; 3285 3286 expr = skip_var_list(arg, &fi->fi_varcount, &fi->fi_semicolon); 3287 if (expr == NULL) 3288 return fi; 3289 3290 expr = skipwhite(expr); 3291 if (expr[0] != 'i' || expr[1] != 'n' || !vim_iswhite(expr[2])) 3292 { 3293 EMSG(_("E690: Missing \"in\" after :for")); 3294 return fi; 3295 } 3296 3297 if (skip) 3298 ++emsg_skip; 3299 if (eval0(skipwhite(expr + 2), &tv, nextcmdp, !skip) == OK) 3300 { 3301 *errp = FALSE; 3302 if (!skip) 3303 { 3304 l = tv.vval.v_list; 3305 if (tv.v_type != VAR_LIST) 3306 { 3307 EMSG(_(e_listreq)); 3308 clear_tv(&tv); 3309 } 3310 else if (l == NULL) 3311 { 3312 /* a null list is like an empty list: do nothing */ 3313 clear_tv(&tv); 3314 } 3315 else 3316 { 3317 /* No need to increment the refcount, it's already set for the 3318 * list being used in "tv". */ 3319 fi->fi_list = l; 3320 list_add_watch(l, &fi->fi_lw); 3321 fi->fi_lw.lw_item = l->lv_first; 3322 } 3323 } 3324 } 3325 if (skip) 3326 --emsg_skip; 3327 3328 return fi; 3329 } 3330 3331 /* 3332 * Use the first item in a ":for" list. Advance to the next. 3333 * Assign the values to the variable (list). "arg" points to the first one. 3334 * Return TRUE when a valid item was found, FALSE when at end of list or 3335 * something wrong. 3336 */ 3337 int 3338 next_for_item(void *fi_void, char_u *arg) 3339 { 3340 forinfo_T *fi = (forinfo_T *)fi_void; 3341 int result; 3342 listitem_T *item; 3343 3344 item = fi->fi_lw.lw_item; 3345 if (item == NULL) 3346 result = FALSE; 3347 else 3348 { 3349 fi->fi_lw.lw_item = item->li_next; 3350 result = (ex_let_vars(arg, &item->li_tv, TRUE, 3351 fi->fi_semicolon, fi->fi_varcount, NULL) == OK); 3352 } 3353 return result; 3354 } 3355 3356 /* 3357 * Free the structure used to store info used by ":for". 3358 */ 3359 void 3360 free_for_info(void *fi_void) 3361 { 3362 forinfo_T *fi = (forinfo_T *)fi_void; 3363 3364 if (fi != NULL && fi->fi_list != NULL) 3365 { 3366 list_rem_watch(fi->fi_list, &fi->fi_lw); 3367 list_unref(fi->fi_list); 3368 } 3369 vim_free(fi); 3370 } 3371 3372 #if defined(FEAT_CMDL_COMPL) || defined(PROTO) 3373 3374 void 3375 set_context_for_expression( 3376 expand_T *xp, 3377 char_u *arg, 3378 cmdidx_T cmdidx) 3379 { 3380 int got_eq = FALSE; 3381 int c; 3382 char_u *p; 3383 3384 if (cmdidx == CMD_let) 3385 { 3386 xp->xp_context = EXPAND_USER_VARS; 3387 if (vim_strpbrk(arg, (char_u *)"\"'+-*/%.=!?~|&$([<>,#") == NULL) 3388 { 3389 /* ":let var1 var2 ...": find last space. */ 3390 for (p = arg + STRLEN(arg); p >= arg; ) 3391 { 3392 xp->xp_pattern = p; 3393 mb_ptr_back(arg, p); 3394 if (vim_iswhite(*p)) 3395 break; 3396 } 3397 return; 3398 } 3399 } 3400 else 3401 xp->xp_context = cmdidx == CMD_call ? EXPAND_FUNCTIONS 3402 : EXPAND_EXPRESSION; 3403 while ((xp->xp_pattern = vim_strpbrk(arg, 3404 (char_u *)"\"'+-*/%.=!?~|&$([<>,#")) != NULL) 3405 { 3406 c = *xp->xp_pattern; 3407 if (c == '&') 3408 { 3409 c = xp->xp_pattern[1]; 3410 if (c == '&') 3411 { 3412 ++xp->xp_pattern; 3413 xp->xp_context = cmdidx != CMD_let || got_eq 3414 ? EXPAND_EXPRESSION : EXPAND_NOTHING; 3415 } 3416 else if (c != ' ') 3417 { 3418 xp->xp_context = EXPAND_SETTINGS; 3419 if ((c == 'l' || c == 'g') && xp->xp_pattern[2] == ':') 3420 xp->xp_pattern += 2; 3421 3422 } 3423 } 3424 else if (c == '$') 3425 { 3426 /* environment variable */ 3427 xp->xp_context = EXPAND_ENV_VARS; 3428 } 3429 else if (c == '=') 3430 { 3431 got_eq = TRUE; 3432 xp->xp_context = EXPAND_EXPRESSION; 3433 } 3434 else if (c == '#' 3435 && xp->xp_context == EXPAND_EXPRESSION) 3436 { 3437 /* Autoload function/variable contains '#'. */ 3438 break; 3439 } 3440 else if ((c == '<' || c == '#') 3441 && xp->xp_context == EXPAND_FUNCTIONS 3442 && vim_strchr(xp->xp_pattern, '(') == NULL) 3443 { 3444 /* Function name can start with "<SNR>" and contain '#'. */ 3445 break; 3446 } 3447 else if (cmdidx != CMD_let || got_eq) 3448 { 3449 if (c == '"') /* string */ 3450 { 3451 while ((c = *++xp->xp_pattern) != NUL && c != '"') 3452 if (c == '\\' && xp->xp_pattern[1] != NUL) 3453 ++xp->xp_pattern; 3454 xp->xp_context = EXPAND_NOTHING; 3455 } 3456 else if (c == '\'') /* literal string */ 3457 { 3458 /* Trick: '' is like stopping and starting a literal string. */ 3459 while ((c = *++xp->xp_pattern) != NUL && c != '\'') 3460 /* skip */ ; 3461 xp->xp_context = EXPAND_NOTHING; 3462 } 3463 else if (c == '|') 3464 { 3465 if (xp->xp_pattern[1] == '|') 3466 { 3467 ++xp->xp_pattern; 3468 xp->xp_context = EXPAND_EXPRESSION; 3469 } 3470 else 3471 xp->xp_context = EXPAND_COMMANDS; 3472 } 3473 else 3474 xp->xp_context = EXPAND_EXPRESSION; 3475 } 3476 else 3477 /* Doesn't look like something valid, expand as an expression 3478 * anyway. */ 3479 xp->xp_context = EXPAND_EXPRESSION; 3480 arg = xp->xp_pattern; 3481 if (*arg != NUL) 3482 while ((c = *++arg) != NUL && (c == ' ' || c == '\t')) 3483 /* skip */ ; 3484 } 3485 xp->xp_pattern = arg; 3486 } 3487 3488 #endif /* FEAT_CMDL_COMPL */ 3489 3490 /* 3491 * ":1,25call func(arg1, arg2)" function call. 3492 */ 3493 void 3494 ex_call(exarg_T *eap) 3495 { 3496 char_u *arg = eap->arg; 3497 char_u *startarg; 3498 char_u *name; 3499 char_u *tofree; 3500 int len; 3501 typval_T rettv; 3502 linenr_T lnum; 3503 int doesrange; 3504 int failed = FALSE; 3505 funcdict_T fudi; 3506 partial_T *partial = NULL; 3507 3508 if (eap->skip) 3509 { 3510 /* trans_function_name() doesn't work well when skipping, use eval0() 3511 * instead to skip to any following command, e.g. for: 3512 * :if 0 | call dict.foo().bar() | endif */ 3513 ++emsg_skip; 3514 if (eval0(eap->arg, &rettv, &eap->nextcmd, FALSE) != FAIL) 3515 clear_tv(&rettv); 3516 --emsg_skip; 3517 return; 3518 } 3519 3520 tofree = trans_function_name(&arg, eap->skip, TFN_INT, &fudi, &partial); 3521 if (fudi.fd_newkey != NULL) 3522 { 3523 /* Still need to give an error message for missing key. */ 3524 EMSG2(_(e_dictkey), fudi.fd_newkey); 3525 vim_free(fudi.fd_newkey); 3526 } 3527 if (tofree == NULL) 3528 return; 3529 3530 /* Increase refcount on dictionary, it could get deleted when evaluating 3531 * the arguments. */ 3532 if (fudi.fd_dict != NULL) 3533 ++fudi.fd_dict->dv_refcount; 3534 3535 /* If it is the name of a variable of type VAR_FUNC or VAR_PARTIAL use its 3536 * contents. For VAR_PARTIAL get its partial, unless we already have one 3537 * from trans_function_name(). */ 3538 len = (int)STRLEN(tofree); 3539 name = deref_func_name(tofree, &len, 3540 partial != NULL ? NULL : &partial, FALSE); 3541 3542 /* Skip white space to allow ":call func ()". Not good, but required for 3543 * backward compatibility. */ 3544 startarg = skipwhite(arg); 3545 rettv.v_type = VAR_UNKNOWN; /* clear_tv() uses this */ 3546 3547 if (*startarg != '(') 3548 { 3549 EMSG2(_("E107: Missing parentheses: %s"), eap->arg); 3550 goto end; 3551 } 3552 3553 /* 3554 * When skipping, evaluate the function once, to find the end of the 3555 * arguments. 3556 * When the function takes a range, this is discovered after the first 3557 * call, and the loop is broken. 3558 */ 3559 if (eap->skip) 3560 { 3561 ++emsg_skip; 3562 lnum = eap->line2; /* do it once, also with an invalid range */ 3563 } 3564 else 3565 lnum = eap->line1; 3566 for ( ; lnum <= eap->line2; ++lnum) 3567 { 3568 if (!eap->skip && eap->addr_count > 0) 3569 { 3570 curwin->w_cursor.lnum = lnum; 3571 curwin->w_cursor.col = 0; 3572 #ifdef FEAT_VIRTUALEDIT 3573 curwin->w_cursor.coladd = 0; 3574 #endif 3575 } 3576 arg = startarg; 3577 if (get_func_tv(name, (int)STRLEN(name), &rettv, &arg, 3578 eap->line1, eap->line2, &doesrange, 3579 !eap->skip, partial, fudi.fd_dict) == FAIL) 3580 { 3581 failed = TRUE; 3582 break; 3583 } 3584 3585 /* Handle a function returning a Funcref, Dictionary or List. */ 3586 if (handle_subscript(&arg, &rettv, !eap->skip, TRUE) == FAIL) 3587 { 3588 failed = TRUE; 3589 break; 3590 } 3591 3592 clear_tv(&rettv); 3593 if (doesrange || eap->skip) 3594 break; 3595 3596 /* Stop when immediately aborting on error, or when an interrupt 3597 * occurred or an exception was thrown but not caught. 3598 * get_func_tv() returned OK, so that the check for trailing 3599 * characters below is executed. */ 3600 if (aborting()) 3601 break; 3602 } 3603 if (eap->skip) 3604 --emsg_skip; 3605 3606 if (!failed) 3607 { 3608 /* Check for trailing illegal characters and a following command. */ 3609 if (!ends_excmd(*arg)) 3610 { 3611 emsg_severe = TRUE; 3612 EMSG(_(e_trailing)); 3613 } 3614 else 3615 eap->nextcmd = check_nextcmd(arg); 3616 } 3617 3618 end: 3619 dict_unref(fudi.fd_dict); 3620 vim_free(tofree); 3621 } 3622 3623 /* 3624 * ":unlet[!] var1 ... " command. 3625 */ 3626 void 3627 ex_unlet(exarg_T *eap) 3628 { 3629 ex_unletlock(eap, eap->arg, 0); 3630 } 3631 3632 /* 3633 * ":lockvar" and ":unlockvar" commands 3634 */ 3635 void 3636 ex_lockvar(exarg_T *eap) 3637 { 3638 char_u *arg = eap->arg; 3639 int deep = 2; 3640 3641 if (eap->forceit) 3642 deep = -1; 3643 else if (vim_isdigit(*arg)) 3644 { 3645 deep = getdigits(&arg); 3646 arg = skipwhite(arg); 3647 } 3648 3649 ex_unletlock(eap, arg, deep); 3650 } 3651 3652 /* 3653 * ":unlet", ":lockvar" and ":unlockvar" are quite similar. 3654 */ 3655 static void 3656 ex_unletlock( 3657 exarg_T *eap, 3658 char_u *argstart, 3659 int deep) 3660 { 3661 char_u *arg = argstart; 3662 char_u *name_end; 3663 int error = FALSE; 3664 lval_T lv; 3665 3666 do 3667 { 3668 /* Parse the name and find the end. */ 3669 name_end = get_lval(arg, NULL, &lv, TRUE, eap->skip || error, 0, 3670 FNE_CHECK_START); 3671 if (lv.ll_name == NULL) 3672 error = TRUE; /* error but continue parsing */ 3673 if (name_end == NULL || (!vim_iswhite(*name_end) 3674 && !ends_excmd(*name_end))) 3675 { 3676 if (name_end != NULL) 3677 { 3678 emsg_severe = TRUE; 3679 EMSG(_(e_trailing)); 3680 } 3681 if (!(eap->skip || error)) 3682 clear_lval(&lv); 3683 break; 3684 } 3685 3686 if (!error && !eap->skip) 3687 { 3688 if (eap->cmdidx == CMD_unlet) 3689 { 3690 if (do_unlet_var(&lv, name_end, eap->forceit) == FAIL) 3691 error = TRUE; 3692 } 3693 else 3694 { 3695 if (do_lock_var(&lv, name_end, deep, 3696 eap->cmdidx == CMD_lockvar) == FAIL) 3697 error = TRUE; 3698 } 3699 } 3700 3701 if (!eap->skip) 3702 clear_lval(&lv); 3703 3704 arg = skipwhite(name_end); 3705 } while (!ends_excmd(*arg)); 3706 3707 eap->nextcmd = check_nextcmd(arg); 3708 } 3709 3710 static int 3711 do_unlet_var( 3712 lval_T *lp, 3713 char_u *name_end, 3714 int forceit) 3715 { 3716 int ret = OK; 3717 int cc; 3718 3719 if (lp->ll_tv == NULL) 3720 { 3721 cc = *name_end; 3722 *name_end = NUL; 3723 3724 /* Normal name or expanded name. */ 3725 if (check_changedtick(lp->ll_name)) 3726 ret = FAIL; 3727 else if (do_unlet(lp->ll_name, forceit) == FAIL) 3728 ret = FAIL; 3729 *name_end = cc; 3730 } 3731 else if ((lp->ll_list != NULL 3732 && tv_check_lock(lp->ll_list->lv_lock, lp->ll_name, FALSE)) 3733 || (lp->ll_dict != NULL 3734 && tv_check_lock(lp->ll_dict->dv_lock, lp->ll_name, FALSE))) 3735 return FAIL; 3736 else if (lp->ll_range) 3737 { 3738 listitem_T *li; 3739 listitem_T *ll_li = lp->ll_li; 3740 int ll_n1 = lp->ll_n1; 3741 3742 while (ll_li != NULL && (lp->ll_empty2 || lp->ll_n2 >= ll_n1)) 3743 { 3744 li = ll_li->li_next; 3745 if (tv_check_lock(ll_li->li_tv.v_lock, lp->ll_name, FALSE)) 3746 return FAIL; 3747 ll_li = li; 3748 ++ll_n1; 3749 } 3750 3751 /* Delete a range of List items. */ 3752 while (lp->ll_li != NULL && (lp->ll_empty2 || lp->ll_n2 >= lp->ll_n1)) 3753 { 3754 li = lp->ll_li->li_next; 3755 listitem_remove(lp->ll_list, lp->ll_li); 3756 lp->ll_li = li; 3757 ++lp->ll_n1; 3758 } 3759 } 3760 else 3761 { 3762 if (lp->ll_list != NULL) 3763 /* unlet a List item. */ 3764 listitem_remove(lp->ll_list, lp->ll_li); 3765 else 3766 /* unlet a Dictionary item. */ 3767 dictitem_remove(lp->ll_dict, lp->ll_di); 3768 } 3769 3770 return ret; 3771 } 3772 3773 /* 3774 * "unlet" a variable. Return OK if it existed, FAIL if not. 3775 * When "forceit" is TRUE don't complain if the variable doesn't exist. 3776 */ 3777 int 3778 do_unlet(char_u *name, int forceit) 3779 { 3780 hashtab_T *ht; 3781 hashitem_T *hi; 3782 char_u *varname; 3783 dict_T *d; 3784 dictitem_T *di; 3785 3786 ht = find_var_ht(name, &varname); 3787 if (ht != NULL && *varname != NUL) 3788 { 3789 if (ht == &globvarht) 3790 d = &globvardict; 3791 else if (current_funccal != NULL 3792 && ht == ¤t_funccal->l_vars.dv_hashtab) 3793 d = ¤t_funccal->l_vars; 3794 else if (ht == &compat_hashtab) 3795 d = &vimvardict; 3796 else 3797 { 3798 di = find_var_in_ht(ht, *name, (char_u *)"", FALSE); 3799 d = di == NULL ? NULL : di->di_tv.vval.v_dict; 3800 } 3801 if (d == NULL) 3802 { 3803 EMSG2(_(e_intern2), "do_unlet()"); 3804 return FAIL; 3805 } 3806 hi = hash_find(ht, varname); 3807 if (!HASHITEM_EMPTY(hi)) 3808 { 3809 di = HI2DI(hi); 3810 if (var_check_fixed(di->di_flags, name, FALSE) 3811 || var_check_ro(di->di_flags, name, FALSE) 3812 || tv_check_lock(d->dv_lock, name, FALSE)) 3813 return FAIL; 3814 3815 delete_var(ht, hi); 3816 return OK; 3817 } 3818 } 3819 if (forceit) 3820 return OK; 3821 EMSG2(_("E108: No such variable: \"%s\""), name); 3822 return FAIL; 3823 } 3824 3825 /* 3826 * Lock or unlock variable indicated by "lp". 3827 * "deep" is the levels to go (-1 for unlimited); 3828 * "lock" is TRUE for ":lockvar", FALSE for ":unlockvar". 3829 */ 3830 static int 3831 do_lock_var( 3832 lval_T *lp, 3833 char_u *name_end, 3834 int deep, 3835 int lock) 3836 { 3837 int ret = OK; 3838 int cc; 3839 dictitem_T *di; 3840 3841 if (deep == 0) /* nothing to do */ 3842 return OK; 3843 3844 if (lp->ll_tv == NULL) 3845 { 3846 cc = *name_end; 3847 *name_end = NUL; 3848 3849 /* Normal name or expanded name. */ 3850 if (check_changedtick(lp->ll_name)) 3851 ret = FAIL; 3852 else 3853 { 3854 di = find_var(lp->ll_name, NULL, TRUE); 3855 if (di == NULL) 3856 ret = FAIL; 3857 else 3858 { 3859 if (lock) 3860 di->di_flags |= DI_FLAGS_LOCK; 3861 else 3862 di->di_flags &= ~DI_FLAGS_LOCK; 3863 item_lock(&di->di_tv, deep, lock); 3864 } 3865 } 3866 *name_end = cc; 3867 } 3868 else if (lp->ll_range) 3869 { 3870 listitem_T *li = lp->ll_li; 3871 3872 /* (un)lock a range of List items. */ 3873 while (li != NULL && (lp->ll_empty2 || lp->ll_n2 >= lp->ll_n1)) 3874 { 3875 item_lock(&li->li_tv, deep, lock); 3876 li = li->li_next; 3877 ++lp->ll_n1; 3878 } 3879 } 3880 else if (lp->ll_list != NULL) 3881 /* (un)lock a List item. */ 3882 item_lock(&lp->ll_li->li_tv, deep, lock); 3883 else 3884 /* (un)lock a Dictionary item. */ 3885 item_lock(&lp->ll_di->di_tv, deep, lock); 3886 3887 return ret; 3888 } 3889 3890 /* 3891 * Lock or unlock an item. "deep" is nr of levels to go. 3892 */ 3893 static void 3894 item_lock(typval_T *tv, int deep, int lock) 3895 { 3896 static int recurse = 0; 3897 list_T *l; 3898 listitem_T *li; 3899 dict_T *d; 3900 hashitem_T *hi; 3901 int todo; 3902 3903 if (recurse >= DICT_MAXNEST) 3904 { 3905 EMSG(_("E743: variable nested too deep for (un)lock")); 3906 return; 3907 } 3908 if (deep == 0) 3909 return; 3910 ++recurse; 3911 3912 /* lock/unlock the item itself */ 3913 if (lock) 3914 tv->v_lock |= VAR_LOCKED; 3915 else 3916 tv->v_lock &= ~VAR_LOCKED; 3917 3918 switch (tv->v_type) 3919 { 3920 case VAR_UNKNOWN: 3921 case VAR_NUMBER: 3922 case VAR_STRING: 3923 case VAR_FUNC: 3924 case VAR_PARTIAL: 3925 case VAR_FLOAT: 3926 case VAR_SPECIAL: 3927 case VAR_JOB: 3928 case VAR_CHANNEL: 3929 break; 3930 3931 case VAR_LIST: 3932 if ((l = tv->vval.v_list) != NULL) 3933 { 3934 if (lock) 3935 l->lv_lock |= VAR_LOCKED; 3936 else 3937 l->lv_lock &= ~VAR_LOCKED; 3938 if (deep < 0 || deep > 1) 3939 /* recursive: lock/unlock the items the List contains */ 3940 for (li = l->lv_first; li != NULL; li = li->li_next) 3941 item_lock(&li->li_tv, deep - 1, lock); 3942 } 3943 break; 3944 case VAR_DICT: 3945 if ((d = tv->vval.v_dict) != NULL) 3946 { 3947 if (lock) 3948 d->dv_lock |= VAR_LOCKED; 3949 else 3950 d->dv_lock &= ~VAR_LOCKED; 3951 if (deep < 0 || deep > 1) 3952 { 3953 /* recursive: lock/unlock the items the List contains */ 3954 todo = (int)d->dv_hashtab.ht_used; 3955 for (hi = d->dv_hashtab.ht_array; todo > 0; ++hi) 3956 { 3957 if (!HASHITEM_EMPTY(hi)) 3958 { 3959 --todo; 3960 item_lock(&HI2DI(hi)->di_tv, deep - 1, lock); 3961 } 3962 } 3963 } 3964 } 3965 } 3966 --recurse; 3967 } 3968 3969 /* 3970 * Return TRUE if typeval "tv" is locked: Either that value is locked itself 3971 * or it refers to a List or Dictionary that is locked. 3972 */ 3973 static int 3974 tv_islocked(typval_T *tv) 3975 { 3976 return (tv->v_lock & VAR_LOCKED) 3977 || (tv->v_type == VAR_LIST 3978 && tv->vval.v_list != NULL 3979 && (tv->vval.v_list->lv_lock & VAR_LOCKED)) 3980 || (tv->v_type == VAR_DICT 3981 && tv->vval.v_dict != NULL 3982 && (tv->vval.v_dict->dv_lock & VAR_LOCKED)); 3983 } 3984 3985 #if (defined(FEAT_MENU) && defined(FEAT_MULTI_LANG)) || defined(PROTO) 3986 /* 3987 * Delete all "menutrans_" variables. 3988 */ 3989 void 3990 del_menutrans_vars(void) 3991 { 3992 hashitem_T *hi; 3993 int todo; 3994 3995 hash_lock(&globvarht); 3996 todo = (int)globvarht.ht_used; 3997 for (hi = globvarht.ht_array; todo > 0 && !got_int; ++hi) 3998 { 3999 if (!HASHITEM_EMPTY(hi)) 4000 { 4001 --todo; 4002 if (STRNCMP(HI2DI(hi)->di_key, "menutrans_", 10) == 0) 4003 delete_var(&globvarht, hi); 4004 } 4005 } 4006 hash_unlock(&globvarht); 4007 } 4008 #endif 4009 4010 #if defined(FEAT_CMDL_COMPL) || defined(PROTO) 4011 4012 /* 4013 * Local string buffer for the next two functions to store a variable name 4014 * with its prefix. Allocated in cat_prefix_varname(), freed later in 4015 * get_user_var_name(). 4016 */ 4017 4018 static char_u *cat_prefix_varname(int prefix, char_u *name); 4019 4020 static char_u *varnamebuf = NULL; 4021 static int varnamebuflen = 0; 4022 4023 /* 4024 * Function to concatenate a prefix and a variable name. 4025 */ 4026 static char_u * 4027 cat_prefix_varname(int prefix, char_u *name) 4028 { 4029 int len; 4030 4031 len = (int)STRLEN(name) + 3; 4032 if (len > varnamebuflen) 4033 { 4034 vim_free(varnamebuf); 4035 len += 10; /* some additional space */ 4036 varnamebuf = alloc(len); 4037 if (varnamebuf == NULL) 4038 { 4039 varnamebuflen = 0; 4040 return NULL; 4041 } 4042 varnamebuflen = len; 4043 } 4044 *varnamebuf = prefix; 4045 varnamebuf[1] = ':'; 4046 STRCPY(varnamebuf + 2, name); 4047 return varnamebuf; 4048 } 4049 4050 /* 4051 * Function given to ExpandGeneric() to obtain the list of user defined 4052 * (global/buffer/window/built-in) variable names. 4053 */ 4054 char_u * 4055 get_user_var_name(expand_T *xp, int idx) 4056 { 4057 static long_u gdone; 4058 static long_u bdone; 4059 static long_u wdone; 4060 #ifdef FEAT_WINDOWS 4061 static long_u tdone; 4062 #endif 4063 static int vidx; 4064 static hashitem_T *hi; 4065 hashtab_T *ht; 4066 4067 if (idx == 0) 4068 { 4069 gdone = bdone = wdone = vidx = 0; 4070 #ifdef FEAT_WINDOWS 4071 tdone = 0; 4072 #endif 4073 } 4074 4075 /* Global variables */ 4076 if (gdone < globvarht.ht_used) 4077 { 4078 if (gdone++ == 0) 4079 hi = globvarht.ht_array; 4080 else 4081 ++hi; 4082 while (HASHITEM_EMPTY(hi)) 4083 ++hi; 4084 if (STRNCMP("g:", xp->xp_pattern, 2) == 0) 4085 return cat_prefix_varname('g', hi->hi_key); 4086 return hi->hi_key; 4087 } 4088 4089 /* b: variables */ 4090 ht = &curbuf->b_vars->dv_hashtab; 4091 if (bdone < ht->ht_used) 4092 { 4093 if (bdone++ == 0) 4094 hi = ht->ht_array; 4095 else 4096 ++hi; 4097 while (HASHITEM_EMPTY(hi)) 4098 ++hi; 4099 return cat_prefix_varname('b', hi->hi_key); 4100 } 4101 if (bdone == ht->ht_used) 4102 { 4103 ++bdone; 4104 return (char_u *)"b:changedtick"; 4105 } 4106 4107 /* w: variables */ 4108 ht = &curwin->w_vars->dv_hashtab; 4109 if (wdone < ht->ht_used) 4110 { 4111 if (wdone++ == 0) 4112 hi = ht->ht_array; 4113 else 4114 ++hi; 4115 while (HASHITEM_EMPTY(hi)) 4116 ++hi; 4117 return cat_prefix_varname('w', hi->hi_key); 4118 } 4119 4120 #ifdef FEAT_WINDOWS 4121 /* t: variables */ 4122 ht = &curtab->tp_vars->dv_hashtab; 4123 if (tdone < ht->ht_used) 4124 { 4125 if (tdone++ == 0) 4126 hi = ht->ht_array; 4127 else 4128 ++hi; 4129 while (HASHITEM_EMPTY(hi)) 4130 ++hi; 4131 return cat_prefix_varname('t', hi->hi_key); 4132 } 4133 #endif 4134 4135 /* v: variables */ 4136 if (vidx < VV_LEN) 4137 return cat_prefix_varname('v', (char_u *)vimvars[vidx++].vv_name); 4138 4139 vim_free(varnamebuf); 4140 varnamebuf = NULL; 4141 varnamebuflen = 0; 4142 return NULL; 4143 } 4144 4145 #endif /* FEAT_CMDL_COMPL */ 4146 4147 /* 4148 * Return TRUE if "pat" matches "text". 4149 * Does not use 'cpo' and always uses 'magic'. 4150 */ 4151 static int 4152 pattern_match(char_u *pat, char_u *text, int ic) 4153 { 4154 int matches = FALSE; 4155 char_u *save_cpo; 4156 regmatch_T regmatch; 4157 4158 /* avoid 'l' flag in 'cpoptions' */ 4159 save_cpo = p_cpo; 4160 p_cpo = (char_u *)""; 4161 regmatch.regprog = vim_regcomp(pat, RE_MAGIC + RE_STRING); 4162 if (regmatch.regprog != NULL) 4163 { 4164 regmatch.rm_ic = ic; 4165 matches = vim_regexec_nl(®match, text, (colnr_T)0); 4166 vim_regfree(regmatch.regprog); 4167 } 4168 p_cpo = save_cpo; 4169 return matches; 4170 } 4171 4172 /* 4173 * types for expressions. 4174 */ 4175 typedef enum 4176 { 4177 TYPE_UNKNOWN = 0 4178 , TYPE_EQUAL /* == */ 4179 , TYPE_NEQUAL /* != */ 4180 , TYPE_GREATER /* > */ 4181 , TYPE_GEQUAL /* >= */ 4182 , TYPE_SMALLER /* < */ 4183 , TYPE_SEQUAL /* <= */ 4184 , TYPE_MATCH /* =~ */ 4185 , TYPE_NOMATCH /* !~ */ 4186 } exptype_T; 4187 4188 /* 4189 * The "evaluate" argument: When FALSE, the argument is only parsed but not 4190 * executed. The function may return OK, but the rettv will be of type 4191 * VAR_UNKNOWN. The function still returns FAIL for a syntax error. 4192 */ 4193 4194 /* 4195 * Handle zero level expression. 4196 * This calls eval1() and handles error message and nextcmd. 4197 * Put the result in "rettv" when returning OK and "evaluate" is TRUE. 4198 * Note: "rettv.v_lock" is not set. 4199 * Return OK or FAIL. 4200 */ 4201 static int 4202 eval0( 4203 char_u *arg, 4204 typval_T *rettv, 4205 char_u **nextcmd, 4206 int evaluate) 4207 { 4208 int ret; 4209 char_u *p; 4210 4211 p = skipwhite(arg); 4212 ret = eval1(&p, rettv, evaluate); 4213 if (ret == FAIL || !ends_excmd(*p)) 4214 { 4215 if (ret != FAIL) 4216 clear_tv(rettv); 4217 /* 4218 * Report the invalid expression unless the expression evaluation has 4219 * been cancelled due to an aborting error, an interrupt, or an 4220 * exception. 4221 */ 4222 if (!aborting()) 4223 EMSG2(_(e_invexpr2), arg); 4224 ret = FAIL; 4225 } 4226 if (nextcmd != NULL) 4227 *nextcmd = check_nextcmd(p); 4228 4229 return ret; 4230 } 4231 4232 /* 4233 * Handle top level expression: 4234 * expr2 ? expr1 : expr1 4235 * 4236 * "arg" must point to the first non-white of the expression. 4237 * "arg" is advanced to the next non-white after the recognized expression. 4238 * 4239 * Note: "rettv.v_lock" is not set. 4240 * 4241 * Return OK or FAIL. 4242 */ 4243 static int 4244 eval1(char_u **arg, typval_T *rettv, int evaluate) 4245 { 4246 int result; 4247 typval_T var2; 4248 4249 /* 4250 * Get the first variable. 4251 */ 4252 if (eval2(arg, rettv, evaluate) == FAIL) 4253 return FAIL; 4254 4255 if ((*arg)[0] == '?') 4256 { 4257 result = FALSE; 4258 if (evaluate) 4259 { 4260 int error = FALSE; 4261 4262 if (get_tv_number_chk(rettv, &error) != 0) 4263 result = TRUE; 4264 clear_tv(rettv); 4265 if (error) 4266 return FAIL; 4267 } 4268 4269 /* 4270 * Get the second variable. 4271 */ 4272 *arg = skipwhite(*arg + 1); 4273 if (eval1(arg, rettv, evaluate && result) == FAIL) /* recursive! */ 4274 return FAIL; 4275 4276 /* 4277 * Check for the ":". 4278 */ 4279 if ((*arg)[0] != ':') 4280 { 4281 EMSG(_("E109: Missing ':' after '?'")); 4282 if (evaluate && result) 4283 clear_tv(rettv); 4284 return FAIL; 4285 } 4286 4287 /* 4288 * Get the third variable. 4289 */ 4290 *arg = skipwhite(*arg + 1); 4291 if (eval1(arg, &var2, evaluate && !result) == FAIL) /* recursive! */ 4292 { 4293 if (evaluate && result) 4294 clear_tv(rettv); 4295 return FAIL; 4296 } 4297 if (evaluate && !result) 4298 *rettv = var2; 4299 } 4300 4301 return OK; 4302 } 4303 4304 /* 4305 * Handle first level expression: 4306 * expr2 || expr2 || expr2 logical OR 4307 * 4308 * "arg" must point to the first non-white of the expression. 4309 * "arg" is advanced to the next non-white after the recognized expression. 4310 * 4311 * Return OK or FAIL. 4312 */ 4313 static int 4314 eval2(char_u **arg, typval_T *rettv, int evaluate) 4315 { 4316 typval_T var2; 4317 long result; 4318 int first; 4319 int error = FALSE; 4320 4321 /* 4322 * Get the first variable. 4323 */ 4324 if (eval3(arg, rettv, evaluate) == FAIL) 4325 return FAIL; 4326 4327 /* 4328 * Repeat until there is no following "||". 4329 */ 4330 first = TRUE; 4331 result = FALSE; 4332 while ((*arg)[0] == '|' && (*arg)[1] == '|') 4333 { 4334 if (evaluate && first) 4335 { 4336 if (get_tv_number_chk(rettv, &error) != 0) 4337 result = TRUE; 4338 clear_tv(rettv); 4339 if (error) 4340 return FAIL; 4341 first = FALSE; 4342 } 4343 4344 /* 4345 * Get the second variable. 4346 */ 4347 *arg = skipwhite(*arg + 2); 4348 if (eval3(arg, &var2, evaluate && !result) == FAIL) 4349 return FAIL; 4350 4351 /* 4352 * Compute the result. 4353 */ 4354 if (evaluate && !result) 4355 { 4356 if (get_tv_number_chk(&var2, &error) != 0) 4357 result = TRUE; 4358 clear_tv(&var2); 4359 if (error) 4360 return FAIL; 4361 } 4362 if (evaluate) 4363 { 4364 rettv->v_type = VAR_NUMBER; 4365 rettv->vval.v_number = result; 4366 } 4367 } 4368 4369 return OK; 4370 } 4371 4372 /* 4373 * Handle second level expression: 4374 * expr3 && expr3 && expr3 logical AND 4375 * 4376 * "arg" must point to the first non-white of the expression. 4377 * "arg" is advanced to the next non-white after the recognized expression. 4378 * 4379 * Return OK or FAIL. 4380 */ 4381 static int 4382 eval3(char_u **arg, typval_T *rettv, int evaluate) 4383 { 4384 typval_T var2; 4385 long result; 4386 int first; 4387 int error = FALSE; 4388 4389 /* 4390 * Get the first variable. 4391 */ 4392 if (eval4(arg, rettv, evaluate) == FAIL) 4393 return FAIL; 4394 4395 /* 4396 * Repeat until there is no following "&&". 4397 */ 4398 first = TRUE; 4399 result = TRUE; 4400 while ((*arg)[0] == '&' && (*arg)[1] == '&') 4401 { 4402 if (evaluate && first) 4403 { 4404 if (get_tv_number_chk(rettv, &error) == 0) 4405 result = FALSE; 4406 clear_tv(rettv); 4407 if (error) 4408 return FAIL; 4409 first = FALSE; 4410 } 4411 4412 /* 4413 * Get the second variable. 4414 */ 4415 *arg = skipwhite(*arg + 2); 4416 if (eval4(arg, &var2, evaluate && result) == FAIL) 4417 return FAIL; 4418 4419 /* 4420 * Compute the result. 4421 */ 4422 if (evaluate && result) 4423 { 4424 if (get_tv_number_chk(&var2, &error) == 0) 4425 result = FALSE; 4426 clear_tv(&var2); 4427 if (error) 4428 return FAIL; 4429 } 4430 if (evaluate) 4431 { 4432 rettv->v_type = VAR_NUMBER; 4433 rettv->vval.v_number = result; 4434 } 4435 } 4436 4437 return OK; 4438 } 4439 4440 /* 4441 * Handle third level expression: 4442 * var1 == var2 4443 * var1 =~ var2 4444 * var1 != var2 4445 * var1 !~ var2 4446 * var1 > var2 4447 * var1 >= var2 4448 * var1 < var2 4449 * var1 <= var2 4450 * var1 is var2 4451 * var1 isnot var2 4452 * 4453 * "arg" must point to the first non-white of the expression. 4454 * "arg" is advanced to the next non-white after the recognized expression. 4455 * 4456 * Return OK or FAIL. 4457 */ 4458 static int 4459 eval4(char_u **arg, typval_T *rettv, int evaluate) 4460 { 4461 typval_T var2; 4462 char_u *p; 4463 int i; 4464 exptype_T type = TYPE_UNKNOWN; 4465 int type_is = FALSE; /* TRUE for "is" and "isnot" */ 4466 int len = 2; 4467 long n1, n2; 4468 char_u *s1, *s2; 4469 char_u buf1[NUMBUFLEN], buf2[NUMBUFLEN]; 4470 int ic; 4471 4472 /* 4473 * Get the first variable. 4474 */ 4475 if (eval5(arg, rettv, evaluate) == FAIL) 4476 return FAIL; 4477 4478 p = *arg; 4479 switch (p[0]) 4480 { 4481 case '=': if (p[1] == '=') 4482 type = TYPE_EQUAL; 4483 else if (p[1] == '~') 4484 type = TYPE_MATCH; 4485 break; 4486 case '!': if (p[1] == '=') 4487 type = TYPE_NEQUAL; 4488 else if (p[1] == '~') 4489 type = TYPE_NOMATCH; 4490 break; 4491 case '>': if (p[1] != '=') 4492 { 4493 type = TYPE_GREATER; 4494 len = 1; 4495 } 4496 else 4497 type = TYPE_GEQUAL; 4498 break; 4499 case '<': if (p[1] != '=') 4500 { 4501 type = TYPE_SMALLER; 4502 len = 1; 4503 } 4504 else 4505 type = TYPE_SEQUAL; 4506 break; 4507 case 'i': if (p[1] == 's') 4508 { 4509 if (p[2] == 'n' && p[3] == 'o' && p[4] == 't') 4510 len = 5; 4511 i = p[len]; 4512 if (!isalnum(i) && i != '_') 4513 { 4514 type = len == 2 ? TYPE_EQUAL : TYPE_NEQUAL; 4515 type_is = TRUE; 4516 } 4517 } 4518 break; 4519 } 4520 4521 /* 4522 * If there is a comparative operator, use it. 4523 */ 4524 if (type != TYPE_UNKNOWN) 4525 { 4526 /* extra question mark appended: ignore case */ 4527 if (p[len] == '?') 4528 { 4529 ic = TRUE; 4530 ++len; 4531 } 4532 /* extra '#' appended: match case */ 4533 else if (p[len] == '#') 4534 { 4535 ic = FALSE; 4536 ++len; 4537 } 4538 /* nothing appended: use 'ignorecase' */ 4539 else 4540 ic = p_ic; 4541 4542 /* 4543 * Get the second variable. 4544 */ 4545 *arg = skipwhite(p + len); 4546 if (eval5(arg, &var2, evaluate) == FAIL) 4547 { 4548 clear_tv(rettv); 4549 return FAIL; 4550 } 4551 4552 if (evaluate) 4553 { 4554 if (type_is && rettv->v_type != var2.v_type) 4555 { 4556 /* For "is" a different type always means FALSE, for "notis" 4557 * it means TRUE. */ 4558 n1 = (type == TYPE_NEQUAL); 4559 } 4560 else if (rettv->v_type == VAR_LIST || var2.v_type == VAR_LIST) 4561 { 4562 if (type_is) 4563 { 4564 n1 = (rettv->v_type == var2.v_type 4565 && rettv->vval.v_list == var2.vval.v_list); 4566 if (type == TYPE_NEQUAL) 4567 n1 = !n1; 4568 } 4569 else if (rettv->v_type != var2.v_type 4570 || (type != TYPE_EQUAL && type != TYPE_NEQUAL)) 4571 { 4572 if (rettv->v_type != var2.v_type) 4573 EMSG(_("E691: Can only compare List with List")); 4574 else 4575 EMSG(_("E692: Invalid operation for List")); 4576 clear_tv(rettv); 4577 clear_tv(&var2); 4578 return FAIL; 4579 } 4580 else 4581 { 4582 /* Compare two Lists for being equal or unequal. */ 4583 n1 = list_equal(rettv->vval.v_list, var2.vval.v_list, 4584 ic, FALSE); 4585 if (type == TYPE_NEQUAL) 4586 n1 = !n1; 4587 } 4588 } 4589 4590 else if (rettv->v_type == VAR_DICT || var2.v_type == VAR_DICT) 4591 { 4592 if (type_is) 4593 { 4594 n1 = (rettv->v_type == var2.v_type 4595 && rettv->vval.v_dict == var2.vval.v_dict); 4596 if (type == TYPE_NEQUAL) 4597 n1 = !n1; 4598 } 4599 else if (rettv->v_type != var2.v_type 4600 || (type != TYPE_EQUAL && type != TYPE_NEQUAL)) 4601 { 4602 if (rettv->v_type != var2.v_type) 4603 EMSG(_("E735: Can only compare Dictionary with Dictionary")); 4604 else 4605 EMSG(_("E736: Invalid operation for Dictionary")); 4606 clear_tv(rettv); 4607 clear_tv(&var2); 4608 return FAIL; 4609 } 4610 else 4611 { 4612 /* Compare two Dictionaries for being equal or unequal. */ 4613 n1 = dict_equal(rettv->vval.v_dict, var2.vval.v_dict, 4614 ic, FALSE); 4615 if (type == TYPE_NEQUAL) 4616 n1 = !n1; 4617 } 4618 } 4619 4620 else if (rettv->v_type == VAR_FUNC || var2.v_type == VAR_FUNC 4621 || rettv->v_type == VAR_PARTIAL || var2.v_type == VAR_PARTIAL) 4622 { 4623 if (type != TYPE_EQUAL && type != TYPE_NEQUAL) 4624 { 4625 EMSG(_("E694: Invalid operation for Funcrefs")); 4626 clear_tv(rettv); 4627 clear_tv(&var2); 4628 return FAIL; 4629 } 4630 if ((rettv->v_type == VAR_PARTIAL 4631 && rettv->vval.v_partial == NULL) 4632 || (var2.v_type == VAR_PARTIAL 4633 && var2.vval.v_partial == NULL)) 4634 /* when a partial is NULL assume not equal */ 4635 n1 = FALSE; 4636 else if (type_is) 4637 { 4638 if (rettv->v_type == VAR_FUNC && var2.v_type == VAR_FUNC) 4639 /* strings are considered the same if their value is 4640 * the same */ 4641 n1 = tv_equal(rettv, &var2, ic, FALSE); 4642 else if (rettv->v_type == VAR_PARTIAL 4643 && var2.v_type == VAR_PARTIAL) 4644 n1 = (rettv->vval.v_partial == var2.vval.v_partial); 4645 else 4646 n1 = FALSE; 4647 } 4648 else 4649 n1 = tv_equal(rettv, &var2, ic, FALSE); 4650 if (type == TYPE_NEQUAL) 4651 n1 = !n1; 4652 } 4653 4654 #ifdef FEAT_FLOAT 4655 /* 4656 * If one of the two variables is a float, compare as a float. 4657 * When using "=~" or "!~", always compare as string. 4658 */ 4659 else if ((rettv->v_type == VAR_FLOAT || var2.v_type == VAR_FLOAT) 4660 && type != TYPE_MATCH && type != TYPE_NOMATCH) 4661 { 4662 float_T f1, f2; 4663 4664 if (rettv->v_type == VAR_FLOAT) 4665 f1 = rettv->vval.v_float; 4666 else 4667 f1 = get_tv_number(rettv); 4668 if (var2.v_type == VAR_FLOAT) 4669 f2 = var2.vval.v_float; 4670 else 4671 f2 = get_tv_number(&var2); 4672 n1 = FALSE; 4673 switch (type) 4674 { 4675 case TYPE_EQUAL: n1 = (f1 == f2); break; 4676 case TYPE_NEQUAL: n1 = (f1 != f2); break; 4677 case TYPE_GREATER: n1 = (f1 > f2); break; 4678 case TYPE_GEQUAL: n1 = (f1 >= f2); break; 4679 case TYPE_SMALLER: n1 = (f1 < f2); break; 4680 case TYPE_SEQUAL: n1 = (f1 <= f2); break; 4681 case TYPE_UNKNOWN: 4682 case TYPE_MATCH: 4683 case TYPE_NOMATCH: break; /* avoid gcc warning */ 4684 } 4685 } 4686 #endif 4687 4688 /* 4689 * If one of the two variables is a number, compare as a number. 4690 * When using "=~" or "!~", always compare as string. 4691 */ 4692 else if ((rettv->v_type == VAR_NUMBER || var2.v_type == VAR_NUMBER) 4693 && type != TYPE_MATCH && type != TYPE_NOMATCH) 4694 { 4695 n1 = get_tv_number(rettv); 4696 n2 = get_tv_number(&var2); 4697 switch (type) 4698 { 4699 case TYPE_EQUAL: n1 = (n1 == n2); break; 4700 case TYPE_NEQUAL: n1 = (n1 != n2); break; 4701 case TYPE_GREATER: n1 = (n1 > n2); break; 4702 case TYPE_GEQUAL: n1 = (n1 >= n2); break; 4703 case TYPE_SMALLER: n1 = (n1 < n2); break; 4704 case TYPE_SEQUAL: n1 = (n1 <= n2); break; 4705 case TYPE_UNKNOWN: 4706 case TYPE_MATCH: 4707 case TYPE_NOMATCH: break; /* avoid gcc warning */ 4708 } 4709 } 4710 else 4711 { 4712 s1 = get_tv_string_buf(rettv, buf1); 4713 s2 = get_tv_string_buf(&var2, buf2); 4714 if (type != TYPE_MATCH && type != TYPE_NOMATCH) 4715 i = ic ? MB_STRICMP(s1, s2) : STRCMP(s1, s2); 4716 else 4717 i = 0; 4718 n1 = FALSE; 4719 switch (type) 4720 { 4721 case TYPE_EQUAL: n1 = (i == 0); break; 4722 case TYPE_NEQUAL: n1 = (i != 0); break; 4723 case TYPE_GREATER: n1 = (i > 0); break; 4724 case TYPE_GEQUAL: n1 = (i >= 0); break; 4725 case TYPE_SMALLER: n1 = (i < 0); break; 4726 case TYPE_SEQUAL: n1 = (i <= 0); break; 4727 4728 case TYPE_MATCH: 4729 case TYPE_NOMATCH: 4730 n1 = pattern_match(s2, s1, ic); 4731 if (type == TYPE_NOMATCH) 4732 n1 = !n1; 4733 break; 4734 4735 case TYPE_UNKNOWN: break; /* avoid gcc warning */ 4736 } 4737 } 4738 clear_tv(rettv); 4739 clear_tv(&var2); 4740 rettv->v_type = VAR_NUMBER; 4741 rettv->vval.v_number = n1; 4742 } 4743 } 4744 4745 return OK; 4746 } 4747 4748 /* 4749 * Handle fourth level expression: 4750 * + number addition 4751 * - number subtraction 4752 * . string concatenation 4753 * 4754 * "arg" must point to the first non-white of the expression. 4755 * "arg" is advanced to the next non-white after the recognized expression. 4756 * 4757 * Return OK or FAIL. 4758 */ 4759 static int 4760 eval5(char_u **arg, typval_T *rettv, int evaluate) 4761 { 4762 typval_T var2; 4763 typval_T var3; 4764 int op; 4765 long n1, n2; 4766 #ifdef FEAT_FLOAT 4767 float_T f1 = 0, f2 = 0; 4768 #endif 4769 char_u *s1, *s2; 4770 char_u buf1[NUMBUFLEN], buf2[NUMBUFLEN]; 4771 char_u *p; 4772 4773 /* 4774 * Get the first variable. 4775 */ 4776 if (eval6(arg, rettv, evaluate, FALSE) == FAIL) 4777 return FAIL; 4778 4779 /* 4780 * Repeat computing, until no '+', '-' or '.' is following. 4781 */ 4782 for (;;) 4783 { 4784 op = **arg; 4785 if (op != '+' && op != '-' && op != '.') 4786 break; 4787 4788 if ((op != '+' || rettv->v_type != VAR_LIST) 4789 #ifdef FEAT_FLOAT 4790 && (op == '.' || rettv->v_type != VAR_FLOAT) 4791 #endif 4792 ) 4793 { 4794 /* For "list + ...", an illegal use of the first operand as 4795 * a number cannot be determined before evaluating the 2nd 4796 * operand: if this is also a list, all is ok. 4797 * For "something . ...", "something - ..." or "non-list + ...", 4798 * we know that the first operand needs to be a string or number 4799 * without evaluating the 2nd operand. So check before to avoid 4800 * side effects after an error. */ 4801 if (evaluate && get_tv_string_chk(rettv) == NULL) 4802 { 4803 clear_tv(rettv); 4804 return FAIL; 4805 } 4806 } 4807 4808 /* 4809 * Get the second variable. 4810 */ 4811 *arg = skipwhite(*arg + 1); 4812 if (eval6(arg, &var2, evaluate, op == '.') == FAIL) 4813 { 4814 clear_tv(rettv); 4815 return FAIL; 4816 } 4817 4818 if (evaluate) 4819 { 4820 /* 4821 * Compute the result. 4822 */ 4823 if (op == '.') 4824 { 4825 s1 = get_tv_string_buf(rettv, buf1); /* already checked */ 4826 s2 = get_tv_string_buf_chk(&var2, buf2); 4827 if (s2 == NULL) /* type error ? */ 4828 { 4829 clear_tv(rettv); 4830 clear_tv(&var2); 4831 return FAIL; 4832 } 4833 p = concat_str(s1, s2); 4834 clear_tv(rettv); 4835 rettv->v_type = VAR_STRING; 4836 rettv->vval.v_string = p; 4837 } 4838 else if (op == '+' && rettv->v_type == VAR_LIST 4839 && var2.v_type == VAR_LIST) 4840 { 4841 /* concatenate Lists */ 4842 if (list_concat(rettv->vval.v_list, var2.vval.v_list, 4843 &var3) == FAIL) 4844 { 4845 clear_tv(rettv); 4846 clear_tv(&var2); 4847 return FAIL; 4848 } 4849 clear_tv(rettv); 4850 *rettv = var3; 4851 } 4852 else 4853 { 4854 int error = FALSE; 4855 4856 #ifdef FEAT_FLOAT 4857 if (rettv->v_type == VAR_FLOAT) 4858 { 4859 f1 = rettv->vval.v_float; 4860 n1 = 0; 4861 } 4862 else 4863 #endif 4864 { 4865 n1 = get_tv_number_chk(rettv, &error); 4866 if (error) 4867 { 4868 /* This can only happen for "list + non-list". For 4869 * "non-list + ..." or "something - ...", we returned 4870 * before evaluating the 2nd operand. */ 4871 clear_tv(rettv); 4872 return FAIL; 4873 } 4874 #ifdef FEAT_FLOAT 4875 if (var2.v_type == VAR_FLOAT) 4876 f1 = n1; 4877 #endif 4878 } 4879 #ifdef FEAT_FLOAT 4880 if (var2.v_type == VAR_FLOAT) 4881 { 4882 f2 = var2.vval.v_float; 4883 n2 = 0; 4884 } 4885 else 4886 #endif 4887 { 4888 n2 = get_tv_number_chk(&var2, &error); 4889 if (error) 4890 { 4891 clear_tv(rettv); 4892 clear_tv(&var2); 4893 return FAIL; 4894 } 4895 #ifdef FEAT_FLOAT 4896 if (rettv->v_type == VAR_FLOAT) 4897 f2 = n2; 4898 #endif 4899 } 4900 clear_tv(rettv); 4901 4902 #ifdef FEAT_FLOAT 4903 /* If there is a float on either side the result is a float. */ 4904 if (rettv->v_type == VAR_FLOAT || var2.v_type == VAR_FLOAT) 4905 { 4906 if (op == '+') 4907 f1 = f1 + f2; 4908 else 4909 f1 = f1 - f2; 4910 rettv->v_type = VAR_FLOAT; 4911 rettv->vval.v_float = f1; 4912 } 4913 else 4914 #endif 4915 { 4916 if (op == '+') 4917 n1 = n1 + n2; 4918 else 4919 n1 = n1 - n2; 4920 rettv->v_type = VAR_NUMBER; 4921 rettv->vval.v_number = n1; 4922 } 4923 } 4924 clear_tv(&var2); 4925 } 4926 } 4927 return OK; 4928 } 4929 4930 /* 4931 * Handle fifth level expression: 4932 * * number multiplication 4933 * / number division 4934 * % number modulo 4935 * 4936 * "arg" must point to the first non-white of the expression. 4937 * "arg" is advanced to the next non-white after the recognized expression. 4938 * 4939 * Return OK or FAIL. 4940 */ 4941 static int 4942 eval6( 4943 char_u **arg, 4944 typval_T *rettv, 4945 int evaluate, 4946 int want_string) /* after "." operator */ 4947 { 4948 typval_T var2; 4949 int op; 4950 long n1, n2; 4951 #ifdef FEAT_FLOAT 4952 int use_float = FALSE; 4953 float_T f1 = 0, f2; 4954 #endif 4955 int error = FALSE; 4956 4957 /* 4958 * Get the first variable. 4959 */ 4960 if (eval7(arg, rettv, evaluate, want_string) == FAIL) 4961 return FAIL; 4962 4963 /* 4964 * Repeat computing, until no '*', '/' or '%' is following. 4965 */ 4966 for (;;) 4967 { 4968 op = **arg; 4969 if (op != '*' && op != '/' && op != '%') 4970 break; 4971 4972 if (evaluate) 4973 { 4974 #ifdef FEAT_FLOAT 4975 if (rettv->v_type == VAR_FLOAT) 4976 { 4977 f1 = rettv->vval.v_float; 4978 use_float = TRUE; 4979 n1 = 0; 4980 } 4981 else 4982 #endif 4983 n1 = get_tv_number_chk(rettv, &error); 4984 clear_tv(rettv); 4985 if (error) 4986 return FAIL; 4987 } 4988 else 4989 n1 = 0; 4990 4991 /* 4992 * Get the second variable. 4993 */ 4994 *arg = skipwhite(*arg + 1); 4995 if (eval7(arg, &var2, evaluate, FALSE) == FAIL) 4996 return FAIL; 4997 4998 if (evaluate) 4999 { 5000 #ifdef FEAT_FLOAT 5001 if (var2.v_type == VAR_FLOAT) 5002 { 5003 if (!use_float) 5004 { 5005 f1 = n1; 5006 use_float = TRUE; 5007 } 5008 f2 = var2.vval.v_float; 5009 n2 = 0; 5010 } 5011 else 5012 #endif 5013 { 5014 n2 = get_tv_number_chk(&var2, &error); 5015 clear_tv(&var2); 5016 if (error) 5017 return FAIL; 5018 #ifdef FEAT_FLOAT 5019 if (use_float) 5020 f2 = n2; 5021 #endif 5022 } 5023 5024 /* 5025 * Compute the result. 5026 * When either side is a float the result is a float. 5027 */ 5028 #ifdef FEAT_FLOAT 5029 if (use_float) 5030 { 5031 if (op == '*') 5032 f1 = f1 * f2; 5033 else if (op == '/') 5034 { 5035 # ifdef VMS 5036 /* VMS crashes on divide by zero, work around it */ 5037 if (f2 == 0.0) 5038 { 5039 if (f1 == 0) 5040 f1 = -1 * __F_FLT_MAX - 1L; /* similar to NaN */ 5041 else if (f1 < 0) 5042 f1 = -1 * __F_FLT_MAX; 5043 else 5044 f1 = __F_FLT_MAX; 5045 } 5046 else 5047 f1 = f1 / f2; 5048 # else 5049 /* We rely on the floating point library to handle divide 5050 * by zero to result in "inf" and not a crash. */ 5051 f1 = f1 / f2; 5052 # endif 5053 } 5054 else 5055 { 5056 EMSG(_("E804: Cannot use '%' with Float")); 5057 return FAIL; 5058 } 5059 rettv->v_type = VAR_FLOAT; 5060 rettv->vval.v_float = f1; 5061 } 5062 else 5063 #endif 5064 { 5065 if (op == '*') 5066 n1 = n1 * n2; 5067 else if (op == '/') 5068 { 5069 if (n2 == 0) /* give an error message? */ 5070 { 5071 if (n1 == 0) 5072 n1 = -0x7fffffffL - 1L; /* similar to NaN */ 5073 else if (n1 < 0) 5074 n1 = -0x7fffffffL; 5075 else 5076 n1 = 0x7fffffffL; 5077 } 5078 else 5079 n1 = n1 / n2; 5080 } 5081 else 5082 { 5083 if (n2 == 0) /* give an error message? */ 5084 n1 = 0; 5085 else 5086 n1 = n1 % n2; 5087 } 5088 rettv->v_type = VAR_NUMBER; 5089 rettv->vval.v_number = n1; 5090 } 5091 } 5092 } 5093 5094 return OK; 5095 } 5096 5097 /* 5098 * Handle sixth level expression: 5099 * number number constant 5100 * "string" string constant 5101 * 'string' literal string constant 5102 * &option-name option value 5103 * @r register contents 5104 * identifier variable value 5105 * function() function call 5106 * $VAR environment variable 5107 * (expression) nested expression 5108 * [expr, expr] List 5109 * {key: val, key: val} Dictionary 5110 * 5111 * Also handle: 5112 * ! in front logical NOT 5113 * - in front unary minus 5114 * + in front unary plus (ignored) 5115 * trailing [] subscript in String or List 5116 * trailing .name entry in Dictionary 5117 * 5118 * "arg" must point to the first non-white of the expression. 5119 * "arg" is advanced to the next non-white after the recognized expression. 5120 * 5121 * Return OK or FAIL. 5122 */ 5123 static int 5124 eval7( 5125 char_u **arg, 5126 typval_T *rettv, 5127 int evaluate, 5128 int want_string UNUSED) /* after "." operator */ 5129 { 5130 long n; 5131 int len; 5132 char_u *s; 5133 char_u *start_leader, *end_leader; 5134 int ret = OK; 5135 char_u *alias; 5136 5137 /* 5138 * Initialise variable so that clear_tv() can't mistake this for a 5139 * string and free a string that isn't there. 5140 */ 5141 rettv->v_type = VAR_UNKNOWN; 5142 5143 /* 5144 * Skip '!' and '-' characters. They are handled later. 5145 */ 5146 start_leader = *arg; 5147 while (**arg == '!' || **arg == '-' || **arg == '+') 5148 *arg = skipwhite(*arg + 1); 5149 end_leader = *arg; 5150 5151 switch (**arg) 5152 { 5153 /* 5154 * Number constant. 5155 */ 5156 case '0': 5157 case '1': 5158 case '2': 5159 case '3': 5160 case '4': 5161 case '5': 5162 case '6': 5163 case '7': 5164 case '8': 5165 case '9': 5166 { 5167 #ifdef FEAT_FLOAT 5168 char_u *p = skipdigits(*arg + 1); 5169 int get_float = FALSE; 5170 5171 /* We accept a float when the format matches 5172 * "[0-9]\+\.[0-9]\+\([eE][+-]\?[0-9]\+\)\?". This is very 5173 * strict to avoid backwards compatibility problems. 5174 * Don't look for a float after the "." operator, so that 5175 * ":let vers = 1.2.3" doesn't fail. */ 5176 if (!want_string && p[0] == '.' && vim_isdigit(p[1])) 5177 { 5178 get_float = TRUE; 5179 p = skipdigits(p + 2); 5180 if (*p == 'e' || *p == 'E') 5181 { 5182 ++p; 5183 if (*p == '-' || *p == '+') 5184 ++p; 5185 if (!vim_isdigit(*p)) 5186 get_float = FALSE; 5187 else 5188 p = skipdigits(p + 1); 5189 } 5190 if (ASCII_ISALPHA(*p) || *p == '.') 5191 get_float = FALSE; 5192 } 5193 if (get_float) 5194 { 5195 float_T f; 5196 5197 *arg += string2float(*arg, &f); 5198 if (evaluate) 5199 { 5200 rettv->v_type = VAR_FLOAT; 5201 rettv->vval.v_float = f; 5202 } 5203 } 5204 else 5205 #endif 5206 { 5207 vim_str2nr(*arg, NULL, &len, STR2NR_ALL, &n, NULL, 0); 5208 *arg += len; 5209 if (evaluate) 5210 { 5211 rettv->v_type = VAR_NUMBER; 5212 rettv->vval.v_number = n; 5213 } 5214 } 5215 break; 5216 } 5217 5218 /* 5219 * String constant: "string". 5220 */ 5221 case '"': ret = get_string_tv(arg, rettv, evaluate); 5222 break; 5223 5224 /* 5225 * Literal string constant: 'str''ing'. 5226 */ 5227 case '\'': ret = get_lit_string_tv(arg, rettv, evaluate); 5228 break; 5229 5230 /* 5231 * List: [expr, expr] 5232 */ 5233 case '[': ret = get_list_tv(arg, rettv, evaluate); 5234 break; 5235 5236 /* 5237 * Dictionary: {key: val, key: val} 5238 */ 5239 case '{': ret = get_dict_tv(arg, rettv, evaluate); 5240 break; 5241 5242 /* 5243 * Option value: &name 5244 */ 5245 case '&': ret = get_option_tv(arg, rettv, evaluate); 5246 break; 5247 5248 /* 5249 * Environment variable: $VAR. 5250 */ 5251 case '$': ret = get_env_tv(arg, rettv, evaluate); 5252 break; 5253 5254 /* 5255 * Register contents: @r. 5256 */ 5257 case '@': ++*arg; 5258 if (evaluate) 5259 { 5260 rettv->v_type = VAR_STRING; 5261 rettv->vval.v_string = get_reg_contents(**arg, 5262 GREG_EXPR_SRC); 5263 } 5264 if (**arg != NUL) 5265 ++*arg; 5266 break; 5267 5268 /* 5269 * nested expression: (expression). 5270 */ 5271 case '(': *arg = skipwhite(*arg + 1); 5272 ret = eval1(arg, rettv, evaluate); /* recursive! */ 5273 if (**arg == ')') 5274 ++*arg; 5275 else if (ret == OK) 5276 { 5277 EMSG(_("E110: Missing ')'")); 5278 clear_tv(rettv); 5279 ret = FAIL; 5280 } 5281 break; 5282 5283 default: ret = NOTDONE; 5284 break; 5285 } 5286 5287 if (ret == NOTDONE) 5288 { 5289 /* 5290 * Must be a variable or function name. 5291 * Can also be a curly-braces kind of name: {expr}. 5292 */ 5293 s = *arg; 5294 len = get_name_len(arg, &alias, evaluate, TRUE); 5295 if (alias != NULL) 5296 s = alias; 5297 5298 if (len <= 0) 5299 ret = FAIL; 5300 else 5301 { 5302 if (**arg == '(') /* recursive! */ 5303 { 5304 partial_T *partial; 5305 5306 /* If "s" is the name of a variable of type VAR_FUNC 5307 * use its contents. */ 5308 s = deref_func_name(s, &len, &partial, !evaluate); 5309 5310 /* Invoke the function. */ 5311 ret = get_func_tv(s, len, rettv, arg, 5312 curwin->w_cursor.lnum, curwin->w_cursor.lnum, 5313 &len, evaluate, partial, NULL); 5314 5315 /* If evaluate is FALSE rettv->v_type was not set in 5316 * get_func_tv, but it's needed in handle_subscript() to parse 5317 * what follows. So set it here. */ 5318 if (rettv->v_type == VAR_UNKNOWN && !evaluate && **arg == '(') 5319 { 5320 rettv->vval.v_string = NULL; 5321 rettv->v_type = VAR_FUNC; 5322 } 5323 5324 /* Stop the expression evaluation when immediately 5325 * aborting on error, or when an interrupt occurred or 5326 * an exception was thrown but not caught. */ 5327 if (aborting()) 5328 { 5329 if (ret == OK) 5330 clear_tv(rettv); 5331 ret = FAIL; 5332 } 5333 } 5334 else if (evaluate) 5335 ret = get_var_tv(s, len, rettv, NULL, TRUE, FALSE); 5336 else 5337 ret = OK; 5338 } 5339 vim_free(alias); 5340 } 5341 5342 *arg = skipwhite(*arg); 5343 5344 /* Handle following '[', '(' and '.' for expr[expr], expr.name, 5345 * expr(expr). */ 5346 if (ret == OK) 5347 ret = handle_subscript(arg, rettv, evaluate, TRUE); 5348 5349 /* 5350 * Apply logical NOT and unary '-', from right to left, ignore '+'. 5351 */ 5352 if (ret == OK && evaluate && end_leader > start_leader) 5353 { 5354 int error = FALSE; 5355 int val = 0; 5356 #ifdef FEAT_FLOAT 5357 float_T f = 0.0; 5358 5359 if (rettv->v_type == VAR_FLOAT) 5360 f = rettv->vval.v_float; 5361 else 5362 #endif 5363 val = get_tv_number_chk(rettv, &error); 5364 if (error) 5365 { 5366 clear_tv(rettv); 5367 ret = FAIL; 5368 } 5369 else 5370 { 5371 while (end_leader > start_leader) 5372 { 5373 --end_leader; 5374 if (*end_leader == '!') 5375 { 5376 #ifdef FEAT_FLOAT 5377 if (rettv->v_type == VAR_FLOAT) 5378 f = !f; 5379 else 5380 #endif 5381 val = !val; 5382 } 5383 else if (*end_leader == '-') 5384 { 5385 #ifdef FEAT_FLOAT 5386 if (rettv->v_type == VAR_FLOAT) 5387 f = -f; 5388 else 5389 #endif 5390 val = -val; 5391 } 5392 } 5393 #ifdef FEAT_FLOAT 5394 if (rettv->v_type == VAR_FLOAT) 5395 { 5396 clear_tv(rettv); 5397 rettv->vval.v_float = f; 5398 } 5399 else 5400 #endif 5401 { 5402 clear_tv(rettv); 5403 rettv->v_type = VAR_NUMBER; 5404 rettv->vval.v_number = val; 5405 } 5406 } 5407 } 5408 5409 return ret; 5410 } 5411 5412 /* 5413 * Evaluate an "[expr]" or "[expr:expr]" index. Also "dict.key". 5414 * "*arg" points to the '[' or '.'. 5415 * Returns FAIL or OK. "*arg" is advanced to after the ']'. 5416 */ 5417 static int 5418 eval_index( 5419 char_u **arg, 5420 typval_T *rettv, 5421 int evaluate, 5422 int verbose) /* give error messages */ 5423 { 5424 int empty1 = FALSE, empty2 = FALSE; 5425 typval_T var1, var2; 5426 long n1, n2 = 0; 5427 long len = -1; 5428 int range = FALSE; 5429 char_u *s; 5430 char_u *key = NULL; 5431 5432 switch (rettv->v_type) 5433 { 5434 case VAR_FUNC: 5435 case VAR_PARTIAL: 5436 if (verbose) 5437 EMSG(_("E695: Cannot index a Funcref")); 5438 return FAIL; 5439 case VAR_FLOAT: 5440 #ifdef FEAT_FLOAT 5441 if (verbose) 5442 EMSG(_(e_float_as_string)); 5443 return FAIL; 5444 #endif 5445 case VAR_SPECIAL: 5446 case VAR_JOB: 5447 case VAR_CHANNEL: 5448 if (verbose) 5449 EMSG(_("E909: Cannot index a special variable")); 5450 return FAIL; 5451 case VAR_UNKNOWN: 5452 if (evaluate) 5453 return FAIL; 5454 /* FALLTHROUGH */ 5455 5456 case VAR_STRING: 5457 case VAR_NUMBER: 5458 case VAR_LIST: 5459 case VAR_DICT: 5460 break; 5461 } 5462 5463 init_tv(&var1); 5464 init_tv(&var2); 5465 if (**arg == '.') 5466 { 5467 /* 5468 * dict.name 5469 */ 5470 key = *arg + 1; 5471 for (len = 0; ASCII_ISALNUM(key[len]) || key[len] == '_'; ++len) 5472 ; 5473 if (len == 0) 5474 return FAIL; 5475 *arg = skipwhite(key + len); 5476 } 5477 else 5478 { 5479 /* 5480 * something[idx] 5481 * 5482 * Get the (first) variable from inside the []. 5483 */ 5484 *arg = skipwhite(*arg + 1); 5485 if (**arg == ':') 5486 empty1 = TRUE; 5487 else if (eval1(arg, &var1, evaluate) == FAIL) /* recursive! */ 5488 return FAIL; 5489 else if (evaluate && get_tv_string_chk(&var1) == NULL) 5490 { 5491 /* not a number or string */ 5492 clear_tv(&var1); 5493 return FAIL; 5494 } 5495 5496 /* 5497 * Get the second variable from inside the [:]. 5498 */ 5499 if (**arg == ':') 5500 { 5501 range = TRUE; 5502 *arg = skipwhite(*arg + 1); 5503 if (**arg == ']') 5504 empty2 = TRUE; 5505 else if (eval1(arg, &var2, evaluate) == FAIL) /* recursive! */ 5506 { 5507 if (!empty1) 5508 clear_tv(&var1); 5509 return FAIL; 5510 } 5511 else if (evaluate && get_tv_string_chk(&var2) == NULL) 5512 { 5513 /* not a number or string */ 5514 if (!empty1) 5515 clear_tv(&var1); 5516 clear_tv(&var2); 5517 return FAIL; 5518 } 5519 } 5520 5521 /* Check for the ']'. */ 5522 if (**arg != ']') 5523 { 5524 if (verbose) 5525 EMSG(_(e_missbrac)); 5526 clear_tv(&var1); 5527 if (range) 5528 clear_tv(&var2); 5529 return FAIL; 5530 } 5531 *arg = skipwhite(*arg + 1); /* skip the ']' */ 5532 } 5533 5534 if (evaluate) 5535 { 5536 n1 = 0; 5537 if (!empty1 && rettv->v_type != VAR_DICT) 5538 { 5539 n1 = get_tv_number(&var1); 5540 clear_tv(&var1); 5541 } 5542 if (range) 5543 { 5544 if (empty2) 5545 n2 = -1; 5546 else 5547 { 5548 n2 = get_tv_number(&var2); 5549 clear_tv(&var2); 5550 } 5551 } 5552 5553 switch (rettv->v_type) 5554 { 5555 case VAR_UNKNOWN: 5556 case VAR_FUNC: 5557 case VAR_PARTIAL: 5558 case VAR_FLOAT: 5559 case VAR_SPECIAL: 5560 case VAR_JOB: 5561 case VAR_CHANNEL: 5562 break; /* not evaluating, skipping over subscript */ 5563 5564 case VAR_NUMBER: 5565 case VAR_STRING: 5566 s = get_tv_string(rettv); 5567 len = (long)STRLEN(s); 5568 if (range) 5569 { 5570 /* The resulting variable is a substring. If the indexes 5571 * are out of range the result is empty. */ 5572 if (n1 < 0) 5573 { 5574 n1 = len + n1; 5575 if (n1 < 0) 5576 n1 = 0; 5577 } 5578 if (n2 < 0) 5579 n2 = len + n2; 5580 else if (n2 >= len) 5581 n2 = len; 5582 if (n1 >= len || n2 < 0 || n1 > n2) 5583 s = NULL; 5584 else 5585 s = vim_strnsave(s + n1, (int)(n2 - n1 + 1)); 5586 } 5587 else 5588 { 5589 /* The resulting variable is a string of a single 5590 * character. If the index is too big or negative the 5591 * result is empty. */ 5592 if (n1 >= len || n1 < 0) 5593 s = NULL; 5594 else 5595 s = vim_strnsave(s + n1, 1); 5596 } 5597 clear_tv(rettv); 5598 rettv->v_type = VAR_STRING; 5599 rettv->vval.v_string = s; 5600 break; 5601 5602 case VAR_LIST: 5603 len = list_len(rettv->vval.v_list); 5604 if (n1 < 0) 5605 n1 = len + n1; 5606 if (!empty1 && (n1 < 0 || n1 >= len)) 5607 { 5608 /* For a range we allow invalid values and return an empty 5609 * list. A list index out of range is an error. */ 5610 if (!range) 5611 { 5612 if (verbose) 5613 EMSGN(_(e_listidx), n1); 5614 return FAIL; 5615 } 5616 n1 = len; 5617 } 5618 if (range) 5619 { 5620 list_T *l; 5621 listitem_T *item; 5622 5623 if (n2 < 0) 5624 n2 = len + n2; 5625 else if (n2 >= len) 5626 n2 = len - 1; 5627 if (!empty2 && (n2 < 0 || n2 + 1 < n1)) 5628 n2 = -1; 5629 l = list_alloc(); 5630 if (l == NULL) 5631 return FAIL; 5632 for (item = list_find(rettv->vval.v_list, n1); 5633 n1 <= n2; ++n1) 5634 { 5635 if (list_append_tv(l, &item->li_tv) == FAIL) 5636 { 5637 list_free(l); 5638 return FAIL; 5639 } 5640 item = item->li_next; 5641 } 5642 clear_tv(rettv); 5643 rettv->v_type = VAR_LIST; 5644 rettv->vval.v_list = l; 5645 ++l->lv_refcount; 5646 } 5647 else 5648 { 5649 copy_tv(&list_find(rettv->vval.v_list, n1)->li_tv, &var1); 5650 clear_tv(rettv); 5651 *rettv = var1; 5652 } 5653 break; 5654 5655 case VAR_DICT: 5656 if (range) 5657 { 5658 if (verbose) 5659 EMSG(_(e_dictrange)); 5660 if (len == -1) 5661 clear_tv(&var1); 5662 return FAIL; 5663 } 5664 { 5665 dictitem_T *item; 5666 5667 if (len == -1) 5668 { 5669 key = get_tv_string_chk(&var1); 5670 if (key == NULL) 5671 { 5672 clear_tv(&var1); 5673 return FAIL; 5674 } 5675 } 5676 5677 item = dict_find(rettv->vval.v_dict, key, (int)len); 5678 5679 if (item == NULL && verbose) 5680 EMSG2(_(e_dictkey), key); 5681 if (len == -1) 5682 clear_tv(&var1); 5683 if (item == NULL) 5684 return FAIL; 5685 5686 copy_tv(&item->di_tv, &var1); 5687 clear_tv(rettv); 5688 *rettv = var1; 5689 } 5690 break; 5691 } 5692 } 5693 5694 return OK; 5695 } 5696 5697 /* 5698 * Get an option value. 5699 * "arg" points to the '&' or '+' before the option name. 5700 * "arg" is advanced to character after the option name. 5701 * Return OK or FAIL. 5702 */ 5703 static int 5704 get_option_tv( 5705 char_u **arg, 5706 typval_T *rettv, /* when NULL, only check if option exists */ 5707 int evaluate) 5708 { 5709 char_u *option_end; 5710 long numval; 5711 char_u *stringval; 5712 int opt_type; 5713 int c; 5714 int working = (**arg == '+'); /* has("+option") */ 5715 int ret = OK; 5716 int opt_flags; 5717 5718 /* 5719 * Isolate the option name and find its value. 5720 */ 5721 option_end = find_option_end(arg, &opt_flags); 5722 if (option_end == NULL) 5723 { 5724 if (rettv != NULL) 5725 EMSG2(_("E112: Option name missing: %s"), *arg); 5726 return FAIL; 5727 } 5728 5729 if (!evaluate) 5730 { 5731 *arg = option_end; 5732 return OK; 5733 } 5734 5735 c = *option_end; 5736 *option_end = NUL; 5737 opt_type = get_option_value(*arg, &numval, 5738 rettv == NULL ? NULL : &stringval, opt_flags); 5739 5740 if (opt_type == -3) /* invalid name */ 5741 { 5742 if (rettv != NULL) 5743 EMSG2(_("E113: Unknown option: %s"), *arg); 5744 ret = FAIL; 5745 } 5746 else if (rettv != NULL) 5747 { 5748 if (opt_type == -2) /* hidden string option */ 5749 { 5750 rettv->v_type = VAR_STRING; 5751 rettv->vval.v_string = NULL; 5752 } 5753 else if (opt_type == -1) /* hidden number option */ 5754 { 5755 rettv->v_type = VAR_NUMBER; 5756 rettv->vval.v_number = 0; 5757 } 5758 else if (opt_type == 1) /* number option */ 5759 { 5760 rettv->v_type = VAR_NUMBER; 5761 rettv->vval.v_number = numval; 5762 } 5763 else /* string option */ 5764 { 5765 rettv->v_type = VAR_STRING; 5766 rettv->vval.v_string = stringval; 5767 } 5768 } 5769 else if (working && (opt_type == -2 || opt_type == -1)) 5770 ret = FAIL; 5771 5772 *option_end = c; /* put back for error messages */ 5773 *arg = option_end; 5774 5775 return ret; 5776 } 5777 5778 /* 5779 * Allocate a variable for a string constant. 5780 * Return OK or FAIL. 5781 */ 5782 static int 5783 get_string_tv(char_u **arg, typval_T *rettv, int evaluate) 5784 { 5785 char_u *p; 5786 char_u *name; 5787 int extra = 0; 5788 5789 /* 5790 * Find the end of the string, skipping backslashed characters. 5791 */ 5792 for (p = *arg + 1; *p != NUL && *p != '"'; mb_ptr_adv(p)) 5793 { 5794 if (*p == '\\' && p[1] != NUL) 5795 { 5796 ++p; 5797 /* A "\<x>" form occupies at least 4 characters, and produces up 5798 * to 6 characters: reserve space for 2 extra */ 5799 if (*p == '<') 5800 extra += 2; 5801 } 5802 } 5803 5804 if (*p != '"') 5805 { 5806 EMSG2(_("E114: Missing quote: %s"), *arg); 5807 return FAIL; 5808 } 5809 5810 /* If only parsing, set *arg and return here */ 5811 if (!evaluate) 5812 { 5813 *arg = p + 1; 5814 return OK; 5815 } 5816 5817 /* 5818 * Copy the string into allocated memory, handling backslashed 5819 * characters. 5820 */ 5821 name = alloc((unsigned)(p - *arg + extra)); 5822 if (name == NULL) 5823 return FAIL; 5824 rettv->v_type = VAR_STRING; 5825 rettv->vval.v_string = name; 5826 5827 for (p = *arg + 1; *p != NUL && *p != '"'; ) 5828 { 5829 if (*p == '\\') 5830 { 5831 switch (*++p) 5832 { 5833 case 'b': *name++ = BS; ++p; break; 5834 case 'e': *name++ = ESC; ++p; break; 5835 case 'f': *name++ = FF; ++p; break; 5836 case 'n': *name++ = NL; ++p; break; 5837 case 'r': *name++ = CAR; ++p; break; 5838 case 't': *name++ = TAB; ++p; break; 5839 5840 case 'X': /* hex: "\x1", "\x12" */ 5841 case 'x': 5842 case 'u': /* Unicode: "\u0023" */ 5843 case 'U': 5844 if (vim_isxdigit(p[1])) 5845 { 5846 int n, nr; 5847 int c = toupper(*p); 5848 5849 if (c == 'X') 5850 n = 2; 5851 else if (*p == 'u') 5852 n = 4; 5853 else 5854 n = 8; 5855 nr = 0; 5856 while (--n >= 0 && vim_isxdigit(p[1])) 5857 { 5858 ++p; 5859 nr = (nr << 4) + hex2nr(*p); 5860 } 5861 ++p; 5862 #ifdef FEAT_MBYTE 5863 /* For "\u" store the number according to 5864 * 'encoding'. */ 5865 if (c != 'X') 5866 name += (*mb_char2bytes)(nr, name); 5867 else 5868 #endif 5869 *name++ = nr; 5870 } 5871 break; 5872 5873 /* octal: "\1", "\12", "\123" */ 5874 case '0': 5875 case '1': 5876 case '2': 5877 case '3': 5878 case '4': 5879 case '5': 5880 case '6': 5881 case '7': *name = *p++ - '0'; 5882 if (*p >= '0' && *p <= '7') 5883 { 5884 *name = (*name << 3) + *p++ - '0'; 5885 if (*p >= '0' && *p <= '7') 5886 *name = (*name << 3) + *p++ - '0'; 5887 } 5888 ++name; 5889 break; 5890 5891 /* Special key, e.g.: "\<C-W>" */ 5892 case '<': extra = trans_special(&p, name, TRUE); 5893 if (extra != 0) 5894 { 5895 name += extra; 5896 break; 5897 } 5898 /* FALLTHROUGH */ 5899 5900 default: MB_COPY_CHAR(p, name); 5901 break; 5902 } 5903 } 5904 else 5905 MB_COPY_CHAR(p, name); 5906 5907 } 5908 *name = NUL; 5909 *arg = p + 1; 5910 5911 return OK; 5912 } 5913 5914 /* 5915 * Allocate a variable for a 'str''ing' constant. 5916 * Return OK or FAIL. 5917 */ 5918 static int 5919 get_lit_string_tv(char_u **arg, typval_T *rettv, int evaluate) 5920 { 5921 char_u *p; 5922 char_u *str; 5923 int reduce = 0; 5924 5925 /* 5926 * Find the end of the string, skipping ''. 5927 */ 5928 for (p = *arg + 1; *p != NUL; mb_ptr_adv(p)) 5929 { 5930 if (*p == '\'') 5931 { 5932 if (p[1] != '\'') 5933 break; 5934 ++reduce; 5935 ++p; 5936 } 5937 } 5938 5939 if (*p != '\'') 5940 { 5941 EMSG2(_("E115: Missing quote: %s"), *arg); 5942 return FAIL; 5943 } 5944 5945 /* If only parsing return after setting "*arg" */ 5946 if (!evaluate) 5947 { 5948 *arg = p + 1; 5949 return OK; 5950 } 5951 5952 /* 5953 * Copy the string into allocated memory, handling '' to ' reduction. 5954 */ 5955 str = alloc((unsigned)((p - *arg) - reduce)); 5956 if (str == NULL) 5957 return FAIL; 5958 rettv->v_type = VAR_STRING; 5959 rettv->vval.v_string = str; 5960 5961 for (p = *arg + 1; *p != NUL; ) 5962 { 5963 if (*p == '\'') 5964 { 5965 if (p[1] != '\'') 5966 break; 5967 ++p; 5968 } 5969 MB_COPY_CHAR(p, str); 5970 } 5971 *str = NUL; 5972 *arg = p + 1; 5973 5974 return OK; 5975 } 5976 5977 static void 5978 partial_free(partial_T *pt) 5979 { 5980 int i; 5981 5982 for (i = 0; i < pt->pt_argc; ++i) 5983 clear_tv(&pt->pt_argv[i]); 5984 vim_free(pt->pt_argv); 5985 dict_unref(pt->pt_dict); 5986 func_unref(pt->pt_name); 5987 vim_free(pt->pt_name); 5988 vim_free(pt); 5989 } 5990 5991 /* 5992 * Unreference a closure: decrement the reference count and free it when it 5993 * becomes zero. 5994 */ 5995 void 5996 partial_unref(partial_T *pt) 5997 { 5998 if (pt != NULL && --pt->pt_refcount <= 0) 5999 partial_free(pt); 6000 } 6001 6002 /* 6003 * Allocate a variable for a List and fill it from "*arg". 6004 * Return OK or FAIL. 6005 */ 6006 static int 6007 get_list_tv(char_u **arg, typval_T *rettv, int evaluate) 6008 { 6009 list_T *l = NULL; 6010 typval_T tv; 6011 listitem_T *item; 6012 6013 if (evaluate) 6014 { 6015 l = list_alloc(); 6016 if (l == NULL) 6017 return FAIL; 6018 } 6019 6020 *arg = skipwhite(*arg + 1); 6021 while (**arg != ']' && **arg != NUL) 6022 { 6023 if (eval1(arg, &tv, evaluate) == FAIL) /* recursive! */ 6024 goto failret; 6025 if (evaluate) 6026 { 6027 item = listitem_alloc(); 6028 if (item != NULL) 6029 { 6030 item->li_tv = tv; 6031 item->li_tv.v_lock = 0; 6032 list_append(l, item); 6033 } 6034 else 6035 clear_tv(&tv); 6036 } 6037 6038 if (**arg == ']') 6039 break; 6040 if (**arg != ',') 6041 { 6042 EMSG2(_("E696: Missing comma in List: %s"), *arg); 6043 goto failret; 6044 } 6045 *arg = skipwhite(*arg + 1); 6046 } 6047 6048 if (**arg != ']') 6049 { 6050 EMSG2(_("E697: Missing end of List ']': %s"), *arg); 6051 failret: 6052 if (evaluate) 6053 list_free(l); 6054 return FAIL; 6055 } 6056 6057 *arg = skipwhite(*arg + 1); 6058 if (evaluate) 6059 { 6060 rettv->v_type = VAR_LIST; 6061 rettv->vval.v_list = l; 6062 ++l->lv_refcount; 6063 } 6064 6065 return OK; 6066 } 6067 6068 /* 6069 * Allocate an empty header for a list. 6070 * Caller should take care of the reference count. 6071 */ 6072 list_T * 6073 list_alloc(void) 6074 { 6075 list_T *l; 6076 6077 l = (list_T *)alloc_clear(sizeof(list_T)); 6078 if (l != NULL) 6079 { 6080 /* Prepend the list to the list of lists for garbage collection. */ 6081 if (first_list != NULL) 6082 first_list->lv_used_prev = l; 6083 l->lv_used_prev = NULL; 6084 l->lv_used_next = first_list; 6085 first_list = l; 6086 } 6087 return l; 6088 } 6089 6090 /* 6091 * Allocate an empty list for a return value, with reference count set. 6092 * Returns OK or FAIL. 6093 */ 6094 int 6095 rettv_list_alloc(typval_T *rettv) 6096 { 6097 list_T *l = list_alloc(); 6098 6099 if (l == NULL) 6100 return FAIL; 6101 6102 rettv->vval.v_list = l; 6103 rettv->v_type = VAR_LIST; 6104 rettv->v_lock = 0; 6105 ++l->lv_refcount; 6106 return OK; 6107 } 6108 6109 /* 6110 * Unreference a list: decrement the reference count and free it when it 6111 * becomes zero. 6112 */ 6113 void 6114 list_unref(list_T *l) 6115 { 6116 if (l != NULL && --l->lv_refcount <= 0) 6117 list_free(l); 6118 } 6119 6120 /* 6121 * Free a list, including all non-container items it points to. 6122 * Ignores the reference count. 6123 */ 6124 static void 6125 list_free_contents(list_T *l) 6126 { 6127 listitem_T *item; 6128 6129 for (item = l->lv_first; item != NULL; item = l->lv_first) 6130 { 6131 /* Remove the item before deleting it. */ 6132 l->lv_first = item->li_next; 6133 clear_tv(&item->li_tv); 6134 vim_free(item); 6135 } 6136 } 6137 6138 static void 6139 list_free_list(list_T *l) 6140 { 6141 /* Remove the list from the list of lists for garbage collection. */ 6142 if (l->lv_used_prev == NULL) 6143 first_list = l->lv_used_next; 6144 else 6145 l->lv_used_prev->lv_used_next = l->lv_used_next; 6146 if (l->lv_used_next != NULL) 6147 l->lv_used_next->lv_used_prev = l->lv_used_prev; 6148 6149 vim_free(l); 6150 } 6151 6152 void 6153 list_free(list_T *l) 6154 { 6155 if (!in_free_unref_items) 6156 { 6157 list_free_contents(l); 6158 list_free_list(l); 6159 } 6160 } 6161 6162 /* 6163 * Allocate a list item. 6164 * It is not initialized, don't forget to set v_lock. 6165 */ 6166 listitem_T * 6167 listitem_alloc(void) 6168 { 6169 return (listitem_T *)alloc(sizeof(listitem_T)); 6170 } 6171 6172 /* 6173 * Free a list item. Also clears the value. Does not notify watchers. 6174 */ 6175 void 6176 listitem_free(listitem_T *item) 6177 { 6178 clear_tv(&item->li_tv); 6179 vim_free(item); 6180 } 6181 6182 /* 6183 * Remove a list item from a List and free it. Also clears the value. 6184 */ 6185 void 6186 listitem_remove(list_T *l, listitem_T *item) 6187 { 6188 vimlist_remove(l, item, item); 6189 listitem_free(item); 6190 } 6191 6192 /* 6193 * Get the number of items in a list. 6194 */ 6195 static long 6196 list_len(list_T *l) 6197 { 6198 if (l == NULL) 6199 return 0L; 6200 return l->lv_len; 6201 } 6202 6203 /* 6204 * Return TRUE when two lists have exactly the same values. 6205 */ 6206 static int 6207 list_equal( 6208 list_T *l1, 6209 list_T *l2, 6210 int ic, /* ignore case for strings */ 6211 int recursive) /* TRUE when used recursively */ 6212 { 6213 listitem_T *item1, *item2; 6214 6215 if (l1 == NULL || l2 == NULL) 6216 return FALSE; 6217 if (l1 == l2) 6218 return TRUE; 6219 if (list_len(l1) != list_len(l2)) 6220 return FALSE; 6221 6222 for (item1 = l1->lv_first, item2 = l2->lv_first; 6223 item1 != NULL && item2 != NULL; 6224 item1 = item1->li_next, item2 = item2->li_next) 6225 if (!tv_equal(&item1->li_tv, &item2->li_tv, ic, recursive)) 6226 return FALSE; 6227 return item1 == NULL && item2 == NULL; 6228 } 6229 6230 /* 6231 * Return the dictitem that an entry in a hashtable points to. 6232 */ 6233 dictitem_T * 6234 dict_lookup(hashitem_T *hi) 6235 { 6236 return HI2DI(hi); 6237 } 6238 6239 /* 6240 * Return TRUE when two dictionaries have exactly the same key/values. 6241 */ 6242 static int 6243 dict_equal( 6244 dict_T *d1, 6245 dict_T *d2, 6246 int ic, /* ignore case for strings */ 6247 int recursive) /* TRUE when used recursively */ 6248 { 6249 hashitem_T *hi; 6250 dictitem_T *item2; 6251 int todo; 6252 6253 if (d1 == NULL && d2 == NULL) 6254 return TRUE; 6255 if (d1 == NULL || d2 == NULL) 6256 return FALSE; 6257 if (d1 == d2) 6258 return TRUE; 6259 if (dict_len(d1) != dict_len(d2)) 6260 return FALSE; 6261 6262 todo = (int)d1->dv_hashtab.ht_used; 6263 for (hi = d1->dv_hashtab.ht_array; todo > 0; ++hi) 6264 { 6265 if (!HASHITEM_EMPTY(hi)) 6266 { 6267 item2 = dict_find(d2, hi->hi_key, -1); 6268 if (item2 == NULL) 6269 return FALSE; 6270 if (!tv_equal(&HI2DI(hi)->di_tv, &item2->di_tv, ic, recursive)) 6271 return FALSE; 6272 --todo; 6273 } 6274 } 6275 return TRUE; 6276 } 6277 6278 static int tv_equal_recurse_limit; 6279 6280 static int 6281 func_equal( 6282 typval_T *tv1, 6283 typval_T *tv2, 6284 int ic) /* ignore case */ 6285 { 6286 char_u *s1, *s2; 6287 dict_T *d1, *d2; 6288 int a1, a2; 6289 int i; 6290 6291 /* empty and NULL function name considered the same */ 6292 s1 = tv1->v_type == VAR_FUNC ? tv1->vval.v_string 6293 : tv1->vval.v_partial->pt_name; 6294 if (s1 != NULL && *s1 == NUL) 6295 s1 = NULL; 6296 s2 = tv2->v_type == VAR_FUNC ? tv2->vval.v_string 6297 : tv2->vval.v_partial->pt_name; 6298 if (s2 != NULL && *s2 == NUL) 6299 s2 = NULL; 6300 if (s1 == NULL || s2 == NULL) 6301 { 6302 if (s1 != s2) 6303 return FALSE; 6304 } 6305 else if (STRCMP(s1, s2) != 0) 6306 return FALSE; 6307 6308 /* empty dict and NULL dict is different */ 6309 d1 = tv1->v_type == VAR_FUNC ? NULL : tv1->vval.v_partial->pt_dict; 6310 d2 = tv2->v_type == VAR_FUNC ? NULL : tv2->vval.v_partial->pt_dict; 6311 if (d1 == NULL || d2 == NULL) 6312 { 6313 if (d1 != d2) 6314 return FALSE; 6315 } 6316 else if (!dict_equal(d1, d2, ic, TRUE)) 6317 return FALSE; 6318 6319 /* empty list and no list considered the same */ 6320 a1 = tv1->v_type == VAR_FUNC ? 0 : tv1->vval.v_partial->pt_argc; 6321 a2 = tv2->v_type == VAR_FUNC ? 0 : tv2->vval.v_partial->pt_argc; 6322 if (a1 != a2) 6323 return FALSE; 6324 for (i = 0; i < a1; ++i) 6325 if (!tv_equal(tv1->vval.v_partial->pt_argv + i, 6326 tv2->vval.v_partial->pt_argv + i, ic, TRUE)) 6327 return FALSE; 6328 6329 return TRUE; 6330 } 6331 6332 /* 6333 * Return TRUE if "tv1" and "tv2" have the same value. 6334 * Compares the items just like "==" would compare them, but strings and 6335 * numbers are different. Floats and numbers are also different. 6336 */ 6337 static int 6338 tv_equal( 6339 typval_T *tv1, 6340 typval_T *tv2, 6341 int ic, /* ignore case */ 6342 int recursive) /* TRUE when used recursively */ 6343 { 6344 char_u buf1[NUMBUFLEN], buf2[NUMBUFLEN]; 6345 char_u *s1, *s2; 6346 static int recursive_cnt = 0; /* catch recursive loops */ 6347 int r; 6348 6349 /* Catch lists and dicts that have an endless loop by limiting 6350 * recursiveness to a limit. We guess they are equal then. 6351 * A fixed limit has the problem of still taking an awful long time. 6352 * Reduce the limit every time running into it. That should work fine for 6353 * deeply linked structures that are not recursively linked and catch 6354 * recursiveness quickly. */ 6355 if (!recursive) 6356 tv_equal_recurse_limit = 1000; 6357 if (recursive_cnt >= tv_equal_recurse_limit) 6358 { 6359 --tv_equal_recurse_limit; 6360 return TRUE; 6361 } 6362 6363 /* For VAR_FUNC and VAR_PARTIAL only compare the function name. */ 6364 if ((tv1->v_type == VAR_FUNC 6365 || (tv1->v_type == VAR_PARTIAL && tv1->vval.v_partial != NULL)) 6366 && (tv2->v_type == VAR_FUNC 6367 || (tv2->v_type == VAR_PARTIAL && tv2->vval.v_partial != NULL))) 6368 { 6369 ++recursive_cnt; 6370 r = func_equal(tv1, tv2, ic); 6371 --recursive_cnt; 6372 return r; 6373 } 6374 6375 if (tv1->v_type != tv2->v_type) 6376 return FALSE; 6377 6378 switch (tv1->v_type) 6379 { 6380 case VAR_LIST: 6381 ++recursive_cnt; 6382 r = list_equal(tv1->vval.v_list, tv2->vval.v_list, ic, TRUE); 6383 --recursive_cnt; 6384 return r; 6385 6386 case VAR_DICT: 6387 ++recursive_cnt; 6388 r = dict_equal(tv1->vval.v_dict, tv2->vval.v_dict, ic, TRUE); 6389 --recursive_cnt; 6390 return r; 6391 6392 case VAR_NUMBER: 6393 return tv1->vval.v_number == tv2->vval.v_number; 6394 6395 case VAR_STRING: 6396 s1 = get_tv_string_buf(tv1, buf1); 6397 s2 = get_tv_string_buf(tv2, buf2); 6398 return ((ic ? MB_STRICMP(s1, s2) : STRCMP(s1, s2)) == 0); 6399 6400 case VAR_SPECIAL: 6401 return tv1->vval.v_number == tv2->vval.v_number; 6402 6403 case VAR_FLOAT: 6404 #ifdef FEAT_FLOAT 6405 return tv1->vval.v_float == tv2->vval.v_float; 6406 #endif 6407 case VAR_JOB: 6408 #ifdef FEAT_JOB_CHANNEL 6409 return tv1->vval.v_job == tv2->vval.v_job; 6410 #endif 6411 case VAR_CHANNEL: 6412 #ifdef FEAT_JOB_CHANNEL 6413 return tv1->vval.v_channel == tv2->vval.v_channel; 6414 #endif 6415 case VAR_FUNC: 6416 case VAR_PARTIAL: 6417 case VAR_UNKNOWN: 6418 break; 6419 } 6420 6421 /* VAR_UNKNOWN can be the result of a invalid expression, let's say it 6422 * does not equal anything, not even itself. */ 6423 return FALSE; 6424 } 6425 6426 /* 6427 * Locate item with index "n" in list "l" and return it. 6428 * A negative index is counted from the end; -1 is the last item. 6429 * Returns NULL when "n" is out of range. 6430 */ 6431 listitem_T * 6432 list_find(list_T *l, long n) 6433 { 6434 listitem_T *item; 6435 long idx; 6436 6437 if (l == NULL) 6438 return NULL; 6439 6440 /* Negative index is relative to the end. */ 6441 if (n < 0) 6442 n = l->lv_len + n; 6443 6444 /* Check for index out of range. */ 6445 if (n < 0 || n >= l->lv_len) 6446 return NULL; 6447 6448 /* When there is a cached index may start search from there. */ 6449 if (l->lv_idx_item != NULL) 6450 { 6451 if (n < l->lv_idx / 2) 6452 { 6453 /* closest to the start of the list */ 6454 item = l->lv_first; 6455 idx = 0; 6456 } 6457 else if (n > (l->lv_idx + l->lv_len) / 2) 6458 { 6459 /* closest to the end of the list */ 6460 item = l->lv_last; 6461 idx = l->lv_len - 1; 6462 } 6463 else 6464 { 6465 /* closest to the cached index */ 6466 item = l->lv_idx_item; 6467 idx = l->lv_idx; 6468 } 6469 } 6470 else 6471 { 6472 if (n < l->lv_len / 2) 6473 { 6474 /* closest to the start of the list */ 6475 item = l->lv_first; 6476 idx = 0; 6477 } 6478 else 6479 { 6480 /* closest to the end of the list */ 6481 item = l->lv_last; 6482 idx = l->lv_len - 1; 6483 } 6484 } 6485 6486 while (n > idx) 6487 { 6488 /* search forward */ 6489 item = item->li_next; 6490 ++idx; 6491 } 6492 while (n < idx) 6493 { 6494 /* search backward */ 6495 item = item->li_prev; 6496 --idx; 6497 } 6498 6499 /* cache the used index */ 6500 l->lv_idx = idx; 6501 l->lv_idx_item = item; 6502 6503 return item; 6504 } 6505 6506 /* 6507 * Get list item "l[idx]" as a number. 6508 */ 6509 static long 6510 list_find_nr( 6511 list_T *l, 6512 long idx, 6513 int *errorp) /* set to TRUE when something wrong */ 6514 { 6515 listitem_T *li; 6516 6517 li = list_find(l, idx); 6518 if (li == NULL) 6519 { 6520 if (errorp != NULL) 6521 *errorp = TRUE; 6522 return -1L; 6523 } 6524 return get_tv_number_chk(&li->li_tv, errorp); 6525 } 6526 6527 /* 6528 * Get list item "l[idx - 1]" as a string. Returns NULL for failure. 6529 */ 6530 char_u * 6531 list_find_str(list_T *l, long idx) 6532 { 6533 listitem_T *li; 6534 6535 li = list_find(l, idx - 1); 6536 if (li == NULL) 6537 { 6538 EMSGN(_(e_listidx), idx); 6539 return NULL; 6540 } 6541 return get_tv_string(&li->li_tv); 6542 } 6543 6544 /* 6545 * Locate "item" list "l" and return its index. 6546 * Returns -1 when "item" is not in the list. 6547 */ 6548 static long 6549 list_idx_of_item(list_T *l, listitem_T *item) 6550 { 6551 long idx = 0; 6552 listitem_T *li; 6553 6554 if (l == NULL) 6555 return -1; 6556 idx = 0; 6557 for (li = l->lv_first; li != NULL && li != item; li = li->li_next) 6558 ++idx; 6559 if (li == NULL) 6560 return -1; 6561 return idx; 6562 } 6563 6564 /* 6565 * Append item "item" to the end of list "l". 6566 */ 6567 void 6568 list_append(list_T *l, listitem_T *item) 6569 { 6570 if (l->lv_last == NULL) 6571 { 6572 /* empty list */ 6573 l->lv_first = item; 6574 l->lv_last = item; 6575 item->li_prev = NULL; 6576 } 6577 else 6578 { 6579 l->lv_last->li_next = item; 6580 item->li_prev = l->lv_last; 6581 l->lv_last = item; 6582 } 6583 ++l->lv_len; 6584 item->li_next = NULL; 6585 } 6586 6587 /* 6588 * Append typval_T "tv" to the end of list "l". 6589 * Return FAIL when out of memory. 6590 */ 6591 int 6592 list_append_tv(list_T *l, typval_T *tv) 6593 { 6594 listitem_T *li = listitem_alloc(); 6595 6596 if (li == NULL) 6597 return FAIL; 6598 copy_tv(tv, &li->li_tv); 6599 list_append(l, li); 6600 return OK; 6601 } 6602 6603 /* 6604 * Add a dictionary to a list. Used by getqflist(). 6605 * Return FAIL when out of memory. 6606 */ 6607 int 6608 list_append_dict(list_T *list, dict_T *dict) 6609 { 6610 listitem_T *li = listitem_alloc(); 6611 6612 if (li == NULL) 6613 return FAIL; 6614 li->li_tv.v_type = VAR_DICT; 6615 li->li_tv.v_lock = 0; 6616 li->li_tv.vval.v_dict = dict; 6617 list_append(list, li); 6618 ++dict->dv_refcount; 6619 return OK; 6620 } 6621 6622 /* 6623 * Make a copy of "str" and append it as an item to list "l". 6624 * When "len" >= 0 use "str[len]". 6625 * Returns FAIL when out of memory. 6626 */ 6627 int 6628 list_append_string(list_T *l, char_u *str, int len) 6629 { 6630 listitem_T *li = listitem_alloc(); 6631 6632 if (li == NULL) 6633 return FAIL; 6634 list_append(l, li); 6635 li->li_tv.v_type = VAR_STRING; 6636 li->li_tv.v_lock = 0; 6637 if (str == NULL) 6638 li->li_tv.vval.v_string = NULL; 6639 else if ((li->li_tv.vval.v_string = (len >= 0 ? vim_strnsave(str, len) 6640 : vim_strsave(str))) == NULL) 6641 return FAIL; 6642 return OK; 6643 } 6644 6645 /* 6646 * Append "n" to list "l". 6647 * Returns FAIL when out of memory. 6648 */ 6649 int 6650 list_append_number(list_T *l, varnumber_T n) 6651 { 6652 listitem_T *li; 6653 6654 li = listitem_alloc(); 6655 if (li == NULL) 6656 return FAIL; 6657 li->li_tv.v_type = VAR_NUMBER; 6658 li->li_tv.v_lock = 0; 6659 li->li_tv.vval.v_number = n; 6660 list_append(l, li); 6661 return OK; 6662 } 6663 6664 /* 6665 * Insert typval_T "tv" in list "l" before "item". 6666 * If "item" is NULL append at the end. 6667 * Return FAIL when out of memory. 6668 */ 6669 int 6670 list_insert_tv(list_T *l, typval_T *tv, listitem_T *item) 6671 { 6672 listitem_T *ni = listitem_alloc(); 6673 6674 if (ni == NULL) 6675 return FAIL; 6676 copy_tv(tv, &ni->li_tv); 6677 list_insert(l, ni, item); 6678 return OK; 6679 } 6680 6681 void 6682 list_insert(list_T *l, listitem_T *ni, listitem_T *item) 6683 { 6684 if (item == NULL) 6685 /* Append new item at end of list. */ 6686 list_append(l, ni); 6687 else 6688 { 6689 /* Insert new item before existing item. */ 6690 ni->li_prev = item->li_prev; 6691 ni->li_next = item; 6692 if (item->li_prev == NULL) 6693 { 6694 l->lv_first = ni; 6695 ++l->lv_idx; 6696 } 6697 else 6698 { 6699 item->li_prev->li_next = ni; 6700 l->lv_idx_item = NULL; 6701 } 6702 item->li_prev = ni; 6703 ++l->lv_len; 6704 } 6705 } 6706 6707 /* 6708 * Extend "l1" with "l2". 6709 * If "bef" is NULL append at the end, otherwise insert before this item. 6710 * Returns FAIL when out of memory. 6711 */ 6712 static int 6713 list_extend(list_T *l1, list_T *l2, listitem_T *bef) 6714 { 6715 listitem_T *item; 6716 int todo = l2->lv_len; 6717 6718 /* We also quit the loop when we have inserted the original item count of 6719 * the list, avoid a hang when we extend a list with itself. */ 6720 for (item = l2->lv_first; item != NULL && --todo >= 0; item = item->li_next) 6721 if (list_insert_tv(l1, &item->li_tv, bef) == FAIL) 6722 return FAIL; 6723 return OK; 6724 } 6725 6726 /* 6727 * Concatenate lists "l1" and "l2" into a new list, stored in "tv". 6728 * Return FAIL when out of memory. 6729 */ 6730 static int 6731 list_concat(list_T *l1, list_T *l2, typval_T *tv) 6732 { 6733 list_T *l; 6734 6735 if (l1 == NULL || l2 == NULL) 6736 return FAIL; 6737 6738 /* make a copy of the first list. */ 6739 l = list_copy(l1, FALSE, 0); 6740 if (l == NULL) 6741 return FAIL; 6742 tv->v_type = VAR_LIST; 6743 tv->vval.v_list = l; 6744 6745 /* append all items from the second list */ 6746 return list_extend(l, l2, NULL); 6747 } 6748 6749 /* 6750 * Make a copy of list "orig". Shallow if "deep" is FALSE. 6751 * The refcount of the new list is set to 1. 6752 * See item_copy() for "copyID". 6753 * Returns NULL when out of memory. 6754 */ 6755 static list_T * 6756 list_copy(list_T *orig, int deep, int copyID) 6757 { 6758 list_T *copy; 6759 listitem_T *item; 6760 listitem_T *ni; 6761 6762 if (orig == NULL) 6763 return NULL; 6764 6765 copy = list_alloc(); 6766 if (copy != NULL) 6767 { 6768 if (copyID != 0) 6769 { 6770 /* Do this before adding the items, because one of the items may 6771 * refer back to this list. */ 6772 orig->lv_copyID = copyID; 6773 orig->lv_copylist = copy; 6774 } 6775 for (item = orig->lv_first; item != NULL && !got_int; 6776 item = item->li_next) 6777 { 6778 ni = listitem_alloc(); 6779 if (ni == NULL) 6780 break; 6781 if (deep) 6782 { 6783 if (item_copy(&item->li_tv, &ni->li_tv, deep, copyID) == FAIL) 6784 { 6785 vim_free(ni); 6786 break; 6787 } 6788 } 6789 else 6790 copy_tv(&item->li_tv, &ni->li_tv); 6791 list_append(copy, ni); 6792 } 6793 ++copy->lv_refcount; 6794 if (item != NULL) 6795 { 6796 list_unref(copy); 6797 copy = NULL; 6798 } 6799 } 6800 6801 return copy; 6802 } 6803 6804 /* 6805 * Remove items "item" to "item2" from list "l". 6806 * Does not free the listitem or the value! 6807 * This used to be called list_remove, but that conflicts with a Sun header 6808 * file. 6809 */ 6810 void 6811 vimlist_remove(list_T *l, listitem_T *item, listitem_T *item2) 6812 { 6813 listitem_T *ip; 6814 6815 /* notify watchers */ 6816 for (ip = item; ip != NULL; ip = ip->li_next) 6817 { 6818 --l->lv_len; 6819 list_fix_watch(l, ip); 6820 if (ip == item2) 6821 break; 6822 } 6823 6824 if (item2->li_next == NULL) 6825 l->lv_last = item->li_prev; 6826 else 6827 item2->li_next->li_prev = item->li_prev; 6828 if (item->li_prev == NULL) 6829 l->lv_first = item2->li_next; 6830 else 6831 item->li_prev->li_next = item2->li_next; 6832 l->lv_idx_item = NULL; 6833 } 6834 6835 /* 6836 * Return an allocated string with the string representation of a list. 6837 * May return NULL. 6838 */ 6839 static char_u * 6840 list2string(typval_T *tv, int copyID, int restore_copyID) 6841 { 6842 garray_T ga; 6843 6844 if (tv->vval.v_list == NULL) 6845 return NULL; 6846 ga_init2(&ga, (int)sizeof(char), 80); 6847 ga_append(&ga, '['); 6848 if (list_join(&ga, tv->vval.v_list, (char_u *)", ", 6849 FALSE, restore_copyID, copyID) == FAIL) 6850 { 6851 vim_free(ga.ga_data); 6852 return NULL; 6853 } 6854 ga_append(&ga, ']'); 6855 ga_append(&ga, NUL); 6856 return (char_u *)ga.ga_data; 6857 } 6858 6859 typedef struct join_S { 6860 char_u *s; 6861 char_u *tofree; 6862 } join_T; 6863 6864 static int 6865 list_join_inner( 6866 garray_T *gap, /* to store the result in */ 6867 list_T *l, 6868 char_u *sep, 6869 int echo_style, 6870 int restore_copyID, 6871 int copyID, 6872 garray_T *join_gap) /* to keep each list item string */ 6873 { 6874 int i; 6875 join_T *p; 6876 int len; 6877 int sumlen = 0; 6878 int first = TRUE; 6879 char_u *tofree; 6880 char_u numbuf[NUMBUFLEN]; 6881 listitem_T *item; 6882 char_u *s; 6883 6884 /* Stringify each item in the list. */ 6885 for (item = l->lv_first; item != NULL && !got_int; item = item->li_next) 6886 { 6887 s = echo_string_core(&item->li_tv, &tofree, numbuf, copyID, 6888 echo_style, restore_copyID, FALSE); 6889 if (s == NULL) 6890 return FAIL; 6891 6892 len = (int)STRLEN(s); 6893 sumlen += len; 6894 6895 (void)ga_grow(join_gap, 1); 6896 p = ((join_T *)join_gap->ga_data) + (join_gap->ga_len++); 6897 if (tofree != NULL || s != numbuf) 6898 { 6899 p->s = s; 6900 p->tofree = tofree; 6901 } 6902 else 6903 { 6904 p->s = vim_strnsave(s, len); 6905 p->tofree = p->s; 6906 } 6907 6908 line_breakcheck(); 6909 if (did_echo_string_emsg) /* recursion error, bail out */ 6910 break; 6911 } 6912 6913 /* Allocate result buffer with its total size, avoid re-allocation and 6914 * multiple copy operations. Add 2 for a tailing ']' and NUL. */ 6915 if (join_gap->ga_len >= 2) 6916 sumlen += (int)STRLEN(sep) * (join_gap->ga_len - 1); 6917 if (ga_grow(gap, sumlen + 2) == FAIL) 6918 return FAIL; 6919 6920 for (i = 0; i < join_gap->ga_len && !got_int; ++i) 6921 { 6922 if (first) 6923 first = FALSE; 6924 else 6925 ga_concat(gap, sep); 6926 p = ((join_T *)join_gap->ga_data) + i; 6927 6928 if (p->s != NULL) 6929 ga_concat(gap, p->s); 6930 line_breakcheck(); 6931 } 6932 6933 return OK; 6934 } 6935 6936 /* 6937 * Join list "l" into a string in "*gap", using separator "sep". 6938 * When "echo_style" is TRUE use String as echoed, otherwise as inside a List. 6939 * Return FAIL or OK. 6940 */ 6941 static int 6942 list_join( 6943 garray_T *gap, 6944 list_T *l, 6945 char_u *sep, 6946 int echo_style, 6947 int restore_copyID, 6948 int copyID) 6949 { 6950 garray_T join_ga; 6951 int retval; 6952 join_T *p; 6953 int i; 6954 6955 if (l->lv_len < 1) 6956 return OK; /* nothing to do */ 6957 ga_init2(&join_ga, (int)sizeof(join_T), l->lv_len); 6958 retval = list_join_inner(gap, l, sep, echo_style, restore_copyID, 6959 copyID, &join_ga); 6960 6961 /* Dispose each item in join_ga. */ 6962 if (join_ga.ga_data != NULL) 6963 { 6964 p = (join_T *)join_ga.ga_data; 6965 for (i = 0; i < join_ga.ga_len; ++i) 6966 { 6967 vim_free(p->tofree); 6968 ++p; 6969 } 6970 ga_clear(&join_ga); 6971 } 6972 6973 return retval; 6974 } 6975 6976 /* 6977 * Return the next (unique) copy ID. 6978 * Used for serializing nested structures. 6979 */ 6980 int 6981 get_copyID(void) 6982 { 6983 current_copyID += COPYID_INC; 6984 return current_copyID; 6985 } 6986 6987 /* Used by get_func_tv() */ 6988 static garray_T funcargs = GA_EMPTY; 6989 6990 /* 6991 * Garbage collection for lists and dictionaries. 6992 * 6993 * We use reference counts to be able to free most items right away when they 6994 * are no longer used. But for composite items it's possible that it becomes 6995 * unused while the reference count is > 0: When there is a recursive 6996 * reference. Example: 6997 * :let l = [1, 2, 3] 6998 * :let d = {9: l} 6999 * :let l[1] = d 7000 * 7001 * Since this is quite unusual we handle this with garbage collection: every 7002 * once in a while find out which lists and dicts are not referenced from any 7003 * variable. 7004 * 7005 * Here is a good reference text about garbage collection (refers to Python 7006 * but it applies to all reference-counting mechanisms): 7007 * http://python.ca/nas/python/gc/ 7008 */ 7009 7010 /* 7011 * Do garbage collection for lists and dicts. 7012 * When "testing" is TRUE this is called from test_garbagecollect_now(). 7013 * Return TRUE if some memory was freed. 7014 */ 7015 int 7016 garbage_collect(int testing) 7017 { 7018 int copyID; 7019 int abort = FALSE; 7020 buf_T *buf; 7021 win_T *wp; 7022 int i; 7023 funccall_T *fc, **pfc; 7024 int did_free = FALSE; 7025 int did_free_funccal = FALSE; 7026 #ifdef FEAT_WINDOWS 7027 tabpage_T *tp; 7028 #endif 7029 7030 if (!testing) 7031 { 7032 /* Only do this once. */ 7033 want_garbage_collect = FALSE; 7034 may_garbage_collect = FALSE; 7035 garbage_collect_at_exit = FALSE; 7036 } 7037 7038 /* We advance by two because we add one for items referenced through 7039 * previous_funccal. */ 7040 copyID = get_copyID(); 7041 7042 /* 7043 * 1. Go through all accessible variables and mark all lists and dicts 7044 * with copyID. 7045 */ 7046 7047 /* Don't free variables in the previous_funccal list unless they are only 7048 * referenced through previous_funccal. This must be first, because if 7049 * the item is referenced elsewhere the funccal must not be freed. */ 7050 for (fc = previous_funccal; fc != NULL; fc = fc->caller) 7051 { 7052 abort = abort || set_ref_in_ht(&fc->l_vars.dv_hashtab, copyID + 1, 7053 NULL); 7054 abort = abort || set_ref_in_ht(&fc->l_avars.dv_hashtab, copyID + 1, 7055 NULL); 7056 } 7057 7058 /* script-local variables */ 7059 for (i = 1; i <= ga_scripts.ga_len; ++i) 7060 abort = abort || set_ref_in_ht(&SCRIPT_VARS(i), copyID, NULL); 7061 7062 /* buffer-local variables */ 7063 for (buf = firstbuf; buf != NULL; buf = buf->b_next) 7064 abort = abort || set_ref_in_item(&buf->b_bufvar.di_tv, copyID, 7065 NULL, NULL); 7066 7067 /* window-local variables */ 7068 FOR_ALL_TAB_WINDOWS(tp, wp) 7069 abort = abort || set_ref_in_item(&wp->w_winvar.di_tv, copyID, 7070 NULL, NULL); 7071 #ifdef FEAT_AUTOCMD 7072 if (aucmd_win != NULL) 7073 abort = abort || set_ref_in_item(&aucmd_win->w_winvar.di_tv, copyID, 7074 NULL, NULL); 7075 #endif 7076 7077 #ifdef FEAT_WINDOWS 7078 /* tabpage-local variables */ 7079 for (tp = first_tabpage; tp != NULL; tp = tp->tp_next) 7080 abort = abort || set_ref_in_item(&tp->tp_winvar.di_tv, copyID, 7081 NULL, NULL); 7082 #endif 7083 7084 /* global variables */ 7085 abort = abort || set_ref_in_ht(&globvarht, copyID, NULL); 7086 7087 /* function-local variables */ 7088 for (fc = current_funccal; fc != NULL; fc = fc->caller) 7089 { 7090 abort = abort || set_ref_in_ht(&fc->l_vars.dv_hashtab, copyID, NULL); 7091 abort = abort || set_ref_in_ht(&fc->l_avars.dv_hashtab, copyID, NULL); 7092 } 7093 7094 /* function call arguments, if v:testing is set. */ 7095 for (i = 0; i < funcargs.ga_len; ++i) 7096 abort = abort || set_ref_in_item(((typval_T **)funcargs.ga_data)[i], 7097 copyID, NULL, NULL); 7098 7099 /* v: vars */ 7100 abort = abort || set_ref_in_ht(&vimvarht, copyID, NULL); 7101 7102 #ifdef FEAT_LUA 7103 abort = abort || set_ref_in_lua(copyID); 7104 #endif 7105 7106 #ifdef FEAT_PYTHON 7107 abort = abort || set_ref_in_python(copyID); 7108 #endif 7109 7110 #ifdef FEAT_PYTHON3 7111 abort = abort || set_ref_in_python3(copyID); 7112 #endif 7113 7114 #ifdef FEAT_JOB_CHANNEL 7115 abort = abort || set_ref_in_channel(copyID); 7116 abort = abort || set_ref_in_job(copyID); 7117 #endif 7118 #ifdef FEAT_NETBEANS_INTG 7119 abort = abort || set_ref_in_nb_channel(copyID); 7120 #endif 7121 7122 #ifdef FEAT_TIMERS 7123 abort = abort || set_ref_in_timer(copyID); 7124 #endif 7125 7126 if (!abort) 7127 { 7128 /* 7129 * 2. Free lists and dictionaries that are not referenced. 7130 */ 7131 did_free = free_unref_items(copyID); 7132 7133 /* 7134 * 3. Check if any funccal can be freed now. 7135 */ 7136 for (pfc = &previous_funccal; *pfc != NULL; ) 7137 { 7138 if (can_free_funccal(*pfc, copyID)) 7139 { 7140 fc = *pfc; 7141 *pfc = fc->caller; 7142 free_funccal(fc, TRUE); 7143 did_free = TRUE; 7144 did_free_funccal = TRUE; 7145 } 7146 else 7147 pfc = &(*pfc)->caller; 7148 } 7149 if (did_free_funccal) 7150 /* When a funccal was freed some more items might be garbage 7151 * collected, so run again. */ 7152 (void)garbage_collect(testing); 7153 } 7154 else if (p_verbose > 0) 7155 { 7156 verb_msg((char_u *)_("Not enough memory to set references, garbage collection aborted!")); 7157 } 7158 7159 return did_free; 7160 } 7161 7162 /* 7163 * Free lists, dictionaries, channels and jobs that are no longer referenced. 7164 */ 7165 static int 7166 free_unref_items(int copyID) 7167 { 7168 dict_T *dd, *dd_next; 7169 list_T *ll, *ll_next; 7170 int did_free = FALSE; 7171 7172 /* Let all "free" functions know that we are here. This means no 7173 * dictionaries, lists, channels or jobs are to be freed, because we will 7174 * do that here. */ 7175 in_free_unref_items = TRUE; 7176 7177 /* 7178 * PASS 1: free the contents of the items. We don't free the items 7179 * themselves yet, so that it is possible to decrement refcount counters 7180 */ 7181 7182 /* 7183 * Go through the list of dicts and free items without the copyID. 7184 */ 7185 for (dd = first_dict; dd != NULL; dd = dd->dv_used_next) 7186 if ((dd->dv_copyID & COPYID_MASK) != (copyID & COPYID_MASK)) 7187 { 7188 /* Free the Dictionary and ordinary items it contains, but don't 7189 * recurse into Lists and Dictionaries, they will be in the list 7190 * of dicts or list of lists. */ 7191 dict_free_contents(dd); 7192 did_free = TRUE; 7193 } 7194 7195 /* 7196 * Go through the list of lists and free items without the copyID. 7197 * But don't free a list that has a watcher (used in a for loop), these 7198 * are not referenced anywhere. 7199 */ 7200 for (ll = first_list; ll != NULL; ll = ll->lv_used_next) 7201 if ((ll->lv_copyID & COPYID_MASK) != (copyID & COPYID_MASK) 7202 && ll->lv_watch == NULL) 7203 { 7204 /* Free the List and ordinary items it contains, but don't recurse 7205 * into Lists and Dictionaries, they will be in the list of dicts 7206 * or list of lists. */ 7207 list_free_contents(ll); 7208 did_free = TRUE; 7209 } 7210 7211 #ifdef FEAT_JOB_CHANNEL 7212 /* Go through the list of jobs and free items without the copyID. This 7213 * must happen before doing channels, because jobs refer to channels, but 7214 * the reference from the channel to the job isn't tracked. */ 7215 did_free |= free_unused_jobs_contents(copyID, COPYID_MASK); 7216 7217 /* Go through the list of channels and free items without the copyID. */ 7218 did_free |= free_unused_channels_contents(copyID, COPYID_MASK); 7219 #endif 7220 7221 /* 7222 * PASS 2: free the items themselves. 7223 */ 7224 for (dd = first_dict; dd != NULL; dd = dd_next) 7225 { 7226 dd_next = dd->dv_used_next; 7227 if ((dd->dv_copyID & COPYID_MASK) != (copyID & COPYID_MASK)) 7228 dict_free_dict(dd); 7229 } 7230 7231 for (ll = first_list; ll != NULL; ll = ll_next) 7232 { 7233 ll_next = ll->lv_used_next; 7234 if ((ll->lv_copyID & COPYID_MASK) != (copyID & COPYID_MASK) 7235 && ll->lv_watch == NULL) 7236 { 7237 /* Free the List and ordinary items it contains, but don't recurse 7238 * into Lists and Dictionaries, they will be in the list of dicts 7239 * or list of lists. */ 7240 list_free_list(ll); 7241 } 7242 } 7243 7244 #ifdef FEAT_JOB_CHANNEL 7245 /* Go through the list of jobs and free items without the copyID. This 7246 * must happen before doing channels, because jobs refer to channels, but 7247 * the reference from the channel to the job isn't tracked. */ 7248 free_unused_jobs(copyID, COPYID_MASK); 7249 7250 /* Go through the list of channels and free items without the copyID. */ 7251 free_unused_channels(copyID, COPYID_MASK); 7252 #endif 7253 7254 in_free_unref_items = FALSE; 7255 7256 return did_free; 7257 } 7258 7259 /* 7260 * Mark all lists and dicts referenced through hashtab "ht" with "copyID". 7261 * "list_stack" is used to add lists to be marked. Can be NULL. 7262 * 7263 * Returns TRUE if setting references failed somehow. 7264 */ 7265 int 7266 set_ref_in_ht(hashtab_T *ht, int copyID, list_stack_T **list_stack) 7267 { 7268 int todo; 7269 int abort = FALSE; 7270 hashitem_T *hi; 7271 hashtab_T *cur_ht; 7272 ht_stack_T *ht_stack = NULL; 7273 ht_stack_T *tempitem; 7274 7275 cur_ht = ht; 7276 for (;;) 7277 { 7278 if (!abort) 7279 { 7280 /* Mark each item in the hashtab. If the item contains a hashtab 7281 * it is added to ht_stack, if it contains a list it is added to 7282 * list_stack. */ 7283 todo = (int)cur_ht->ht_used; 7284 for (hi = cur_ht->ht_array; todo > 0; ++hi) 7285 if (!HASHITEM_EMPTY(hi)) 7286 { 7287 --todo; 7288 abort = abort || set_ref_in_item(&HI2DI(hi)->di_tv, copyID, 7289 &ht_stack, list_stack); 7290 } 7291 } 7292 7293 if (ht_stack == NULL) 7294 break; 7295 7296 /* take an item from the stack */ 7297 cur_ht = ht_stack->ht; 7298 tempitem = ht_stack; 7299 ht_stack = ht_stack->prev; 7300 free(tempitem); 7301 } 7302 7303 return abort; 7304 } 7305 7306 /* 7307 * Mark all lists and dicts referenced through list "l" with "copyID". 7308 * "ht_stack" is used to add hashtabs to be marked. Can be NULL. 7309 * 7310 * Returns TRUE if setting references failed somehow. 7311 */ 7312 int 7313 set_ref_in_list(list_T *l, int copyID, ht_stack_T **ht_stack) 7314 { 7315 listitem_T *li; 7316 int abort = FALSE; 7317 list_T *cur_l; 7318 list_stack_T *list_stack = NULL; 7319 list_stack_T *tempitem; 7320 7321 cur_l = l; 7322 for (;;) 7323 { 7324 if (!abort) 7325 /* Mark each item in the list. If the item contains a hashtab 7326 * it is added to ht_stack, if it contains a list it is added to 7327 * list_stack. */ 7328 for (li = cur_l->lv_first; !abort && li != NULL; li = li->li_next) 7329 abort = abort || set_ref_in_item(&li->li_tv, copyID, 7330 ht_stack, &list_stack); 7331 if (list_stack == NULL) 7332 break; 7333 7334 /* take an item from the stack */ 7335 cur_l = list_stack->list; 7336 tempitem = list_stack; 7337 list_stack = list_stack->prev; 7338 free(tempitem); 7339 } 7340 7341 return abort; 7342 } 7343 7344 /* 7345 * Mark all lists and dicts referenced through typval "tv" with "copyID". 7346 * "list_stack" is used to add lists to be marked. Can be NULL. 7347 * "ht_stack" is used to add hashtabs to be marked. Can be NULL. 7348 * 7349 * Returns TRUE if setting references failed somehow. 7350 */ 7351 int 7352 set_ref_in_item( 7353 typval_T *tv, 7354 int copyID, 7355 ht_stack_T **ht_stack, 7356 list_stack_T **list_stack) 7357 { 7358 int abort = FALSE; 7359 7360 if (tv->v_type == VAR_DICT) 7361 { 7362 dict_T *dd = tv->vval.v_dict; 7363 7364 if (dd != NULL && dd->dv_copyID != copyID) 7365 { 7366 /* Didn't see this dict yet. */ 7367 dd->dv_copyID = copyID; 7368 if (ht_stack == NULL) 7369 { 7370 abort = set_ref_in_ht(&dd->dv_hashtab, copyID, list_stack); 7371 } 7372 else 7373 { 7374 ht_stack_T *newitem = (ht_stack_T*)malloc(sizeof(ht_stack_T)); 7375 if (newitem == NULL) 7376 abort = TRUE; 7377 else 7378 { 7379 newitem->ht = &dd->dv_hashtab; 7380 newitem->prev = *ht_stack; 7381 *ht_stack = newitem; 7382 } 7383 } 7384 } 7385 } 7386 else if (tv->v_type == VAR_LIST) 7387 { 7388 list_T *ll = tv->vval.v_list; 7389 7390 if (ll != NULL && ll->lv_copyID != copyID) 7391 { 7392 /* Didn't see this list yet. */ 7393 ll->lv_copyID = copyID; 7394 if (list_stack == NULL) 7395 { 7396 abort = set_ref_in_list(ll, copyID, ht_stack); 7397 } 7398 else 7399 { 7400 list_stack_T *newitem = (list_stack_T*)malloc( 7401 sizeof(list_stack_T)); 7402 if (newitem == NULL) 7403 abort = TRUE; 7404 else 7405 { 7406 newitem->list = ll; 7407 newitem->prev = *list_stack; 7408 *list_stack = newitem; 7409 } 7410 } 7411 } 7412 } 7413 else if (tv->v_type == VAR_PARTIAL) 7414 { 7415 partial_T *pt = tv->vval.v_partial; 7416 int i; 7417 7418 /* A partial does not have a copyID, because it cannot contain itself. 7419 */ 7420 if (pt != NULL) 7421 { 7422 if (pt->pt_dict != NULL) 7423 { 7424 typval_T dtv; 7425 7426 dtv.v_type = VAR_DICT; 7427 dtv.vval.v_dict = pt->pt_dict; 7428 set_ref_in_item(&dtv, copyID, ht_stack, list_stack); 7429 } 7430 7431 for (i = 0; i < pt->pt_argc; ++i) 7432 abort = abort || set_ref_in_item(&pt->pt_argv[i], copyID, 7433 ht_stack, list_stack); 7434 } 7435 } 7436 #ifdef FEAT_JOB_CHANNEL 7437 else if (tv->v_type == VAR_JOB) 7438 { 7439 job_T *job = tv->vval.v_job; 7440 typval_T dtv; 7441 7442 if (job != NULL && job->jv_copyID != copyID) 7443 { 7444 job->jv_copyID = copyID; 7445 if (job->jv_channel != NULL) 7446 { 7447 dtv.v_type = VAR_CHANNEL; 7448 dtv.vval.v_channel = job->jv_channel; 7449 set_ref_in_item(&dtv, copyID, ht_stack, list_stack); 7450 } 7451 if (job->jv_exit_partial != NULL) 7452 { 7453 dtv.v_type = VAR_PARTIAL; 7454 dtv.vval.v_partial = job->jv_exit_partial; 7455 set_ref_in_item(&dtv, copyID, ht_stack, list_stack); 7456 } 7457 } 7458 } 7459 else if (tv->v_type == VAR_CHANNEL) 7460 { 7461 channel_T *ch =tv->vval.v_channel; 7462 int part; 7463 typval_T dtv; 7464 jsonq_T *jq; 7465 cbq_T *cq; 7466 7467 if (ch != NULL && ch->ch_copyID != copyID) 7468 { 7469 ch->ch_copyID = copyID; 7470 for (part = PART_SOCK; part <= PART_IN; ++part) 7471 { 7472 for (jq = ch->ch_part[part].ch_json_head.jq_next; jq != NULL; 7473 jq = jq->jq_next) 7474 set_ref_in_item(jq->jq_value, copyID, ht_stack, list_stack); 7475 for (cq = ch->ch_part[part].ch_cb_head.cq_next; cq != NULL; 7476 cq = cq->cq_next) 7477 if (cq->cq_partial != NULL) 7478 { 7479 dtv.v_type = VAR_PARTIAL; 7480 dtv.vval.v_partial = cq->cq_partial; 7481 set_ref_in_item(&dtv, copyID, ht_stack, list_stack); 7482 } 7483 if (ch->ch_part[part].ch_partial != NULL) 7484 { 7485 dtv.v_type = VAR_PARTIAL; 7486 dtv.vval.v_partial = ch->ch_part[part].ch_partial; 7487 set_ref_in_item(&dtv, copyID, ht_stack, list_stack); 7488 } 7489 } 7490 if (ch->ch_partial != NULL) 7491 { 7492 dtv.v_type = VAR_PARTIAL; 7493 dtv.vval.v_partial = ch->ch_partial; 7494 set_ref_in_item(&dtv, copyID, ht_stack, list_stack); 7495 } 7496 if (ch->ch_close_partial != NULL) 7497 { 7498 dtv.v_type = VAR_PARTIAL; 7499 dtv.vval.v_partial = ch->ch_close_partial; 7500 set_ref_in_item(&dtv, copyID, ht_stack, list_stack); 7501 } 7502 } 7503 } 7504 #endif 7505 return abort; 7506 } 7507 7508 /* 7509 * Allocate an empty header for a dictionary. 7510 */ 7511 dict_T * 7512 dict_alloc(void) 7513 { 7514 dict_T *d; 7515 7516 d = (dict_T *)alloc(sizeof(dict_T)); 7517 if (d != NULL) 7518 { 7519 /* Add the dict to the list of dicts for garbage collection. */ 7520 if (first_dict != NULL) 7521 first_dict->dv_used_prev = d; 7522 d->dv_used_next = first_dict; 7523 d->dv_used_prev = NULL; 7524 first_dict = d; 7525 7526 hash_init(&d->dv_hashtab); 7527 d->dv_lock = 0; 7528 d->dv_scope = 0; 7529 d->dv_refcount = 0; 7530 d->dv_copyID = 0; 7531 } 7532 return d; 7533 } 7534 7535 /* 7536 * Allocate an empty dict for a return value. 7537 * Returns OK or FAIL. 7538 */ 7539 int 7540 rettv_dict_alloc(typval_T *rettv) 7541 { 7542 dict_T *d = dict_alloc(); 7543 7544 if (d == NULL) 7545 return FAIL; 7546 7547 rettv->vval.v_dict = d; 7548 rettv->v_type = VAR_DICT; 7549 rettv->v_lock = 0; 7550 ++d->dv_refcount; 7551 return OK; 7552 } 7553 7554 7555 /* 7556 * Unreference a Dictionary: decrement the reference count and free it when it 7557 * becomes zero. 7558 */ 7559 void 7560 dict_unref(dict_T *d) 7561 { 7562 if (d != NULL && --d->dv_refcount <= 0) 7563 dict_free(d); 7564 } 7565 7566 /* 7567 * Free a Dictionary, including all non-container items it contains. 7568 * Ignores the reference count. 7569 */ 7570 static void 7571 dict_free_contents(dict_T *d) 7572 { 7573 int todo; 7574 hashitem_T *hi; 7575 dictitem_T *di; 7576 7577 /* Lock the hashtab, we don't want it to resize while freeing items. */ 7578 hash_lock(&d->dv_hashtab); 7579 todo = (int)d->dv_hashtab.ht_used; 7580 for (hi = d->dv_hashtab.ht_array; todo > 0; ++hi) 7581 { 7582 if (!HASHITEM_EMPTY(hi)) 7583 { 7584 /* Remove the item before deleting it, just in case there is 7585 * something recursive causing trouble. */ 7586 di = HI2DI(hi); 7587 hash_remove(&d->dv_hashtab, hi); 7588 clear_tv(&di->di_tv); 7589 vim_free(di); 7590 --todo; 7591 } 7592 } 7593 hash_clear(&d->dv_hashtab); 7594 } 7595 7596 static void 7597 dict_free_dict(dict_T *d) 7598 { 7599 /* Remove the dict from the list of dicts for garbage collection. */ 7600 if (d->dv_used_prev == NULL) 7601 first_dict = d->dv_used_next; 7602 else 7603 d->dv_used_prev->dv_used_next = d->dv_used_next; 7604 if (d->dv_used_next != NULL) 7605 d->dv_used_next->dv_used_prev = d->dv_used_prev; 7606 vim_free(d); 7607 } 7608 7609 void 7610 dict_free(dict_T *d) 7611 { 7612 if (!in_free_unref_items) 7613 { 7614 dict_free_contents(d); 7615 dict_free_dict(d); 7616 } 7617 } 7618 7619 /* 7620 * Allocate a Dictionary item. 7621 * The "key" is copied to the new item. 7622 * Note that the value of the item "di_tv" still needs to be initialized! 7623 * Returns NULL when out of memory. 7624 */ 7625 dictitem_T * 7626 dictitem_alloc(char_u *key) 7627 { 7628 dictitem_T *di; 7629 7630 di = (dictitem_T *)alloc((unsigned)(sizeof(dictitem_T) + STRLEN(key))); 7631 if (di != NULL) 7632 { 7633 STRCPY(di->di_key, key); 7634 di->di_flags = DI_FLAGS_ALLOC; 7635 } 7636 return di; 7637 } 7638 7639 /* 7640 * Make a copy of a Dictionary item. 7641 */ 7642 static dictitem_T * 7643 dictitem_copy(dictitem_T *org) 7644 { 7645 dictitem_T *di; 7646 7647 di = (dictitem_T *)alloc((unsigned)(sizeof(dictitem_T) 7648 + STRLEN(org->di_key))); 7649 if (di != NULL) 7650 { 7651 STRCPY(di->di_key, org->di_key); 7652 di->di_flags = DI_FLAGS_ALLOC; 7653 copy_tv(&org->di_tv, &di->di_tv); 7654 } 7655 return di; 7656 } 7657 7658 /* 7659 * Remove item "item" from Dictionary "dict" and free it. 7660 */ 7661 static void 7662 dictitem_remove(dict_T *dict, dictitem_T *item) 7663 { 7664 hashitem_T *hi; 7665 7666 hi = hash_find(&dict->dv_hashtab, item->di_key); 7667 if (HASHITEM_EMPTY(hi)) 7668 EMSG2(_(e_intern2), "dictitem_remove()"); 7669 else 7670 hash_remove(&dict->dv_hashtab, hi); 7671 dictitem_free(item); 7672 } 7673 7674 /* 7675 * Free a dict item. Also clears the value. 7676 */ 7677 void 7678 dictitem_free(dictitem_T *item) 7679 { 7680 clear_tv(&item->di_tv); 7681 if (item->di_flags & DI_FLAGS_ALLOC) 7682 vim_free(item); 7683 } 7684 7685 /* 7686 * Make a copy of dict "d". Shallow if "deep" is FALSE. 7687 * The refcount of the new dict is set to 1. 7688 * See item_copy() for "copyID". 7689 * Returns NULL when out of memory. 7690 */ 7691 static dict_T * 7692 dict_copy(dict_T *orig, int deep, int copyID) 7693 { 7694 dict_T *copy; 7695 dictitem_T *di; 7696 int todo; 7697 hashitem_T *hi; 7698 7699 if (orig == NULL) 7700 return NULL; 7701 7702 copy = dict_alloc(); 7703 if (copy != NULL) 7704 { 7705 if (copyID != 0) 7706 { 7707 orig->dv_copyID = copyID; 7708 orig->dv_copydict = copy; 7709 } 7710 todo = (int)orig->dv_hashtab.ht_used; 7711 for (hi = orig->dv_hashtab.ht_array; todo > 0 && !got_int; ++hi) 7712 { 7713 if (!HASHITEM_EMPTY(hi)) 7714 { 7715 --todo; 7716 7717 di = dictitem_alloc(hi->hi_key); 7718 if (di == NULL) 7719 break; 7720 if (deep) 7721 { 7722 if (item_copy(&HI2DI(hi)->di_tv, &di->di_tv, deep, 7723 copyID) == FAIL) 7724 { 7725 vim_free(di); 7726 break; 7727 } 7728 } 7729 else 7730 copy_tv(&HI2DI(hi)->di_tv, &di->di_tv); 7731 if (dict_add(copy, di) == FAIL) 7732 { 7733 dictitem_free(di); 7734 break; 7735 } 7736 } 7737 } 7738 7739 ++copy->dv_refcount; 7740 if (todo > 0) 7741 { 7742 dict_unref(copy); 7743 copy = NULL; 7744 } 7745 } 7746 7747 return copy; 7748 } 7749 7750 /* 7751 * Add item "item" to Dictionary "d". 7752 * Returns FAIL when out of memory and when key already exists. 7753 */ 7754 int 7755 dict_add(dict_T *d, dictitem_T *item) 7756 { 7757 return hash_add(&d->dv_hashtab, item->di_key); 7758 } 7759 7760 /* 7761 * Add a number or string entry to dictionary "d". 7762 * When "str" is NULL use number "nr", otherwise use "str". 7763 * Returns FAIL when out of memory and when key already exists. 7764 */ 7765 int 7766 dict_add_nr_str( 7767 dict_T *d, 7768 char *key, 7769 long nr, 7770 char_u *str) 7771 { 7772 dictitem_T *item; 7773 7774 item = dictitem_alloc((char_u *)key); 7775 if (item == NULL) 7776 return FAIL; 7777 item->di_tv.v_lock = 0; 7778 if (str == NULL) 7779 { 7780 item->di_tv.v_type = VAR_NUMBER; 7781 item->di_tv.vval.v_number = nr; 7782 } 7783 else 7784 { 7785 item->di_tv.v_type = VAR_STRING; 7786 item->di_tv.vval.v_string = vim_strsave(str); 7787 } 7788 if (dict_add(d, item) == FAIL) 7789 { 7790 dictitem_free(item); 7791 return FAIL; 7792 } 7793 return OK; 7794 } 7795 7796 /* 7797 * Add a list entry to dictionary "d". 7798 * Returns FAIL when out of memory and when key already exists. 7799 */ 7800 int 7801 dict_add_list(dict_T *d, char *key, list_T *list) 7802 { 7803 dictitem_T *item; 7804 7805 item = dictitem_alloc((char_u *)key); 7806 if (item == NULL) 7807 return FAIL; 7808 item->di_tv.v_lock = 0; 7809 item->di_tv.v_type = VAR_LIST; 7810 item->di_tv.vval.v_list = list; 7811 if (dict_add(d, item) == FAIL) 7812 { 7813 dictitem_free(item); 7814 return FAIL; 7815 } 7816 ++list->lv_refcount; 7817 return OK; 7818 } 7819 7820 /* 7821 * Get the number of items in a Dictionary. 7822 */ 7823 static long 7824 dict_len(dict_T *d) 7825 { 7826 if (d == NULL) 7827 return 0L; 7828 return (long)d->dv_hashtab.ht_used; 7829 } 7830 7831 /* 7832 * Find item "key[len]" in Dictionary "d". 7833 * If "len" is negative use strlen(key). 7834 * Returns NULL when not found. 7835 */ 7836 dictitem_T * 7837 dict_find(dict_T *d, char_u *key, int len) 7838 { 7839 #define AKEYLEN 200 7840 char_u buf[AKEYLEN]; 7841 char_u *akey; 7842 char_u *tofree = NULL; 7843 hashitem_T *hi; 7844 7845 if (d == NULL) 7846 return NULL; 7847 if (len < 0) 7848 akey = key; 7849 else if (len >= AKEYLEN) 7850 { 7851 tofree = akey = vim_strnsave(key, len); 7852 if (akey == NULL) 7853 return NULL; 7854 } 7855 else 7856 { 7857 /* Avoid a malloc/free by using buf[]. */ 7858 vim_strncpy(buf, key, len); 7859 akey = buf; 7860 } 7861 7862 hi = hash_find(&d->dv_hashtab, akey); 7863 vim_free(tofree); 7864 if (HASHITEM_EMPTY(hi)) 7865 return NULL; 7866 return HI2DI(hi); 7867 } 7868 7869 /* 7870 * Get a string item from a dictionary. 7871 * When "save" is TRUE allocate memory for it. 7872 * Returns NULL if the entry doesn't exist or out of memory. 7873 */ 7874 char_u * 7875 get_dict_string(dict_T *d, char_u *key, int save) 7876 { 7877 dictitem_T *di; 7878 char_u *s; 7879 7880 di = dict_find(d, key, -1); 7881 if (di == NULL) 7882 return NULL; 7883 s = get_tv_string(&di->di_tv); 7884 if (save && s != NULL) 7885 s = vim_strsave(s); 7886 return s; 7887 } 7888 7889 /* 7890 * Get a number item from a dictionary. 7891 * Returns 0 if the entry doesn't exist. 7892 */ 7893 long 7894 get_dict_number(dict_T *d, char_u *key) 7895 { 7896 dictitem_T *di; 7897 7898 di = dict_find(d, key, -1); 7899 if (di == NULL) 7900 return 0; 7901 return get_tv_number(&di->di_tv); 7902 } 7903 7904 /* 7905 * Return an allocated string with the string representation of a Dictionary. 7906 * May return NULL. 7907 */ 7908 static char_u * 7909 dict2string(typval_T *tv, int copyID, int restore_copyID) 7910 { 7911 garray_T ga; 7912 int first = TRUE; 7913 char_u *tofree; 7914 char_u numbuf[NUMBUFLEN]; 7915 hashitem_T *hi; 7916 char_u *s; 7917 dict_T *d; 7918 int todo; 7919 7920 if ((d = tv->vval.v_dict) == NULL) 7921 return NULL; 7922 ga_init2(&ga, (int)sizeof(char), 80); 7923 ga_append(&ga, '{'); 7924 7925 todo = (int)d->dv_hashtab.ht_used; 7926 for (hi = d->dv_hashtab.ht_array; todo > 0 && !got_int; ++hi) 7927 { 7928 if (!HASHITEM_EMPTY(hi)) 7929 { 7930 --todo; 7931 7932 if (first) 7933 first = FALSE; 7934 else 7935 ga_concat(&ga, (char_u *)", "); 7936 7937 tofree = string_quote(hi->hi_key, FALSE); 7938 if (tofree != NULL) 7939 { 7940 ga_concat(&ga, tofree); 7941 vim_free(tofree); 7942 } 7943 ga_concat(&ga, (char_u *)": "); 7944 s = echo_string_core(&HI2DI(hi)->di_tv, &tofree, numbuf, copyID, 7945 FALSE, restore_copyID, TRUE); 7946 if (s != NULL) 7947 ga_concat(&ga, s); 7948 vim_free(tofree); 7949 if (s == NULL || did_echo_string_emsg) 7950 break; 7951 line_breakcheck(); 7952 7953 } 7954 } 7955 if (todo > 0) 7956 { 7957 vim_free(ga.ga_data); 7958 return NULL; 7959 } 7960 7961 ga_append(&ga, '}'); 7962 ga_append(&ga, NUL); 7963 return (char_u *)ga.ga_data; 7964 } 7965 7966 /* 7967 * Allocate a variable for a Dictionary and fill it from "*arg". 7968 * Return OK or FAIL. Returns NOTDONE for {expr}. 7969 */ 7970 static int 7971 get_dict_tv(char_u **arg, typval_T *rettv, int evaluate) 7972 { 7973 dict_T *d = NULL; 7974 typval_T tvkey; 7975 typval_T tv; 7976 char_u *key = NULL; 7977 dictitem_T *item; 7978 char_u *start = skipwhite(*arg + 1); 7979 char_u buf[NUMBUFLEN]; 7980 7981 /* 7982 * First check if it's not a curly-braces thing: {expr}. 7983 * Must do this without evaluating, otherwise a function may be called 7984 * twice. Unfortunately this means we need to call eval1() twice for the 7985 * first item. 7986 * But {} is an empty Dictionary. 7987 */ 7988 if (*start != '}') 7989 { 7990 if (eval1(&start, &tv, FALSE) == FAIL) /* recursive! */ 7991 return FAIL; 7992 if (*start == '}') 7993 return NOTDONE; 7994 } 7995 7996 if (evaluate) 7997 { 7998 d = dict_alloc(); 7999 if (d == NULL) 8000 return FAIL; 8001 } 8002 tvkey.v_type = VAR_UNKNOWN; 8003 tv.v_type = VAR_UNKNOWN; 8004 8005 *arg = skipwhite(*arg + 1); 8006 while (**arg != '}' && **arg != NUL) 8007 { 8008 if (eval1(arg, &tvkey, evaluate) == FAIL) /* recursive! */ 8009 goto failret; 8010 if (**arg != ':') 8011 { 8012 EMSG2(_("E720: Missing colon in Dictionary: %s"), *arg); 8013 clear_tv(&tvkey); 8014 goto failret; 8015 } 8016 if (evaluate) 8017 { 8018 key = get_tv_string_buf_chk(&tvkey, buf); 8019 if (key == NULL) 8020 { 8021 /* "key" is NULL when get_tv_string_buf_chk() gave an errmsg */ 8022 clear_tv(&tvkey); 8023 goto failret; 8024 } 8025 } 8026 8027 *arg = skipwhite(*arg + 1); 8028 if (eval1(arg, &tv, evaluate) == FAIL) /* recursive! */ 8029 { 8030 if (evaluate) 8031 clear_tv(&tvkey); 8032 goto failret; 8033 } 8034 if (evaluate) 8035 { 8036 item = dict_find(d, key, -1); 8037 if (item != NULL) 8038 { 8039 EMSG2(_("E721: Duplicate key in Dictionary: \"%s\""), key); 8040 clear_tv(&tvkey); 8041 clear_tv(&tv); 8042 goto failret; 8043 } 8044 item = dictitem_alloc(key); 8045 clear_tv(&tvkey); 8046 if (item != NULL) 8047 { 8048 item->di_tv = tv; 8049 item->di_tv.v_lock = 0; 8050 if (dict_add(d, item) == FAIL) 8051 dictitem_free(item); 8052 } 8053 } 8054 8055 if (**arg == '}') 8056 break; 8057 if (**arg != ',') 8058 { 8059 EMSG2(_("E722: Missing comma in Dictionary: %s"), *arg); 8060 goto failret; 8061 } 8062 *arg = skipwhite(*arg + 1); 8063 } 8064 8065 if (**arg != '}') 8066 { 8067 EMSG2(_("E723: Missing end of Dictionary '}': %s"), *arg); 8068 failret: 8069 if (evaluate) 8070 dict_free(d); 8071 return FAIL; 8072 } 8073 8074 *arg = skipwhite(*arg + 1); 8075 if (evaluate) 8076 { 8077 rettv->v_type = VAR_DICT; 8078 rettv->vval.v_dict = d; 8079 ++d->dv_refcount; 8080 } 8081 8082 return OK; 8083 } 8084 8085 static char * 8086 get_var_special_name(int nr) 8087 { 8088 switch (nr) 8089 { 8090 case VVAL_FALSE: return "v:false"; 8091 case VVAL_TRUE: return "v:true"; 8092 case VVAL_NONE: return "v:none"; 8093 case VVAL_NULL: return "v:null"; 8094 } 8095 EMSG2(_(e_intern2), "get_var_special_name()"); 8096 return "42"; 8097 } 8098 8099 /* 8100 * Return a string with the string representation of a variable. 8101 * If the memory is allocated "tofree" is set to it, otherwise NULL. 8102 * "numbuf" is used for a number. 8103 * When "copyID" is not NULL replace recursive lists and dicts with "...". 8104 * When both "echo_style" and "dict_val" are FALSE, put quotes around stings as 8105 * "string()", otherwise does not put quotes around strings, as ":echo" 8106 * displays values. 8107 * When "restore_copyID" is FALSE, repeated items in dictionaries and lists 8108 * are replaced with "...". 8109 * May return NULL. 8110 */ 8111 static char_u * 8112 echo_string_core( 8113 typval_T *tv, 8114 char_u **tofree, 8115 char_u *numbuf, 8116 int copyID, 8117 int echo_style, 8118 int restore_copyID, 8119 int dict_val) 8120 { 8121 static int recurse = 0; 8122 char_u *r = NULL; 8123 8124 if (recurse >= DICT_MAXNEST) 8125 { 8126 if (!did_echo_string_emsg) 8127 { 8128 /* Only give this message once for a recursive call to avoid 8129 * flooding the user with errors. And stop iterating over lists 8130 * and dicts. */ 8131 did_echo_string_emsg = TRUE; 8132 EMSG(_("E724: variable nested too deep for displaying")); 8133 } 8134 *tofree = NULL; 8135 return (char_u *)"{E724}"; 8136 } 8137 ++recurse; 8138 8139 switch (tv->v_type) 8140 { 8141 case VAR_STRING: 8142 if (echo_style && !dict_val) 8143 { 8144 *tofree = NULL; 8145 r = get_tv_string_buf(tv, numbuf); 8146 } 8147 else 8148 { 8149 *tofree = string_quote(tv->vval.v_string, FALSE); 8150 r = *tofree; 8151 } 8152 break; 8153 8154 case VAR_FUNC: 8155 if (echo_style) 8156 { 8157 *tofree = NULL; 8158 r = tv->vval.v_string; 8159 } 8160 else 8161 { 8162 *tofree = string_quote(tv->vval.v_string, TRUE); 8163 r = *tofree; 8164 } 8165 break; 8166 8167 case VAR_PARTIAL: 8168 { 8169 partial_T *pt = tv->vval.v_partial; 8170 char_u *fname = string_quote(pt == NULL ? NULL 8171 : pt->pt_name, FALSE); 8172 garray_T ga; 8173 int i; 8174 char_u *tf; 8175 8176 ga_init2(&ga, 1, 100); 8177 ga_concat(&ga, (char_u *)"function("); 8178 if (fname != NULL) 8179 { 8180 ga_concat(&ga, fname); 8181 vim_free(fname); 8182 } 8183 if (pt != NULL && pt->pt_argc > 0) 8184 { 8185 ga_concat(&ga, (char_u *)", ["); 8186 for (i = 0; i < pt->pt_argc; ++i) 8187 { 8188 if (i > 0) 8189 ga_concat(&ga, (char_u *)", "); 8190 ga_concat(&ga, 8191 tv2string(&pt->pt_argv[i], &tf, numbuf, copyID)); 8192 vim_free(tf); 8193 } 8194 ga_concat(&ga, (char_u *)"]"); 8195 } 8196 if (pt != NULL && pt->pt_dict != NULL) 8197 { 8198 typval_T dtv; 8199 8200 ga_concat(&ga, (char_u *)", "); 8201 dtv.v_type = VAR_DICT; 8202 dtv.vval.v_dict = pt->pt_dict; 8203 ga_concat(&ga, tv2string(&dtv, &tf, numbuf, copyID)); 8204 vim_free(tf); 8205 } 8206 ga_concat(&ga, (char_u *)")"); 8207 8208 *tofree = ga.ga_data; 8209 r = *tofree; 8210 break; 8211 } 8212 8213 case VAR_LIST: 8214 if (tv->vval.v_list == NULL) 8215 { 8216 *tofree = NULL; 8217 r = NULL; 8218 } 8219 else if (copyID != 0 && tv->vval.v_list->lv_copyID == copyID 8220 && tv->vval.v_list->lv_len > 0) 8221 { 8222 *tofree = NULL; 8223 r = (char_u *)"[...]"; 8224 } 8225 else 8226 { 8227 int old_copyID = tv->vval.v_list->lv_copyID; 8228 8229 tv->vval.v_list->lv_copyID = copyID; 8230 *tofree = list2string(tv, copyID, restore_copyID); 8231 if (restore_copyID) 8232 tv->vval.v_list->lv_copyID = old_copyID; 8233 r = *tofree; 8234 } 8235 break; 8236 8237 case VAR_DICT: 8238 if (tv->vval.v_dict == NULL) 8239 { 8240 *tofree = NULL; 8241 r = NULL; 8242 } 8243 else if (copyID != 0 && tv->vval.v_dict->dv_copyID == copyID 8244 && tv->vval.v_dict->dv_hashtab.ht_used != 0) 8245 { 8246 *tofree = NULL; 8247 r = (char_u *)"{...}"; 8248 } 8249 else 8250 { 8251 int old_copyID = tv->vval.v_dict->dv_copyID; 8252 tv->vval.v_dict->dv_copyID = copyID; 8253 *tofree = dict2string(tv, copyID, restore_copyID); 8254 if (restore_copyID) 8255 tv->vval.v_dict->dv_copyID = old_copyID; 8256 r = *tofree; 8257 } 8258 break; 8259 8260 case VAR_NUMBER: 8261 case VAR_UNKNOWN: 8262 case VAR_JOB: 8263 case VAR_CHANNEL: 8264 *tofree = NULL; 8265 r = get_tv_string_buf(tv, numbuf); 8266 break; 8267 8268 case VAR_FLOAT: 8269 #ifdef FEAT_FLOAT 8270 *tofree = NULL; 8271 vim_snprintf((char *)numbuf, NUMBUFLEN, "%g", tv->vval.v_float); 8272 r = numbuf; 8273 break; 8274 #endif 8275 8276 case VAR_SPECIAL: 8277 *tofree = NULL; 8278 r = (char_u *)get_var_special_name(tv->vval.v_number); 8279 break; 8280 } 8281 8282 if (--recurse == 0) 8283 did_echo_string_emsg = FALSE; 8284 return r; 8285 } 8286 8287 /* 8288 * Return a string with the string representation of a variable. 8289 * If the memory is allocated "tofree" is set to it, otherwise NULL. 8290 * "numbuf" is used for a number. 8291 * Does not put quotes around strings, as ":echo" displays values. 8292 * When "copyID" is not NULL replace recursive lists and dicts with "...". 8293 * May return NULL. 8294 */ 8295 static char_u * 8296 echo_string( 8297 typval_T *tv, 8298 char_u **tofree, 8299 char_u *numbuf, 8300 int copyID) 8301 { 8302 return echo_string_core(tv, tofree, numbuf, copyID, TRUE, FALSE, FALSE); 8303 } 8304 8305 /* 8306 * Return a string with the string representation of a variable. 8307 * If the memory is allocated "tofree" is set to it, otherwise NULL. 8308 * "numbuf" is used for a number. 8309 * Puts quotes around strings, so that they can be parsed back by eval(). 8310 * May return NULL. 8311 */ 8312 char_u * 8313 tv2string( 8314 typval_T *tv, 8315 char_u **tofree, 8316 char_u *numbuf, 8317 int copyID) 8318 { 8319 return echo_string_core(tv, tofree, numbuf, copyID, FALSE, TRUE, FALSE); 8320 } 8321 8322 /* 8323 * Return string "str" in ' quotes, doubling ' characters. 8324 * If "str" is NULL an empty string is assumed. 8325 * If "function" is TRUE make it function('string'). 8326 */ 8327 static char_u * 8328 string_quote(char_u *str, int function) 8329 { 8330 unsigned len; 8331 char_u *p, *r, *s; 8332 8333 len = (function ? 13 : 3); 8334 if (str != NULL) 8335 { 8336 len += (unsigned)STRLEN(str); 8337 for (p = str; *p != NUL; mb_ptr_adv(p)) 8338 if (*p == '\'') 8339 ++len; 8340 } 8341 s = r = alloc(len); 8342 if (r != NULL) 8343 { 8344 if (function) 8345 { 8346 STRCPY(r, "function('"); 8347 r += 10; 8348 } 8349 else 8350 *r++ = '\''; 8351 if (str != NULL) 8352 for (p = str; *p != NUL; ) 8353 { 8354 if (*p == '\'') 8355 *r++ = '\''; 8356 MB_COPY_CHAR(p, r); 8357 } 8358 *r++ = '\''; 8359 if (function) 8360 *r++ = ')'; 8361 *r++ = NUL; 8362 } 8363 return s; 8364 } 8365 8366 #if defined(FEAT_FLOAT) || defined(PROTO) 8367 /* 8368 * Convert the string "text" to a floating point number. 8369 * This uses strtod(). setlocale(LC_NUMERIC, "C") has been used to make sure 8370 * this always uses a decimal point. 8371 * Returns the length of the text that was consumed. 8372 */ 8373 int 8374 string2float( 8375 char_u *text, 8376 float_T *value) /* result stored here */ 8377 { 8378 char *s = (char *)text; 8379 float_T f; 8380 8381 f = strtod(s, &s); 8382 *value = f; 8383 return (int)((char_u *)s - text); 8384 } 8385 #endif 8386 8387 /* 8388 * Get the value of an environment variable. 8389 * "arg" is pointing to the '$'. It is advanced to after the name. 8390 * If the environment variable was not set, silently assume it is empty. 8391 * Return FAIL if the name is invalid. 8392 */ 8393 static int 8394 get_env_tv(char_u **arg, typval_T *rettv, int evaluate) 8395 { 8396 char_u *string = NULL; 8397 int len; 8398 int cc; 8399 char_u *name; 8400 int mustfree = FALSE; 8401 8402 ++*arg; 8403 name = *arg; 8404 len = get_env_len(arg); 8405 if (evaluate) 8406 { 8407 if (len == 0) 8408 return FAIL; /* invalid empty name */ 8409 8410 cc = name[len]; 8411 name[len] = NUL; 8412 /* first try vim_getenv(), fast for normal environment vars */ 8413 string = vim_getenv(name, &mustfree); 8414 if (string != NULL && *string != NUL) 8415 { 8416 if (!mustfree) 8417 string = vim_strsave(string); 8418 } 8419 else 8420 { 8421 if (mustfree) 8422 vim_free(string); 8423 8424 /* next try expanding things like $VIM and ${HOME} */ 8425 string = expand_env_save(name - 1); 8426 if (string != NULL && *string == '$') 8427 { 8428 vim_free(string); 8429 string = NULL; 8430 } 8431 } 8432 name[len] = cc; 8433 8434 rettv->v_type = VAR_STRING; 8435 rettv->vval.v_string = string; 8436 } 8437 8438 return OK; 8439 } 8440 8441 /* 8442 * Array with names and number of arguments of all internal functions 8443 * MUST BE KEPT SORTED IN strcmp() ORDER FOR BINARY SEARCH! 8444 */ 8445 static struct fst 8446 { 8447 char *f_name; /* function name */ 8448 char f_min_argc; /* minimal number of arguments */ 8449 char f_max_argc; /* maximal number of arguments */ 8450 void (*f_func)(typval_T *args, typval_T *rvar); 8451 /* implementation of function */ 8452 } functions[] = 8453 { 8454 #ifdef FEAT_FLOAT 8455 {"abs", 1, 1, f_abs}, 8456 {"acos", 1, 1, f_acos}, /* WJMc */ 8457 #endif 8458 {"add", 2, 2, f_add}, 8459 {"and", 2, 2, f_and}, 8460 {"append", 2, 2, f_append}, 8461 {"argc", 0, 0, f_argc}, 8462 {"argidx", 0, 0, f_argidx}, 8463 {"arglistid", 0, 2, f_arglistid}, 8464 {"argv", 0, 1, f_argv}, 8465 #ifdef FEAT_FLOAT 8466 {"asin", 1, 1, f_asin}, /* WJMc */ 8467 #endif 8468 {"assert_equal", 2, 3, f_assert_equal}, 8469 {"assert_exception", 1, 2, f_assert_exception}, 8470 {"assert_fails", 1, 2, f_assert_fails}, 8471 {"assert_false", 1, 2, f_assert_false}, 8472 {"assert_match", 2, 3, f_assert_match}, 8473 {"assert_notequal", 2, 3, f_assert_notequal}, 8474 {"assert_notmatch", 2, 3, f_assert_notmatch}, 8475 {"assert_true", 1, 2, f_assert_true}, 8476 #ifdef FEAT_FLOAT 8477 {"atan", 1, 1, f_atan}, 8478 {"atan2", 2, 2, f_atan2}, 8479 #endif 8480 {"browse", 4, 4, f_browse}, 8481 {"browsedir", 2, 2, f_browsedir}, 8482 {"bufexists", 1, 1, f_bufexists}, 8483 {"buffer_exists", 1, 1, f_bufexists}, /* obsolete */ 8484 {"buffer_name", 1, 1, f_bufname}, /* obsolete */ 8485 {"buffer_number", 1, 1, f_bufnr}, /* obsolete */ 8486 {"buflisted", 1, 1, f_buflisted}, 8487 {"bufloaded", 1, 1, f_bufloaded}, 8488 {"bufname", 1, 1, f_bufname}, 8489 {"bufnr", 1, 2, f_bufnr}, 8490 {"bufwinnr", 1, 1, f_bufwinnr}, 8491 {"byte2line", 1, 1, f_byte2line}, 8492 {"byteidx", 2, 2, f_byteidx}, 8493 {"byteidxcomp", 2, 2, f_byteidxcomp}, 8494 {"call", 2, 3, f_call}, 8495 #ifdef FEAT_FLOAT 8496 {"ceil", 1, 1, f_ceil}, 8497 #endif 8498 #ifdef FEAT_JOB_CHANNEL 8499 {"ch_close", 1, 1, f_ch_close}, 8500 {"ch_evalexpr", 2, 3, f_ch_evalexpr}, 8501 {"ch_evalraw", 2, 3, f_ch_evalraw}, 8502 {"ch_getbufnr", 2, 2, f_ch_getbufnr}, 8503 {"ch_getjob", 1, 1, f_ch_getjob}, 8504 {"ch_info", 1, 1, f_ch_info}, 8505 {"ch_log", 1, 2, f_ch_log}, 8506 {"ch_logfile", 1, 2, f_ch_logfile}, 8507 {"ch_open", 1, 2, f_ch_open}, 8508 {"ch_read", 1, 2, f_ch_read}, 8509 {"ch_readraw", 1, 2, f_ch_readraw}, 8510 {"ch_sendexpr", 2, 3, f_ch_sendexpr}, 8511 {"ch_sendraw", 2, 3, f_ch_sendraw}, 8512 {"ch_setoptions", 2, 2, f_ch_setoptions}, 8513 {"ch_status", 1, 1, f_ch_status}, 8514 #endif 8515 {"changenr", 0, 0, f_changenr}, 8516 {"char2nr", 1, 2, f_char2nr}, 8517 {"cindent", 1, 1, f_cindent}, 8518 {"clearmatches", 0, 0, f_clearmatches}, 8519 {"col", 1, 1, f_col}, 8520 #if defined(FEAT_INS_EXPAND) 8521 {"complete", 2, 2, f_complete}, 8522 {"complete_add", 1, 1, f_complete_add}, 8523 {"complete_check", 0, 0, f_complete_check}, 8524 #endif 8525 {"confirm", 1, 4, f_confirm}, 8526 {"copy", 1, 1, f_copy}, 8527 #ifdef FEAT_FLOAT 8528 {"cos", 1, 1, f_cos}, 8529 {"cosh", 1, 1, f_cosh}, 8530 #endif 8531 {"count", 2, 4, f_count}, 8532 {"cscope_connection",0,3, f_cscope_connection}, 8533 {"cursor", 1, 3, f_cursor}, 8534 {"deepcopy", 1, 2, f_deepcopy}, 8535 {"delete", 1, 2, f_delete}, 8536 {"did_filetype", 0, 0, f_did_filetype}, 8537 {"diff_filler", 1, 1, f_diff_filler}, 8538 {"diff_hlID", 2, 2, f_diff_hlID}, 8539 {"empty", 1, 1, f_empty}, 8540 {"escape", 2, 2, f_escape}, 8541 {"eval", 1, 1, f_eval}, 8542 {"eventhandler", 0, 0, f_eventhandler}, 8543 {"executable", 1, 1, f_executable}, 8544 {"exepath", 1, 1, f_exepath}, 8545 {"exists", 1, 1, f_exists}, 8546 #ifdef FEAT_FLOAT 8547 {"exp", 1, 1, f_exp}, 8548 #endif 8549 {"expand", 1, 3, f_expand}, 8550 {"extend", 2, 3, f_extend}, 8551 {"feedkeys", 1, 2, f_feedkeys}, 8552 {"file_readable", 1, 1, f_filereadable}, /* obsolete */ 8553 {"filereadable", 1, 1, f_filereadable}, 8554 {"filewritable", 1, 1, f_filewritable}, 8555 {"filter", 2, 2, f_filter}, 8556 {"finddir", 1, 3, f_finddir}, 8557 {"findfile", 1, 3, f_findfile}, 8558 #ifdef FEAT_FLOAT 8559 {"float2nr", 1, 1, f_float2nr}, 8560 {"floor", 1, 1, f_floor}, 8561 {"fmod", 2, 2, f_fmod}, 8562 #endif 8563 {"fnameescape", 1, 1, f_fnameescape}, 8564 {"fnamemodify", 2, 2, f_fnamemodify}, 8565 {"foldclosed", 1, 1, f_foldclosed}, 8566 {"foldclosedend", 1, 1, f_foldclosedend}, 8567 {"foldlevel", 1, 1, f_foldlevel}, 8568 {"foldtext", 0, 0, f_foldtext}, 8569 {"foldtextresult", 1, 1, f_foldtextresult}, 8570 {"foreground", 0, 0, f_foreground}, 8571 {"function", 1, 3, f_function}, 8572 {"garbagecollect", 0, 1, f_garbagecollect}, 8573 {"get", 2, 3, f_get}, 8574 {"getbufline", 2, 3, f_getbufline}, 8575 {"getbufvar", 2, 3, f_getbufvar}, 8576 {"getchar", 0, 1, f_getchar}, 8577 {"getcharmod", 0, 0, f_getcharmod}, 8578 {"getcharsearch", 0, 0, f_getcharsearch}, 8579 {"getcmdline", 0, 0, f_getcmdline}, 8580 {"getcmdpos", 0, 0, f_getcmdpos}, 8581 {"getcmdtype", 0, 0, f_getcmdtype}, 8582 {"getcmdwintype", 0, 0, f_getcmdwintype}, 8583 {"getcurpos", 0, 0, f_getcurpos}, 8584 {"getcwd", 0, 2, f_getcwd}, 8585 {"getfontname", 0, 1, f_getfontname}, 8586 {"getfperm", 1, 1, f_getfperm}, 8587 {"getfsize", 1, 1, f_getfsize}, 8588 {"getftime", 1, 1, f_getftime}, 8589 {"getftype", 1, 1, f_getftype}, 8590 {"getline", 1, 2, f_getline}, 8591 {"getloclist", 1, 1, f_getqflist}, 8592 {"getmatches", 0, 0, f_getmatches}, 8593 {"getpid", 0, 0, f_getpid}, 8594 {"getpos", 1, 1, f_getpos}, 8595 {"getqflist", 0, 0, f_getqflist}, 8596 {"getreg", 0, 3, f_getreg}, 8597 {"getregtype", 0, 1, f_getregtype}, 8598 {"gettabvar", 2, 3, f_gettabvar}, 8599 {"gettabwinvar", 3, 4, f_gettabwinvar}, 8600 {"getwinposx", 0, 0, f_getwinposx}, 8601 {"getwinposy", 0, 0, f_getwinposy}, 8602 {"getwinvar", 2, 3, f_getwinvar}, 8603 {"glob", 1, 4, f_glob}, 8604 {"glob2regpat", 1, 1, f_glob2regpat}, 8605 {"globpath", 2, 5, f_globpath}, 8606 {"has", 1, 1, f_has}, 8607 {"has_key", 2, 2, f_has_key}, 8608 {"haslocaldir", 0, 2, f_haslocaldir}, 8609 {"hasmapto", 1, 3, f_hasmapto}, 8610 {"highlightID", 1, 1, f_hlID}, /* obsolete */ 8611 {"highlight_exists",1, 1, f_hlexists}, /* obsolete */ 8612 {"histadd", 2, 2, f_histadd}, 8613 {"histdel", 1, 2, f_histdel}, 8614 {"histget", 1, 2, f_histget}, 8615 {"histnr", 1, 1, f_histnr}, 8616 {"hlID", 1, 1, f_hlID}, 8617 {"hlexists", 1, 1, f_hlexists}, 8618 {"hostname", 0, 0, f_hostname}, 8619 {"iconv", 3, 3, f_iconv}, 8620 {"indent", 1, 1, f_indent}, 8621 {"index", 2, 4, f_index}, 8622 {"input", 1, 3, f_input}, 8623 {"inputdialog", 1, 3, f_inputdialog}, 8624 {"inputlist", 1, 1, f_inputlist}, 8625 {"inputrestore", 0, 0, f_inputrestore}, 8626 {"inputsave", 0, 0, f_inputsave}, 8627 {"inputsecret", 1, 2, f_inputsecret}, 8628 {"insert", 2, 3, f_insert}, 8629 {"invert", 1, 1, f_invert}, 8630 {"isdirectory", 1, 1, f_isdirectory}, 8631 {"islocked", 1, 1, f_islocked}, 8632 #if defined(FEAT_FLOAT) && defined(HAVE_MATH_H) 8633 {"isnan", 1, 1, f_isnan}, 8634 #endif 8635 {"items", 1, 1, f_items}, 8636 #ifdef FEAT_JOB_CHANNEL 8637 {"job_getchannel", 1, 1, f_job_getchannel}, 8638 {"job_info", 1, 1, f_job_info}, 8639 {"job_setoptions", 2, 2, f_job_setoptions}, 8640 {"job_start", 1, 2, f_job_start}, 8641 {"job_status", 1, 1, f_job_status}, 8642 {"job_stop", 1, 2, f_job_stop}, 8643 #endif 8644 {"join", 1, 2, f_join}, 8645 {"js_decode", 1, 1, f_js_decode}, 8646 {"js_encode", 1, 1, f_js_encode}, 8647 {"json_decode", 1, 1, f_json_decode}, 8648 {"json_encode", 1, 1, f_json_encode}, 8649 {"keys", 1, 1, f_keys}, 8650 {"last_buffer_nr", 0, 0, f_last_buffer_nr},/* obsolete */ 8651 {"len", 1, 1, f_len}, 8652 {"libcall", 3, 3, f_libcall}, 8653 {"libcallnr", 3, 3, f_libcallnr}, 8654 {"line", 1, 1, f_line}, 8655 {"line2byte", 1, 1, f_line2byte}, 8656 {"lispindent", 1, 1, f_lispindent}, 8657 {"localtime", 0, 0, f_localtime}, 8658 #ifdef FEAT_FLOAT 8659 {"log", 1, 1, f_log}, 8660 {"log10", 1, 1, f_log10}, 8661 #endif 8662 #ifdef FEAT_LUA 8663 {"luaeval", 1, 2, f_luaeval}, 8664 #endif 8665 {"map", 2, 2, f_map}, 8666 {"maparg", 1, 4, f_maparg}, 8667 {"mapcheck", 1, 3, f_mapcheck}, 8668 {"match", 2, 4, f_match}, 8669 {"matchadd", 2, 5, f_matchadd}, 8670 {"matchaddpos", 2, 5, f_matchaddpos}, 8671 {"matcharg", 1, 1, f_matcharg}, 8672 {"matchdelete", 1, 1, f_matchdelete}, 8673 {"matchend", 2, 4, f_matchend}, 8674 {"matchlist", 2, 4, f_matchlist}, 8675 {"matchstr", 2, 4, f_matchstr}, 8676 {"matchstrpos", 2, 4, f_matchstrpos}, 8677 {"max", 1, 1, f_max}, 8678 {"min", 1, 1, f_min}, 8679 #ifdef vim_mkdir 8680 {"mkdir", 1, 3, f_mkdir}, 8681 #endif 8682 {"mode", 0, 1, f_mode}, 8683 #ifdef FEAT_MZSCHEME 8684 {"mzeval", 1, 1, f_mzeval}, 8685 #endif 8686 {"nextnonblank", 1, 1, f_nextnonblank}, 8687 {"nr2char", 1, 2, f_nr2char}, 8688 {"or", 2, 2, f_or}, 8689 {"pathshorten", 1, 1, f_pathshorten}, 8690 #ifdef FEAT_PERL 8691 {"perleval", 1, 1, f_perleval}, 8692 #endif 8693 #ifdef FEAT_FLOAT 8694 {"pow", 2, 2, f_pow}, 8695 #endif 8696 {"prevnonblank", 1, 1, f_prevnonblank}, 8697 {"printf", 2, 19, f_printf}, 8698 {"pumvisible", 0, 0, f_pumvisible}, 8699 #ifdef FEAT_PYTHON3 8700 {"py3eval", 1, 1, f_py3eval}, 8701 #endif 8702 #ifdef FEAT_PYTHON 8703 {"pyeval", 1, 1, f_pyeval}, 8704 #endif 8705 {"range", 1, 3, f_range}, 8706 {"readfile", 1, 3, f_readfile}, 8707 {"reltime", 0, 2, f_reltime}, 8708 #ifdef FEAT_FLOAT 8709 {"reltimefloat", 1, 1, f_reltimefloat}, 8710 #endif 8711 {"reltimestr", 1, 1, f_reltimestr}, 8712 {"remote_expr", 2, 3, f_remote_expr}, 8713 {"remote_foreground", 1, 1, f_remote_foreground}, 8714 {"remote_peek", 1, 2, f_remote_peek}, 8715 {"remote_read", 1, 1, f_remote_read}, 8716 {"remote_send", 2, 3, f_remote_send}, 8717 {"remove", 2, 3, f_remove}, 8718 {"rename", 2, 2, f_rename}, 8719 {"repeat", 2, 2, f_repeat}, 8720 {"resolve", 1, 1, f_resolve}, 8721 {"reverse", 1, 1, f_reverse}, 8722 #ifdef FEAT_FLOAT 8723 {"round", 1, 1, f_round}, 8724 #endif 8725 {"screenattr", 2, 2, f_screenattr}, 8726 {"screenchar", 2, 2, f_screenchar}, 8727 {"screencol", 0, 0, f_screencol}, 8728 {"screenrow", 0, 0, f_screenrow}, 8729 {"search", 1, 4, f_search}, 8730 {"searchdecl", 1, 3, f_searchdecl}, 8731 {"searchpair", 3, 7, f_searchpair}, 8732 {"searchpairpos", 3, 7, f_searchpairpos}, 8733 {"searchpos", 1, 4, f_searchpos}, 8734 {"server2client", 2, 2, f_server2client}, 8735 {"serverlist", 0, 0, f_serverlist}, 8736 {"setbufvar", 3, 3, f_setbufvar}, 8737 {"setcharsearch", 1, 1, f_setcharsearch}, 8738 {"setcmdpos", 1, 1, f_setcmdpos}, 8739 {"setfperm", 2, 2, f_setfperm}, 8740 {"setline", 2, 2, f_setline}, 8741 {"setloclist", 2, 3, f_setloclist}, 8742 {"setmatches", 1, 1, f_setmatches}, 8743 {"setpos", 2, 2, f_setpos}, 8744 {"setqflist", 1, 2, f_setqflist}, 8745 {"setreg", 2, 3, f_setreg}, 8746 {"settabvar", 3, 3, f_settabvar}, 8747 {"settabwinvar", 4, 4, f_settabwinvar}, 8748 {"setwinvar", 3, 3, f_setwinvar}, 8749 #ifdef FEAT_CRYPT 8750 {"sha256", 1, 1, f_sha256}, 8751 #endif 8752 {"shellescape", 1, 2, f_shellescape}, 8753 {"shiftwidth", 0, 0, f_shiftwidth}, 8754 {"simplify", 1, 1, f_simplify}, 8755 #ifdef FEAT_FLOAT 8756 {"sin", 1, 1, f_sin}, 8757 {"sinh", 1, 1, f_sinh}, 8758 #endif 8759 {"sort", 1, 3, f_sort}, 8760 {"soundfold", 1, 1, f_soundfold}, 8761 {"spellbadword", 0, 1, f_spellbadword}, 8762 {"spellsuggest", 1, 3, f_spellsuggest}, 8763 {"split", 1, 3, f_split}, 8764 #ifdef FEAT_FLOAT 8765 {"sqrt", 1, 1, f_sqrt}, 8766 {"str2float", 1, 1, f_str2float}, 8767 #endif 8768 {"str2nr", 1, 2, f_str2nr}, 8769 {"strcharpart", 2, 3, f_strcharpart}, 8770 {"strchars", 1, 2, f_strchars}, 8771 {"strdisplaywidth", 1, 2, f_strdisplaywidth}, 8772 #ifdef HAVE_STRFTIME 8773 {"strftime", 1, 2, f_strftime}, 8774 #endif 8775 {"strgetchar", 2, 2, f_strgetchar}, 8776 {"stridx", 2, 3, f_stridx}, 8777 {"string", 1, 1, f_string}, 8778 {"strlen", 1, 1, f_strlen}, 8779 {"strpart", 2, 3, f_strpart}, 8780 {"strridx", 2, 3, f_strridx}, 8781 {"strtrans", 1, 1, f_strtrans}, 8782 {"strwidth", 1, 1, f_strwidth}, 8783 {"submatch", 1, 2, f_submatch}, 8784 {"substitute", 4, 4, f_substitute}, 8785 {"synID", 3, 3, f_synID}, 8786 {"synIDattr", 2, 3, f_synIDattr}, 8787 {"synIDtrans", 1, 1, f_synIDtrans}, 8788 {"synconcealed", 2, 2, f_synconcealed}, 8789 {"synstack", 2, 2, f_synstack}, 8790 {"system", 1, 2, f_system}, 8791 {"systemlist", 1, 2, f_systemlist}, 8792 {"tabpagebuflist", 0, 1, f_tabpagebuflist}, 8793 {"tabpagenr", 0, 1, f_tabpagenr}, 8794 {"tabpagewinnr", 1, 2, f_tabpagewinnr}, 8795 {"tagfiles", 0, 0, f_tagfiles}, 8796 {"taglist", 1, 1, f_taglist}, 8797 #ifdef FEAT_FLOAT 8798 {"tan", 1, 1, f_tan}, 8799 {"tanh", 1, 1, f_tanh}, 8800 #endif 8801 {"tempname", 0, 0, f_tempname}, 8802 {"test_alloc_fail", 3, 3, f_test_alloc_fail}, 8803 {"test_disable_char_avail", 1, 1, f_test_disable_char_avail}, 8804 {"test_garbagecollect_now", 0, 0, f_test_garbagecollect_now}, 8805 #ifdef FEAT_JOB_CHANNEL 8806 {"test_null_channel", 0, 0, f_test_null_channel}, 8807 #endif 8808 {"test_null_dict", 0, 0, f_test_null_dict}, 8809 #ifdef FEAT_JOB_CHANNEL 8810 {"test_null_job", 0, 0, f_test_null_job}, 8811 #endif 8812 {"test_null_list", 0, 0, f_test_null_list}, 8813 {"test_null_partial", 0, 0, f_test_null_partial}, 8814 {"test_null_string", 0, 0, f_test_null_string}, 8815 #ifdef FEAT_TIMERS 8816 {"timer_start", 2, 3, f_timer_start}, 8817 {"timer_stop", 1, 1, f_timer_stop}, 8818 #endif 8819 {"tolower", 1, 1, f_tolower}, 8820 {"toupper", 1, 1, f_toupper}, 8821 {"tr", 3, 3, f_tr}, 8822 #ifdef FEAT_FLOAT 8823 {"trunc", 1, 1, f_trunc}, 8824 #endif 8825 {"type", 1, 1, f_type}, 8826 {"undofile", 1, 1, f_undofile}, 8827 {"undotree", 0, 0, f_undotree}, 8828 {"uniq", 1, 3, f_uniq}, 8829 {"values", 1, 1, f_values}, 8830 {"virtcol", 1, 1, f_virtcol}, 8831 {"visualmode", 0, 1, f_visualmode}, 8832 {"wildmenumode", 0, 0, f_wildmenumode}, 8833 {"win_findbuf", 1, 1, f_win_findbuf}, 8834 {"win_getid", 0, 2, f_win_getid}, 8835 {"win_gotoid", 1, 1, f_win_gotoid}, 8836 {"win_id2tabwin", 1, 1, f_win_id2tabwin}, 8837 {"win_id2win", 1, 1, f_win_id2win}, 8838 {"winbufnr", 1, 1, f_winbufnr}, 8839 {"wincol", 0, 0, f_wincol}, 8840 {"winheight", 1, 1, f_winheight}, 8841 {"winline", 0, 0, f_winline}, 8842 {"winnr", 0, 1, f_winnr}, 8843 {"winrestcmd", 0, 0, f_winrestcmd}, 8844 {"winrestview", 1, 1, f_winrestview}, 8845 {"winsaveview", 0, 0, f_winsaveview}, 8846 {"winwidth", 1, 1, f_winwidth}, 8847 {"wordcount", 0, 0, f_wordcount}, 8848 {"writefile", 2, 3, f_writefile}, 8849 {"xor", 2, 2, f_xor}, 8850 }; 8851 8852 #if defined(FEAT_CMDL_COMPL) || defined(PROTO) 8853 8854 /* 8855 * Function given to ExpandGeneric() to obtain the list of internal 8856 * or user defined function names. 8857 */ 8858 char_u * 8859 get_function_name(expand_T *xp, int idx) 8860 { 8861 static int intidx = -1; 8862 char_u *name; 8863 8864 if (idx == 0) 8865 intidx = -1; 8866 if (intidx < 0) 8867 { 8868 name = get_user_func_name(xp, idx); 8869 if (name != NULL) 8870 return name; 8871 } 8872 if (++intidx < (int)(sizeof(functions) / sizeof(struct fst))) 8873 { 8874 STRCPY(IObuff, functions[intidx].f_name); 8875 STRCAT(IObuff, "("); 8876 if (functions[intidx].f_max_argc == 0) 8877 STRCAT(IObuff, ")"); 8878 return IObuff; 8879 } 8880 8881 return NULL; 8882 } 8883 8884 /* 8885 * Function given to ExpandGeneric() to obtain the list of internal or 8886 * user defined variable or function names. 8887 */ 8888 char_u * 8889 get_expr_name(expand_T *xp, int idx) 8890 { 8891 static int intidx = -1; 8892 char_u *name; 8893 8894 if (idx == 0) 8895 intidx = -1; 8896 if (intidx < 0) 8897 { 8898 name = get_function_name(xp, idx); 8899 if (name != NULL) 8900 return name; 8901 } 8902 return get_user_var_name(xp, ++intidx); 8903 } 8904 8905 #endif /* FEAT_CMDL_COMPL */ 8906 8907 #if defined(EBCDIC) || defined(PROTO) 8908 /* 8909 * Compare struct fst by function name. 8910 */ 8911 static int 8912 compare_func_name(const void *s1, const void *s2) 8913 { 8914 struct fst *p1 = (struct fst *)s1; 8915 struct fst *p2 = (struct fst *)s2; 8916 8917 return STRCMP(p1->f_name, p2->f_name); 8918 } 8919 8920 /* 8921 * Sort the function table by function name. 8922 * The sorting of the table above is ASCII dependant. 8923 * On machines using EBCDIC we have to sort it. 8924 */ 8925 static void 8926 sortFunctions(void) 8927 { 8928 int funcCnt = (int)(sizeof(functions) / sizeof(struct fst)) - 1; 8929 8930 qsort(functions, (size_t)funcCnt, sizeof(struct fst), compare_func_name); 8931 } 8932 #endif 8933 8934 8935 /* 8936 * Find internal function in table above. 8937 * Return index, or -1 if not found 8938 */ 8939 static int 8940 find_internal_func( 8941 char_u *name) /* name of the function */ 8942 { 8943 int first = 0; 8944 int last = (int)(sizeof(functions) / sizeof(struct fst)) - 1; 8945 int cmp; 8946 int x; 8947 8948 /* 8949 * Find the function name in the table. Binary search. 8950 */ 8951 while (first <= last) 8952 { 8953 x = first + ((unsigned)(last - first) >> 1); 8954 cmp = STRCMP(name, functions[x].f_name); 8955 if (cmp < 0) 8956 last = x - 1; 8957 else if (cmp > 0) 8958 first = x + 1; 8959 else 8960 return x; 8961 } 8962 return -1; 8963 } 8964 8965 /* 8966 * Check if "name" is a variable of type VAR_FUNC. If so, return the function 8967 * name it contains, otherwise return "name". 8968 * If "partialp" is not NULL, and "name" is of type VAR_PARTIAL also set 8969 * "partialp". 8970 */ 8971 static char_u * 8972 deref_func_name(char_u *name, int *lenp, partial_T **partialp, int no_autoload) 8973 { 8974 dictitem_T *v; 8975 int cc; 8976 8977 if (partialp != NULL) 8978 *partialp = NULL; 8979 8980 cc = name[*lenp]; 8981 name[*lenp] = NUL; 8982 v = find_var(name, NULL, no_autoload); 8983 name[*lenp] = cc; 8984 if (v != NULL && v->di_tv.v_type == VAR_FUNC) 8985 { 8986 if (v->di_tv.vval.v_string == NULL) 8987 { 8988 *lenp = 0; 8989 return (char_u *)""; /* just in case */ 8990 } 8991 *lenp = (int)STRLEN(v->di_tv.vval.v_string); 8992 return v->di_tv.vval.v_string; 8993 } 8994 8995 if (v != NULL && v->di_tv.v_type == VAR_PARTIAL) 8996 { 8997 partial_T *pt = v->di_tv.vval.v_partial; 8998 8999 if (pt == NULL) 9000 { 9001 *lenp = 0; 9002 return (char_u *)""; /* just in case */ 9003 } 9004 if (partialp != NULL) 9005 *partialp = pt; 9006 *lenp = (int)STRLEN(pt->pt_name); 9007 return pt->pt_name; 9008 } 9009 9010 return name; 9011 } 9012 9013 /* 9014 * Allocate a variable for the result of a function. 9015 * Return OK or FAIL. 9016 */ 9017 static int 9018 get_func_tv( 9019 char_u *name, /* name of the function */ 9020 int len, /* length of "name" */ 9021 typval_T *rettv, 9022 char_u **arg, /* argument, pointing to the '(' */ 9023 linenr_T firstline, /* first line of range */ 9024 linenr_T lastline, /* last line of range */ 9025 int *doesrange, /* return: function handled range */ 9026 int evaluate, 9027 partial_T *partial, /* for extra arguments */ 9028 dict_T *selfdict) /* Dictionary for "self" */ 9029 { 9030 char_u *argp; 9031 int ret = OK; 9032 typval_T argvars[MAX_FUNC_ARGS + 1]; /* vars for arguments */ 9033 int argcount = 0; /* number of arguments found */ 9034 9035 /* 9036 * Get the arguments. 9037 */ 9038 argp = *arg; 9039 while (argcount < MAX_FUNC_ARGS - (partial == NULL ? 0 : partial->pt_argc)) 9040 { 9041 argp = skipwhite(argp + 1); /* skip the '(' or ',' */ 9042 if (*argp == ')' || *argp == ',' || *argp == NUL) 9043 break; 9044 if (eval1(&argp, &argvars[argcount], evaluate) == FAIL) 9045 { 9046 ret = FAIL; 9047 break; 9048 } 9049 ++argcount; 9050 if (*argp != ',') 9051 break; 9052 } 9053 if (*argp == ')') 9054 ++argp; 9055 else 9056 ret = FAIL; 9057 9058 if (ret == OK) 9059 { 9060 int i = 0; 9061 9062 if (get_vim_var_nr(VV_TESTING)) 9063 { 9064 /* Prepare for calling test_garbagecollect_now(), need to know 9065 * what variables are used on the call stack. */ 9066 if (funcargs.ga_itemsize == 0) 9067 ga_init2(&funcargs, (int)sizeof(typval_T *), 50); 9068 for (i = 0; i < argcount; ++i) 9069 if (ga_grow(&funcargs, 1) == OK) 9070 ((typval_T **)funcargs.ga_data)[funcargs.ga_len++] = 9071 &argvars[i]; 9072 } 9073 9074 ret = call_func(name, len, rettv, argcount, argvars, 9075 firstline, lastline, doesrange, evaluate, partial, selfdict); 9076 9077 funcargs.ga_len -= i; 9078 } 9079 else if (!aborting()) 9080 { 9081 if (argcount == MAX_FUNC_ARGS) 9082 emsg_funcname(N_("E740: Too many arguments for function %s"), name); 9083 else 9084 emsg_funcname(N_("E116: Invalid arguments for function %s"), name); 9085 } 9086 9087 while (--argcount >= 0) 9088 clear_tv(&argvars[argcount]); 9089 9090 *arg = skipwhite(argp); 9091 return ret; 9092 } 9093 9094 #define ERROR_UNKNOWN 0 9095 #define ERROR_TOOMANY 1 9096 #define ERROR_TOOFEW 2 9097 #define ERROR_SCRIPT 3 9098 #define ERROR_DICT 4 9099 #define ERROR_NONE 5 9100 #define ERROR_OTHER 6 9101 #define FLEN_FIXED 40 9102 9103 /* 9104 * In a script change <SID>name() and s:name() to K_SNR 123_name(). 9105 * Change <SNR>123_name() to K_SNR 123_name(). 9106 * Use "fname_buf[FLEN_FIXED + 1]" when it fits, otherwise allocate memory 9107 * (slow). 9108 */ 9109 static char_u * 9110 fname_trans_sid(char_u *name, char_u *fname_buf, char_u **tofree, int *error) 9111 { 9112 int llen; 9113 char_u *fname; 9114 int i; 9115 9116 llen = eval_fname_script(name); 9117 if (llen > 0) 9118 { 9119 fname_buf[0] = K_SPECIAL; 9120 fname_buf[1] = KS_EXTRA; 9121 fname_buf[2] = (int)KE_SNR; 9122 i = 3; 9123 if (eval_fname_sid(name)) /* "<SID>" or "s:" */ 9124 { 9125 if (current_SID <= 0) 9126 *error = ERROR_SCRIPT; 9127 else 9128 { 9129 sprintf((char *)fname_buf + 3, "%ld_", (long)current_SID); 9130 i = (int)STRLEN(fname_buf); 9131 } 9132 } 9133 if (i + STRLEN(name + llen) < FLEN_FIXED) 9134 { 9135 STRCPY(fname_buf + i, name + llen); 9136 fname = fname_buf; 9137 } 9138 else 9139 { 9140 fname = alloc((unsigned)(i + STRLEN(name + llen) + 1)); 9141 if (fname == NULL) 9142 *error = ERROR_OTHER; 9143 else 9144 { 9145 *tofree = fname; 9146 mch_memmove(fname, fname_buf, (size_t)i); 9147 STRCPY(fname + i, name + llen); 9148 } 9149 } 9150 } 9151 else 9152 fname = name; 9153 return fname; 9154 } 9155 9156 /* 9157 * Call a function with its resolved parameters 9158 * Return FAIL when the function can't be called, OK otherwise. 9159 * Also returns OK when an error was encountered while executing the function. 9160 */ 9161 int 9162 call_func( 9163 char_u *funcname, /* name of the function */ 9164 int len, /* length of "name" */ 9165 typval_T *rettv, /* return value goes here */ 9166 int argcount_in, /* number of "argvars" */ 9167 typval_T *argvars_in, /* vars for arguments, must have "argcount" 9168 PLUS ONE elements! */ 9169 linenr_T firstline, /* first line of range */ 9170 linenr_T lastline, /* last line of range */ 9171 int *doesrange, /* return: function handled range */ 9172 int evaluate, 9173 partial_T *partial, /* optional, can be NULL */ 9174 dict_T *selfdict_in) /* Dictionary for "self" */ 9175 { 9176 int ret = FAIL; 9177 int error = ERROR_NONE; 9178 int i; 9179 ufunc_T *fp; 9180 char_u fname_buf[FLEN_FIXED + 1]; 9181 char_u *tofree = NULL; 9182 char_u *fname; 9183 char_u *name; 9184 int argcount = argcount_in; 9185 typval_T *argvars = argvars_in; 9186 dict_T *selfdict = selfdict_in; 9187 typval_T argv[MAX_FUNC_ARGS + 1]; /* used when "partial" is not NULL */ 9188 int argv_clear = 0; 9189 9190 /* Make a copy of the name, if it comes from a funcref variable it could 9191 * be changed or deleted in the called function. */ 9192 name = vim_strnsave(funcname, len); 9193 if (name == NULL) 9194 return ret; 9195 9196 fname = fname_trans_sid(name, fname_buf, &tofree, &error); 9197 9198 *doesrange = FALSE; 9199 9200 if (partial != NULL) 9201 { 9202 /* When the function has a partial with a dict and there is a dict 9203 * argument, use the dict argument. That is backwards compatible. 9204 * When the dict was bound explicitly use the one from the partial. */ 9205 if (partial->pt_dict != NULL 9206 && (selfdict_in == NULL || !partial->pt_auto)) 9207 selfdict = partial->pt_dict; 9208 if (error == ERROR_NONE && partial->pt_argc > 0) 9209 { 9210 for (argv_clear = 0; argv_clear < partial->pt_argc; ++argv_clear) 9211 copy_tv(&partial->pt_argv[argv_clear], &argv[argv_clear]); 9212 for (i = 0; i < argcount_in; ++i) 9213 argv[i + argv_clear] = argvars_in[i]; 9214 argvars = argv; 9215 argcount = partial->pt_argc + argcount_in; 9216 } 9217 } 9218 9219 9220 /* execute the function if no errors detected and executing */ 9221 if (evaluate && error == ERROR_NONE) 9222 { 9223 char_u *rfname = fname; 9224 9225 /* Ignore "g:" before a function name. */ 9226 if (fname[0] == 'g' && fname[1] == ':') 9227 rfname = fname + 2; 9228 9229 rettv->v_type = VAR_NUMBER; /* default rettv is number zero */ 9230 rettv->vval.v_number = 0; 9231 error = ERROR_UNKNOWN; 9232 9233 if (!builtin_function(rfname, -1)) 9234 { 9235 /* 9236 * User defined function. 9237 */ 9238 fp = find_func(rfname); 9239 9240 #ifdef FEAT_AUTOCMD 9241 /* Trigger FuncUndefined event, may load the function. */ 9242 if (fp == NULL 9243 && apply_autocmds(EVENT_FUNCUNDEFINED, 9244 rfname, rfname, TRUE, NULL) 9245 && !aborting()) 9246 { 9247 /* executed an autocommand, search for the function again */ 9248 fp = find_func(rfname); 9249 } 9250 #endif 9251 /* Try loading a package. */ 9252 if (fp == NULL && script_autoload(rfname, TRUE) && !aborting()) 9253 { 9254 /* loaded a package, search for the function again */ 9255 fp = find_func(rfname); 9256 } 9257 9258 if (fp != NULL) 9259 { 9260 if (fp->uf_flags & FC_RANGE) 9261 *doesrange = TRUE; 9262 if (argcount < fp->uf_args.ga_len) 9263 error = ERROR_TOOFEW; 9264 else if (!fp->uf_varargs && argcount > fp->uf_args.ga_len) 9265 error = ERROR_TOOMANY; 9266 else if ((fp->uf_flags & FC_DICT) && selfdict == NULL) 9267 error = ERROR_DICT; 9268 else 9269 { 9270 int did_save_redo = FALSE; 9271 9272 /* 9273 * Call the user function. 9274 * Save and restore search patterns, script variables and 9275 * redo buffer. 9276 */ 9277 save_search_patterns(); 9278 #ifdef FEAT_INS_EXPAND 9279 if (!ins_compl_active()) 9280 #endif 9281 { 9282 saveRedobuff(); 9283 did_save_redo = TRUE; 9284 } 9285 ++fp->uf_calls; 9286 call_user_func(fp, argcount, argvars, rettv, 9287 firstline, lastline, 9288 (fp->uf_flags & FC_DICT) ? selfdict : NULL); 9289 if (--fp->uf_calls <= 0 && isdigit(*fp->uf_name) 9290 && fp->uf_refcount <= 0) 9291 /* Function was unreferenced while being used, free it 9292 * now. */ 9293 func_free(fp); 9294 if (did_save_redo) 9295 restoreRedobuff(); 9296 restore_search_patterns(); 9297 error = ERROR_NONE; 9298 } 9299 } 9300 } 9301 else 9302 { 9303 /* 9304 * Find the function name in the table, call its implementation. 9305 */ 9306 i = find_internal_func(fname); 9307 if (i >= 0) 9308 { 9309 if (argcount < functions[i].f_min_argc) 9310 error = ERROR_TOOFEW; 9311 else if (argcount > functions[i].f_max_argc) 9312 error = ERROR_TOOMANY; 9313 else 9314 { 9315 argvars[argcount].v_type = VAR_UNKNOWN; 9316 functions[i].f_func(argvars, rettv); 9317 error = ERROR_NONE; 9318 } 9319 } 9320 } 9321 /* 9322 * The function call (or "FuncUndefined" autocommand sequence) might 9323 * have been aborted by an error, an interrupt, or an explicitly thrown 9324 * exception that has not been caught so far. This situation can be 9325 * tested for by calling aborting(). For an error in an internal 9326 * function or for the "E132" error in call_user_func(), however, the 9327 * throw point at which the "force_abort" flag (temporarily reset by 9328 * emsg()) is normally updated has not been reached yet. We need to 9329 * update that flag first to make aborting() reliable. 9330 */ 9331 update_force_abort(); 9332 } 9333 if (error == ERROR_NONE) 9334 ret = OK; 9335 9336 /* 9337 * Report an error unless the argument evaluation or function call has been 9338 * cancelled due to an aborting error, an interrupt, or an exception. 9339 */ 9340 if (!aborting()) 9341 { 9342 switch (error) 9343 { 9344 case ERROR_UNKNOWN: 9345 emsg_funcname(N_("E117: Unknown function: %s"), name); 9346 break; 9347 case ERROR_TOOMANY: 9348 emsg_funcname(e_toomanyarg, name); 9349 break; 9350 case ERROR_TOOFEW: 9351 emsg_funcname(N_("E119: Not enough arguments for function: %s"), 9352 name); 9353 break; 9354 case ERROR_SCRIPT: 9355 emsg_funcname(N_("E120: Using <SID> not in a script context: %s"), 9356 name); 9357 break; 9358 case ERROR_DICT: 9359 emsg_funcname(N_("E725: Calling dict function without Dictionary: %s"), 9360 name); 9361 break; 9362 } 9363 } 9364 9365 while (argv_clear > 0) 9366 clear_tv(&argv[--argv_clear]); 9367 vim_free(tofree); 9368 vim_free(name); 9369 9370 return ret; 9371 } 9372 9373 /* 9374 * Give an error message with a function name. Handle <SNR> things. 9375 * "ermsg" is to be passed without translation, use N_() instead of _(). 9376 */ 9377 static void 9378 emsg_funcname(char *ermsg, char_u *name) 9379 { 9380 char_u *p; 9381 9382 if (*name == K_SPECIAL) 9383 p = concat_str((char_u *)"<SNR>", name + 3); 9384 else 9385 p = name; 9386 EMSG2(_(ermsg), p); 9387 if (p != name) 9388 vim_free(p); 9389 } 9390 9391 /* 9392 * Return TRUE for a non-zero Number and a non-empty String. 9393 */ 9394 static int 9395 non_zero_arg(typval_T *argvars) 9396 { 9397 return ((argvars[0].v_type == VAR_NUMBER 9398 && argvars[0].vval.v_number != 0) 9399 || (argvars[0].v_type == VAR_STRING 9400 && argvars[0].vval.v_string != NULL 9401 && *argvars[0].vval.v_string != NUL)); 9402 } 9403 9404 /********************************************* 9405 * Implementation of the built-in functions 9406 */ 9407 9408 #ifdef FEAT_FLOAT 9409 static int get_float_arg(typval_T *argvars, float_T *f); 9410 9411 /* 9412 * Get the float value of "argvars[0]" into "f". 9413 * Returns FAIL when the argument is not a Number or Float. 9414 */ 9415 static int 9416 get_float_arg(typval_T *argvars, float_T *f) 9417 { 9418 if (argvars[0].v_type == VAR_FLOAT) 9419 { 9420 *f = argvars[0].vval.v_float; 9421 return OK; 9422 } 9423 if (argvars[0].v_type == VAR_NUMBER) 9424 { 9425 *f = (float_T)argvars[0].vval.v_number; 9426 return OK; 9427 } 9428 EMSG(_("E808: Number or Float required")); 9429 return FAIL; 9430 } 9431 9432 /* 9433 * "abs(expr)" function 9434 */ 9435 static void 9436 f_abs(typval_T *argvars, typval_T *rettv) 9437 { 9438 if (argvars[0].v_type == VAR_FLOAT) 9439 { 9440 rettv->v_type = VAR_FLOAT; 9441 rettv->vval.v_float = fabs(argvars[0].vval.v_float); 9442 } 9443 else 9444 { 9445 varnumber_T n; 9446 int error = FALSE; 9447 9448 n = get_tv_number_chk(&argvars[0], &error); 9449 if (error) 9450 rettv->vval.v_number = -1; 9451 else if (n > 0) 9452 rettv->vval.v_number = n; 9453 else 9454 rettv->vval.v_number = -n; 9455 } 9456 } 9457 9458 /* 9459 * "acos()" function 9460 */ 9461 static void 9462 f_acos(typval_T *argvars, typval_T *rettv) 9463 { 9464 float_T f = 0.0; 9465 9466 rettv->v_type = VAR_FLOAT; 9467 if (get_float_arg(argvars, &f) == OK) 9468 rettv->vval.v_float = acos(f); 9469 else 9470 rettv->vval.v_float = 0.0; 9471 } 9472 #endif 9473 9474 /* 9475 * "add(list, item)" function 9476 */ 9477 static void 9478 f_add(typval_T *argvars, typval_T *rettv) 9479 { 9480 list_T *l; 9481 9482 rettv->vval.v_number = 1; /* Default: Failed */ 9483 if (argvars[0].v_type == VAR_LIST) 9484 { 9485 if ((l = argvars[0].vval.v_list) != NULL 9486 && !tv_check_lock(l->lv_lock, 9487 (char_u *)N_("add() argument"), TRUE) 9488 && list_append_tv(l, &argvars[1]) == OK) 9489 copy_tv(&argvars[0], rettv); 9490 } 9491 else 9492 EMSG(_(e_listreq)); 9493 } 9494 9495 /* 9496 * "and(expr, expr)" function 9497 */ 9498 static void 9499 f_and(typval_T *argvars, typval_T *rettv) 9500 { 9501 rettv->vval.v_number = get_tv_number_chk(&argvars[0], NULL) 9502 & get_tv_number_chk(&argvars[1], NULL); 9503 } 9504 9505 /* 9506 * "append(lnum, string/list)" function 9507 */ 9508 static void 9509 f_append(typval_T *argvars, typval_T *rettv) 9510 { 9511 long lnum; 9512 char_u *line; 9513 list_T *l = NULL; 9514 listitem_T *li = NULL; 9515 typval_T *tv; 9516 long added = 0; 9517 9518 /* When coming here from Insert mode, sync undo, so that this can be 9519 * undone separately from what was previously inserted. */ 9520 if (u_sync_once == 2) 9521 { 9522 u_sync_once = 1; /* notify that u_sync() was called */ 9523 u_sync(TRUE); 9524 } 9525 9526 lnum = get_tv_lnum(argvars); 9527 if (lnum >= 0 9528 && lnum <= curbuf->b_ml.ml_line_count 9529 && u_save(lnum, lnum + 1) == OK) 9530 { 9531 if (argvars[1].v_type == VAR_LIST) 9532 { 9533 l = argvars[1].vval.v_list; 9534 if (l == NULL) 9535 return; 9536 li = l->lv_first; 9537 } 9538 for (;;) 9539 { 9540 if (l == NULL) 9541 tv = &argvars[1]; /* append a string */ 9542 else if (li == NULL) 9543 break; /* end of list */ 9544 else 9545 tv = &li->li_tv; /* append item from list */ 9546 line = get_tv_string_chk(tv); 9547 if (line == NULL) /* type error */ 9548 { 9549 rettv->vval.v_number = 1; /* Failed */ 9550 break; 9551 } 9552 ml_append(lnum + added, line, (colnr_T)0, FALSE); 9553 ++added; 9554 if (l == NULL) 9555 break; 9556 li = li->li_next; 9557 } 9558 9559 appended_lines_mark(lnum, added); 9560 if (curwin->w_cursor.lnum > lnum) 9561 curwin->w_cursor.lnum += added; 9562 } 9563 else 9564 rettv->vval.v_number = 1; /* Failed */ 9565 } 9566 9567 /* 9568 * "argc()" function 9569 */ 9570 static void 9571 f_argc(typval_T *argvars UNUSED, typval_T *rettv) 9572 { 9573 rettv->vval.v_number = ARGCOUNT; 9574 } 9575 9576 /* 9577 * "argidx()" function 9578 */ 9579 static void 9580 f_argidx(typval_T *argvars UNUSED, typval_T *rettv) 9581 { 9582 rettv->vval.v_number = curwin->w_arg_idx; 9583 } 9584 9585 /* 9586 * "arglistid()" function 9587 */ 9588 static void 9589 f_arglistid(typval_T *argvars, typval_T *rettv) 9590 { 9591 win_T *wp; 9592 9593 rettv->vval.v_number = -1; 9594 wp = find_tabwin(&argvars[0], &argvars[1]); 9595 if (wp != NULL) 9596 rettv->vval.v_number = wp->w_alist->id; 9597 } 9598 9599 /* 9600 * "argv(nr)" function 9601 */ 9602 static void 9603 f_argv(typval_T *argvars, typval_T *rettv) 9604 { 9605 int idx; 9606 9607 if (argvars[0].v_type != VAR_UNKNOWN) 9608 { 9609 idx = get_tv_number_chk(&argvars[0], NULL); 9610 if (idx >= 0 && idx < ARGCOUNT) 9611 rettv->vval.v_string = vim_strsave(alist_name(&ARGLIST[idx])); 9612 else 9613 rettv->vval.v_string = NULL; 9614 rettv->v_type = VAR_STRING; 9615 } 9616 else if (rettv_list_alloc(rettv) == OK) 9617 for (idx = 0; idx < ARGCOUNT; ++idx) 9618 list_append_string(rettv->vval.v_list, 9619 alist_name(&ARGLIST[idx]), -1); 9620 } 9621 9622 typedef enum 9623 { 9624 ASSERT_EQUAL, 9625 ASSERT_NOTEQUAL, 9626 ASSERT_MATCH, 9627 ASSERT_NOTMATCH, 9628 ASSERT_OTHER 9629 } assert_type_T; 9630 9631 static void prepare_assert_error(garray_T*gap); 9632 static void fill_assert_error(garray_T *gap, typval_T *opt_msg_tv, char_u *exp_str, typval_T *exp_tv, typval_T *got_tv, assert_type_T is_match); 9633 static void assert_error(garray_T *gap); 9634 static void assert_bool(typval_T *argvars, int isTrue); 9635 9636 /* 9637 * Prepare "gap" for an assert error and add the sourcing position. 9638 */ 9639 static void 9640 prepare_assert_error(garray_T *gap) 9641 { 9642 char buf[NUMBUFLEN]; 9643 9644 ga_init2(gap, 1, 100); 9645 if (sourcing_name != NULL) 9646 { 9647 ga_concat(gap, sourcing_name); 9648 if (sourcing_lnum > 0) 9649 ga_concat(gap, (char_u *)" "); 9650 } 9651 if (sourcing_lnum > 0) 9652 { 9653 sprintf(buf, "line %ld", (long)sourcing_lnum); 9654 ga_concat(gap, (char_u *)buf); 9655 } 9656 if (sourcing_name != NULL || sourcing_lnum > 0) 9657 ga_concat(gap, (char_u *)": "); 9658 } 9659 9660 /* 9661 * Append "str" to "gap", escaping unprintable characters. 9662 * Changes NL to \n, CR to \r, etc. 9663 */ 9664 static void 9665 ga_concat_esc(garray_T *gap, char_u *str) 9666 { 9667 char_u *p; 9668 char_u buf[NUMBUFLEN]; 9669 9670 if (str == NULL) 9671 { 9672 ga_concat(gap, (char_u *)"NULL"); 9673 return; 9674 } 9675 9676 for (p = str; *p != NUL; ++p) 9677 switch (*p) 9678 { 9679 case BS: ga_concat(gap, (char_u *)"\\b"); break; 9680 case ESC: ga_concat(gap, (char_u *)"\\e"); break; 9681 case FF: ga_concat(gap, (char_u *)"\\f"); break; 9682 case NL: ga_concat(gap, (char_u *)"\\n"); break; 9683 case TAB: ga_concat(gap, (char_u *)"\\t"); break; 9684 case CAR: ga_concat(gap, (char_u *)"\\r"); break; 9685 case '\\': ga_concat(gap, (char_u *)"\\\\"); break; 9686 default: 9687 if (*p < ' ') 9688 { 9689 vim_snprintf((char *)buf, NUMBUFLEN, "\\x%02x", *p); 9690 ga_concat(gap, buf); 9691 } 9692 else 9693 ga_append(gap, *p); 9694 break; 9695 } 9696 } 9697 9698 /* 9699 * Fill "gap" with information about an assert error. 9700 */ 9701 static void 9702 fill_assert_error( 9703 garray_T *gap, 9704 typval_T *opt_msg_tv, 9705 char_u *exp_str, 9706 typval_T *exp_tv, 9707 typval_T *got_tv, 9708 assert_type_T atype) 9709 { 9710 char_u numbuf[NUMBUFLEN]; 9711 char_u *tofree; 9712 9713 if (opt_msg_tv->v_type != VAR_UNKNOWN) 9714 { 9715 ga_concat(gap, tv2string(opt_msg_tv, &tofree, numbuf, 0)); 9716 vim_free(tofree); 9717 } 9718 else 9719 { 9720 if (atype == ASSERT_MATCH || atype == ASSERT_NOTMATCH) 9721 ga_concat(gap, (char_u *)"Pattern "); 9722 else 9723 ga_concat(gap, (char_u *)"Expected "); 9724 if (exp_str == NULL) 9725 { 9726 ga_concat_esc(gap, tv2string(exp_tv, &tofree, numbuf, 0)); 9727 vim_free(tofree); 9728 } 9729 else 9730 ga_concat_esc(gap, exp_str); 9731 if (atype == ASSERT_MATCH) 9732 ga_concat(gap, (char_u *)" does not match "); 9733 else if (atype == ASSERT_NOTMATCH) 9734 ga_concat(gap, (char_u *)" does match "); 9735 else if (atype == ASSERT_NOTEQUAL) 9736 ga_concat(gap, (char_u *)" differs from "); 9737 else 9738 ga_concat(gap, (char_u *)" but got "); 9739 ga_concat_esc(gap, tv2string(got_tv, &tofree, numbuf, 0)); 9740 vim_free(tofree); 9741 } 9742 } 9743 9744 /* 9745 * Add an assert error to v:errors. 9746 */ 9747 static void 9748 assert_error(garray_T *gap) 9749 { 9750 struct vimvar *vp = &vimvars[VV_ERRORS]; 9751 9752 if (vp->vv_type != VAR_LIST || vimvars[VV_ERRORS].vv_list == NULL) 9753 /* Make sure v:errors is a list. */ 9754 set_vim_var_list(VV_ERRORS, list_alloc()); 9755 list_append_string(vimvars[VV_ERRORS].vv_list, gap->ga_data, gap->ga_len); 9756 } 9757 9758 static void 9759 assert_equal_common(typval_T *argvars, assert_type_T atype) 9760 { 9761 garray_T ga; 9762 9763 if (tv_equal(&argvars[0], &argvars[1], FALSE, FALSE) 9764 != (atype == ASSERT_EQUAL)) 9765 { 9766 prepare_assert_error(&ga); 9767 fill_assert_error(&ga, &argvars[2], NULL, &argvars[0], &argvars[1], 9768 atype); 9769 assert_error(&ga); 9770 ga_clear(&ga); 9771 } 9772 } 9773 9774 /* 9775 * "assert_equal(expected, actual[, msg])" function 9776 */ 9777 static void 9778 f_assert_equal(typval_T *argvars, typval_T *rettv UNUSED) 9779 { 9780 assert_equal_common(argvars, ASSERT_EQUAL); 9781 } 9782 9783 /* 9784 * "assert_notequal(expected, actual[, msg])" function 9785 */ 9786 static void 9787 f_assert_notequal(typval_T *argvars, typval_T *rettv UNUSED) 9788 { 9789 assert_equal_common(argvars, ASSERT_NOTEQUAL); 9790 } 9791 9792 /* 9793 * "assert_exception(string[, msg])" function 9794 */ 9795 static void 9796 f_assert_exception(typval_T *argvars, typval_T *rettv UNUSED) 9797 { 9798 garray_T ga; 9799 char *error; 9800 9801 error = (char *)get_tv_string_chk(&argvars[0]); 9802 if (vimvars[VV_EXCEPTION].vv_str == NULL) 9803 { 9804 prepare_assert_error(&ga); 9805 ga_concat(&ga, (char_u *)"v:exception is not set"); 9806 assert_error(&ga); 9807 ga_clear(&ga); 9808 } 9809 else if (error != NULL 9810 && strstr((char *)vimvars[VV_EXCEPTION].vv_str, error) == NULL) 9811 { 9812 prepare_assert_error(&ga); 9813 fill_assert_error(&ga, &argvars[1], NULL, &argvars[0], 9814 &vimvars[VV_EXCEPTION].vv_tv, ASSERT_OTHER); 9815 assert_error(&ga); 9816 ga_clear(&ga); 9817 } 9818 } 9819 9820 /* 9821 * "assert_fails(cmd [, error])" function 9822 */ 9823 static void 9824 f_assert_fails(typval_T *argvars, typval_T *rettv UNUSED) 9825 { 9826 char_u *cmd = get_tv_string_chk(&argvars[0]); 9827 garray_T ga; 9828 9829 called_emsg = FALSE; 9830 suppress_errthrow = TRUE; 9831 emsg_silent = TRUE; 9832 do_cmdline_cmd(cmd); 9833 if (!called_emsg) 9834 { 9835 prepare_assert_error(&ga); 9836 ga_concat(&ga, (char_u *)"command did not fail: "); 9837 ga_concat(&ga, cmd); 9838 assert_error(&ga); 9839 ga_clear(&ga); 9840 } 9841 else if (argvars[1].v_type != VAR_UNKNOWN) 9842 { 9843 char_u buf[NUMBUFLEN]; 9844 char *error = (char *)get_tv_string_buf_chk(&argvars[1], buf); 9845 9846 if (error == NULL 9847 || strstr((char *)vimvars[VV_ERRMSG].vv_str, error) == NULL) 9848 { 9849 prepare_assert_error(&ga); 9850 fill_assert_error(&ga, &argvars[2], NULL, &argvars[1], 9851 &vimvars[VV_ERRMSG].vv_tv, ASSERT_OTHER); 9852 assert_error(&ga); 9853 ga_clear(&ga); 9854 } 9855 } 9856 9857 called_emsg = FALSE; 9858 suppress_errthrow = FALSE; 9859 emsg_silent = FALSE; 9860 emsg_on_display = FALSE; 9861 set_vim_var_string(VV_ERRMSG, NULL, 0); 9862 } 9863 9864 /* 9865 * Common for assert_true() and assert_false(). 9866 */ 9867 static void 9868 assert_bool(typval_T *argvars, int isTrue) 9869 { 9870 int error = FALSE; 9871 garray_T ga; 9872 9873 if (argvars[0].v_type == VAR_SPECIAL 9874 && argvars[0].vval.v_number == (isTrue ? VVAL_TRUE : VVAL_FALSE)) 9875 return; 9876 if (argvars[0].v_type != VAR_NUMBER 9877 || (get_tv_number_chk(&argvars[0], &error) == 0) == isTrue 9878 || error) 9879 { 9880 prepare_assert_error(&ga); 9881 fill_assert_error(&ga, &argvars[1], 9882 (char_u *)(isTrue ? "True" : "False"), 9883 NULL, &argvars[0], ASSERT_OTHER); 9884 assert_error(&ga); 9885 ga_clear(&ga); 9886 } 9887 } 9888 9889 /* 9890 * "assert_false(actual[, msg])" function 9891 */ 9892 static void 9893 f_assert_false(typval_T *argvars, typval_T *rettv UNUSED) 9894 { 9895 assert_bool(argvars, FALSE); 9896 } 9897 9898 static void 9899 assert_match_common(typval_T *argvars, assert_type_T atype) 9900 { 9901 garray_T ga; 9902 char_u buf1[NUMBUFLEN]; 9903 char_u buf2[NUMBUFLEN]; 9904 char_u *pat = get_tv_string_buf_chk(&argvars[0], buf1); 9905 char_u *text = get_tv_string_buf_chk(&argvars[1], buf2); 9906 9907 if (pat == NULL || text == NULL) 9908 EMSG(_(e_invarg)); 9909 else if (pattern_match(pat, text, FALSE) != (atype == ASSERT_MATCH)) 9910 { 9911 prepare_assert_error(&ga); 9912 fill_assert_error(&ga, &argvars[2], NULL, &argvars[0], &argvars[1], 9913 atype); 9914 assert_error(&ga); 9915 ga_clear(&ga); 9916 } 9917 } 9918 9919 /* 9920 * "assert_match(pattern, actual[, msg])" function 9921 */ 9922 static void 9923 f_assert_match(typval_T *argvars, typval_T *rettv UNUSED) 9924 { 9925 assert_match_common(argvars, ASSERT_MATCH); 9926 } 9927 9928 /* 9929 * "assert_notmatch(pattern, actual[, msg])" function 9930 */ 9931 static void 9932 f_assert_notmatch(typval_T *argvars, typval_T *rettv UNUSED) 9933 { 9934 assert_match_common(argvars, ASSERT_NOTMATCH); 9935 } 9936 9937 /* 9938 * "assert_true(actual[, msg])" function 9939 */ 9940 static void 9941 f_assert_true(typval_T *argvars, typval_T *rettv UNUSED) 9942 { 9943 assert_bool(argvars, TRUE); 9944 } 9945 9946 #ifdef FEAT_FLOAT 9947 /* 9948 * "asin()" function 9949 */ 9950 static void 9951 f_asin(typval_T *argvars, typval_T *rettv) 9952 { 9953 float_T f = 0.0; 9954 9955 rettv->v_type = VAR_FLOAT; 9956 if (get_float_arg(argvars, &f) == OK) 9957 rettv->vval.v_float = asin(f); 9958 else 9959 rettv->vval.v_float = 0.0; 9960 } 9961 9962 /* 9963 * "atan()" function 9964 */ 9965 static void 9966 f_atan(typval_T *argvars, typval_T *rettv) 9967 { 9968 float_T f = 0.0; 9969 9970 rettv->v_type = VAR_FLOAT; 9971 if (get_float_arg(argvars, &f) == OK) 9972 rettv->vval.v_float = atan(f); 9973 else 9974 rettv->vval.v_float = 0.0; 9975 } 9976 9977 /* 9978 * "atan2()" function 9979 */ 9980 static void 9981 f_atan2(typval_T *argvars, typval_T *rettv) 9982 { 9983 float_T fx = 0.0, fy = 0.0; 9984 9985 rettv->v_type = VAR_FLOAT; 9986 if (get_float_arg(argvars, &fx) == OK 9987 && get_float_arg(&argvars[1], &fy) == OK) 9988 rettv->vval.v_float = atan2(fx, fy); 9989 else 9990 rettv->vval.v_float = 0.0; 9991 } 9992 #endif 9993 9994 /* 9995 * "browse(save, title, initdir, default)" function 9996 */ 9997 static void 9998 f_browse(typval_T *argvars UNUSED, typval_T *rettv) 9999 { 10000 #ifdef FEAT_BROWSE 10001 int save; 10002 char_u *title; 10003 char_u *initdir; 10004 char_u *defname; 10005 char_u buf[NUMBUFLEN]; 10006 char_u buf2[NUMBUFLEN]; 10007 int error = FALSE; 10008 10009 save = get_tv_number_chk(&argvars[0], &error); 10010 title = get_tv_string_chk(&argvars[1]); 10011 initdir = get_tv_string_buf_chk(&argvars[2], buf); 10012 defname = get_tv_string_buf_chk(&argvars[3], buf2); 10013 10014 if (error || title == NULL || initdir == NULL || defname == NULL) 10015 rettv->vval.v_string = NULL; 10016 else 10017 rettv->vval.v_string = 10018 do_browse(save ? BROWSE_SAVE : 0, 10019 title, defname, NULL, initdir, NULL, curbuf); 10020 #else 10021 rettv->vval.v_string = NULL; 10022 #endif 10023 rettv->v_type = VAR_STRING; 10024 } 10025 10026 /* 10027 * "browsedir(title, initdir)" function 10028 */ 10029 static void 10030 f_browsedir(typval_T *argvars UNUSED, typval_T *rettv) 10031 { 10032 #ifdef FEAT_BROWSE 10033 char_u *title; 10034 char_u *initdir; 10035 char_u buf[NUMBUFLEN]; 10036 10037 title = get_tv_string_chk(&argvars[0]); 10038 initdir = get_tv_string_buf_chk(&argvars[1], buf); 10039 10040 if (title == NULL || initdir == NULL) 10041 rettv->vval.v_string = NULL; 10042 else 10043 rettv->vval.v_string = do_browse(BROWSE_DIR, 10044 title, NULL, NULL, initdir, NULL, curbuf); 10045 #else 10046 rettv->vval.v_string = NULL; 10047 #endif 10048 rettv->v_type = VAR_STRING; 10049 } 10050 10051 static buf_T *find_buffer(typval_T *avar); 10052 10053 /* 10054 * Find a buffer by number or exact name. 10055 */ 10056 static buf_T * 10057 find_buffer(typval_T *avar) 10058 { 10059 buf_T *buf = NULL; 10060 10061 if (avar->v_type == VAR_NUMBER) 10062 buf = buflist_findnr((int)avar->vval.v_number); 10063 else if (avar->v_type == VAR_STRING && avar->vval.v_string != NULL) 10064 { 10065 buf = buflist_findname_exp(avar->vval.v_string); 10066 if (buf == NULL) 10067 { 10068 /* No full path name match, try a match with a URL or a "nofile" 10069 * buffer, these don't use the full path. */ 10070 for (buf = firstbuf; buf != NULL; buf = buf->b_next) 10071 if (buf->b_fname != NULL 10072 && (path_with_url(buf->b_fname) 10073 #ifdef FEAT_QUICKFIX 10074 || bt_nofile(buf) 10075 #endif 10076 ) 10077 && STRCMP(buf->b_fname, avar->vval.v_string) == 0) 10078 break; 10079 } 10080 } 10081 return buf; 10082 } 10083 10084 /* 10085 * "bufexists(expr)" function 10086 */ 10087 static void 10088 f_bufexists(typval_T *argvars, typval_T *rettv) 10089 { 10090 rettv->vval.v_number = (find_buffer(&argvars[0]) != NULL); 10091 } 10092 10093 /* 10094 * "buflisted(expr)" function 10095 */ 10096 static void 10097 f_buflisted(typval_T *argvars, typval_T *rettv) 10098 { 10099 buf_T *buf; 10100 10101 buf = find_buffer(&argvars[0]); 10102 rettv->vval.v_number = (buf != NULL && buf->b_p_bl); 10103 } 10104 10105 /* 10106 * "bufloaded(expr)" function 10107 */ 10108 static void 10109 f_bufloaded(typval_T *argvars, typval_T *rettv) 10110 { 10111 buf_T *buf; 10112 10113 buf = find_buffer(&argvars[0]); 10114 rettv->vval.v_number = (buf != NULL && buf->b_ml.ml_mfp != NULL); 10115 } 10116 10117 buf_T * 10118 buflist_find_by_name(char_u *name, int curtab_only) 10119 { 10120 int save_magic; 10121 char_u *save_cpo; 10122 buf_T *buf; 10123 10124 /* Ignore 'magic' and 'cpoptions' here to make scripts portable */ 10125 save_magic = p_magic; 10126 p_magic = TRUE; 10127 save_cpo = p_cpo; 10128 p_cpo = (char_u *)""; 10129 10130 buf = buflist_findnr(buflist_findpat(name, name + STRLEN(name), 10131 TRUE, FALSE, curtab_only)); 10132 10133 p_magic = save_magic; 10134 p_cpo = save_cpo; 10135 return buf; 10136 } 10137 10138 /* 10139 * Get buffer by number or pattern. 10140 */ 10141 static buf_T * 10142 get_buf_tv(typval_T *tv, int curtab_only) 10143 { 10144 char_u *name = tv->vval.v_string; 10145 buf_T *buf; 10146 10147 if (tv->v_type == VAR_NUMBER) 10148 return buflist_findnr((int)tv->vval.v_number); 10149 if (tv->v_type != VAR_STRING) 10150 return NULL; 10151 if (name == NULL || *name == NUL) 10152 return curbuf; 10153 if (name[0] == '$' && name[1] == NUL) 10154 return lastbuf; 10155 10156 buf = buflist_find_by_name(name, curtab_only); 10157 10158 /* If not found, try expanding the name, like done for bufexists(). */ 10159 if (buf == NULL) 10160 buf = find_buffer(tv); 10161 10162 return buf; 10163 } 10164 10165 /* 10166 * "bufname(expr)" function 10167 */ 10168 static void 10169 f_bufname(typval_T *argvars, typval_T *rettv) 10170 { 10171 buf_T *buf; 10172 10173 (void)get_tv_number(&argvars[0]); /* issue errmsg if type error */ 10174 ++emsg_off; 10175 buf = get_buf_tv(&argvars[0], FALSE); 10176 rettv->v_type = VAR_STRING; 10177 if (buf != NULL && buf->b_fname != NULL) 10178 rettv->vval.v_string = vim_strsave(buf->b_fname); 10179 else 10180 rettv->vval.v_string = NULL; 10181 --emsg_off; 10182 } 10183 10184 /* 10185 * "bufnr(expr)" function 10186 */ 10187 static void 10188 f_bufnr(typval_T *argvars, typval_T *rettv) 10189 { 10190 buf_T *buf; 10191 int error = FALSE; 10192 char_u *name; 10193 10194 (void)get_tv_number(&argvars[0]); /* issue errmsg if type error */ 10195 ++emsg_off; 10196 buf = get_buf_tv(&argvars[0], FALSE); 10197 --emsg_off; 10198 10199 /* If the buffer isn't found and the second argument is not zero create a 10200 * new buffer. */ 10201 if (buf == NULL 10202 && argvars[1].v_type != VAR_UNKNOWN 10203 && get_tv_number_chk(&argvars[1], &error) != 0 10204 && !error 10205 && (name = get_tv_string_chk(&argvars[0])) != NULL 10206 && !error) 10207 buf = buflist_new(name, NULL, (linenr_T)1, 0); 10208 10209 if (buf != NULL) 10210 rettv->vval.v_number = buf->b_fnum; 10211 else 10212 rettv->vval.v_number = -1; 10213 } 10214 10215 /* 10216 * "bufwinnr(nr)" function 10217 */ 10218 static void 10219 f_bufwinnr(typval_T *argvars, typval_T *rettv) 10220 { 10221 #ifdef FEAT_WINDOWS 10222 win_T *wp; 10223 int winnr = 0; 10224 #endif 10225 buf_T *buf; 10226 10227 (void)get_tv_number(&argvars[0]); /* issue errmsg if type error */ 10228 ++emsg_off; 10229 buf = get_buf_tv(&argvars[0], TRUE); 10230 #ifdef FEAT_WINDOWS 10231 for (wp = firstwin; wp; wp = wp->w_next) 10232 { 10233 ++winnr; 10234 if (wp->w_buffer == buf) 10235 break; 10236 } 10237 rettv->vval.v_number = (wp != NULL ? winnr : -1); 10238 #else 10239 rettv->vval.v_number = (curwin->w_buffer == buf ? 1 : -1); 10240 #endif 10241 --emsg_off; 10242 } 10243 10244 /* 10245 * "byte2line(byte)" function 10246 */ 10247 static void 10248 f_byte2line(typval_T *argvars UNUSED, typval_T *rettv) 10249 { 10250 #ifndef FEAT_BYTEOFF 10251 rettv->vval.v_number = -1; 10252 #else 10253 long boff = 0; 10254 10255 boff = get_tv_number(&argvars[0]) - 1; /* boff gets -1 on type error */ 10256 if (boff < 0) 10257 rettv->vval.v_number = -1; 10258 else 10259 rettv->vval.v_number = ml_find_line_or_offset(curbuf, 10260 (linenr_T)0, &boff); 10261 #endif 10262 } 10263 10264 static void 10265 byteidx(typval_T *argvars, typval_T *rettv, int comp UNUSED) 10266 { 10267 #ifdef FEAT_MBYTE 10268 char_u *t; 10269 #endif 10270 char_u *str; 10271 long idx; 10272 10273 str = get_tv_string_chk(&argvars[0]); 10274 idx = get_tv_number_chk(&argvars[1], NULL); 10275 rettv->vval.v_number = -1; 10276 if (str == NULL || idx < 0) 10277 return; 10278 10279 #ifdef FEAT_MBYTE 10280 t = str; 10281 for ( ; idx > 0; idx--) 10282 { 10283 if (*t == NUL) /* EOL reached */ 10284 return; 10285 if (enc_utf8 && comp) 10286 t += utf_ptr2len(t); 10287 else 10288 t += (*mb_ptr2len)(t); 10289 } 10290 rettv->vval.v_number = (varnumber_T)(t - str); 10291 #else 10292 if ((size_t)idx <= STRLEN(str)) 10293 rettv->vval.v_number = idx; 10294 #endif 10295 } 10296 10297 /* 10298 * "byteidx()" function 10299 */ 10300 static void 10301 f_byteidx(typval_T *argvars, typval_T *rettv) 10302 { 10303 byteidx(argvars, rettv, FALSE); 10304 } 10305 10306 /* 10307 * "byteidxcomp()" function 10308 */ 10309 static void 10310 f_byteidxcomp(typval_T *argvars, typval_T *rettv) 10311 { 10312 byteidx(argvars, rettv, TRUE); 10313 } 10314 10315 int 10316 func_call( 10317 char_u *name, 10318 typval_T *args, 10319 partial_T *partial, 10320 dict_T *selfdict, 10321 typval_T *rettv) 10322 { 10323 listitem_T *item; 10324 typval_T argv[MAX_FUNC_ARGS + 1]; 10325 int argc = 0; 10326 int dummy; 10327 int r = 0; 10328 10329 for (item = args->vval.v_list->lv_first; item != NULL; 10330 item = item->li_next) 10331 { 10332 if (argc == MAX_FUNC_ARGS - (partial == NULL ? 0 : partial->pt_argc)) 10333 { 10334 EMSG(_("E699: Too many arguments")); 10335 break; 10336 } 10337 /* Make a copy of each argument. This is needed to be able to set 10338 * v_lock to VAR_FIXED in the copy without changing the original list. 10339 */ 10340 copy_tv(&item->li_tv, &argv[argc++]); 10341 } 10342 10343 if (item == NULL) 10344 r = call_func(name, (int)STRLEN(name), rettv, argc, argv, 10345 curwin->w_cursor.lnum, curwin->w_cursor.lnum, 10346 &dummy, TRUE, partial, selfdict); 10347 10348 /* Free the arguments. */ 10349 while (argc > 0) 10350 clear_tv(&argv[--argc]); 10351 10352 return r; 10353 } 10354 10355 /* 10356 * "call(func, arglist [, dict])" function 10357 */ 10358 static void 10359 f_call(typval_T *argvars, typval_T *rettv) 10360 { 10361 char_u *func; 10362 partial_T *partial = NULL; 10363 dict_T *selfdict = NULL; 10364 10365 if (argvars[1].v_type != VAR_LIST) 10366 { 10367 EMSG(_(e_listreq)); 10368 return; 10369 } 10370 if (argvars[1].vval.v_list == NULL) 10371 return; 10372 10373 if (argvars[0].v_type == VAR_FUNC) 10374 func = argvars[0].vval.v_string; 10375 else if (argvars[0].v_type == VAR_PARTIAL) 10376 { 10377 partial = argvars[0].vval.v_partial; 10378 func = partial->pt_name; 10379 } 10380 else 10381 func = get_tv_string(&argvars[0]); 10382 if (*func == NUL) 10383 return; /* type error or empty name */ 10384 10385 if (argvars[2].v_type != VAR_UNKNOWN) 10386 { 10387 if (argvars[2].v_type != VAR_DICT) 10388 { 10389 EMSG(_(e_dictreq)); 10390 return; 10391 } 10392 selfdict = argvars[2].vval.v_dict; 10393 } 10394 10395 (void)func_call(func, &argvars[1], partial, selfdict, rettv); 10396 } 10397 10398 #ifdef FEAT_FLOAT 10399 /* 10400 * "ceil({float})" function 10401 */ 10402 static void 10403 f_ceil(typval_T *argvars, typval_T *rettv) 10404 { 10405 float_T f = 0.0; 10406 10407 rettv->v_type = VAR_FLOAT; 10408 if (get_float_arg(argvars, &f) == OK) 10409 rettv->vval.v_float = ceil(f); 10410 else 10411 rettv->vval.v_float = 0.0; 10412 } 10413 #endif 10414 10415 #ifdef FEAT_JOB_CHANNEL 10416 /* 10417 * "ch_close()" function 10418 */ 10419 static void 10420 f_ch_close(typval_T *argvars, typval_T *rettv UNUSED) 10421 { 10422 channel_T *channel = get_channel_arg(&argvars[0], TRUE, FALSE, 0); 10423 10424 if (channel != NULL) 10425 { 10426 channel_close(channel, FALSE); 10427 channel_clear(channel); 10428 } 10429 } 10430 10431 /* 10432 * "ch_getbufnr()" function 10433 */ 10434 static void 10435 f_ch_getbufnr(typval_T *argvars, typval_T *rettv) 10436 { 10437 channel_T *channel = get_channel_arg(&argvars[0], FALSE, FALSE, 0); 10438 10439 rettv->vval.v_number = -1; 10440 if (channel != NULL) 10441 { 10442 char_u *what = get_tv_string(&argvars[1]); 10443 int part; 10444 10445 if (STRCMP(what, "err") == 0) 10446 part = PART_ERR; 10447 else if (STRCMP(what, "out") == 0) 10448 part = PART_OUT; 10449 else if (STRCMP(what, "in") == 0) 10450 part = PART_IN; 10451 else 10452 part = PART_SOCK; 10453 if (channel->ch_part[part].ch_buffer != NULL) 10454 rettv->vval.v_number = channel->ch_part[part].ch_buffer->b_fnum; 10455 } 10456 } 10457 10458 /* 10459 * "ch_getjob()" function 10460 */ 10461 static void 10462 f_ch_getjob(typval_T *argvars, typval_T *rettv) 10463 { 10464 channel_T *channel = get_channel_arg(&argvars[0], FALSE, FALSE, 0); 10465 10466 if (channel != NULL) 10467 { 10468 rettv->v_type = VAR_JOB; 10469 rettv->vval.v_job = channel->ch_job; 10470 if (channel->ch_job != NULL) 10471 ++channel->ch_job->jv_refcount; 10472 } 10473 } 10474 10475 /* 10476 * "ch_info()" function 10477 */ 10478 static void 10479 f_ch_info(typval_T *argvars, typval_T *rettv UNUSED) 10480 { 10481 channel_T *channel = get_channel_arg(&argvars[0], FALSE, FALSE, 0); 10482 10483 if (channel != NULL && rettv_dict_alloc(rettv) != FAIL) 10484 channel_info(channel, rettv->vval.v_dict); 10485 } 10486 10487 /* 10488 * "ch_log()" function 10489 */ 10490 static void 10491 f_ch_log(typval_T *argvars, typval_T *rettv UNUSED) 10492 { 10493 char_u *msg = get_tv_string(&argvars[0]); 10494 channel_T *channel = NULL; 10495 10496 if (argvars[1].v_type != VAR_UNKNOWN) 10497 channel = get_channel_arg(&argvars[1], FALSE, FALSE, 0); 10498 10499 ch_log(channel, (char *)msg); 10500 } 10501 10502 /* 10503 * "ch_logfile()" function 10504 */ 10505 static void 10506 f_ch_logfile(typval_T *argvars, typval_T *rettv UNUSED) 10507 { 10508 char_u *fname; 10509 char_u *opt = (char_u *)""; 10510 char_u buf[NUMBUFLEN]; 10511 10512 fname = get_tv_string(&argvars[0]); 10513 if (argvars[1].v_type == VAR_STRING) 10514 opt = get_tv_string_buf(&argvars[1], buf); 10515 ch_logfile(fname, opt); 10516 } 10517 10518 /* 10519 * "ch_open()" function 10520 */ 10521 static void 10522 f_ch_open(typval_T *argvars, typval_T *rettv) 10523 { 10524 rettv->v_type = VAR_CHANNEL; 10525 if (check_restricted() || check_secure()) 10526 return; 10527 rettv->vval.v_channel = channel_open_func(argvars); 10528 } 10529 10530 /* 10531 * "ch_read()" function 10532 */ 10533 static void 10534 f_ch_read(typval_T *argvars, typval_T *rettv) 10535 { 10536 common_channel_read(argvars, rettv, FALSE); 10537 } 10538 10539 /* 10540 * "ch_readraw()" function 10541 */ 10542 static void 10543 f_ch_readraw(typval_T *argvars, typval_T *rettv) 10544 { 10545 common_channel_read(argvars, rettv, TRUE); 10546 } 10547 10548 /* 10549 * "ch_evalexpr()" function 10550 */ 10551 static void 10552 f_ch_evalexpr(typval_T *argvars, typval_T *rettv) 10553 { 10554 ch_expr_common(argvars, rettv, TRUE); 10555 } 10556 10557 /* 10558 * "ch_sendexpr()" function 10559 */ 10560 static void 10561 f_ch_sendexpr(typval_T *argvars, typval_T *rettv) 10562 { 10563 ch_expr_common(argvars, rettv, FALSE); 10564 } 10565 10566 /* 10567 * "ch_evalraw()" function 10568 */ 10569 static void 10570 f_ch_evalraw(typval_T *argvars, typval_T *rettv) 10571 { 10572 ch_raw_common(argvars, rettv, TRUE); 10573 } 10574 10575 /* 10576 * "ch_sendraw()" function 10577 */ 10578 static void 10579 f_ch_sendraw(typval_T *argvars, typval_T *rettv) 10580 { 10581 ch_raw_common(argvars, rettv, FALSE); 10582 } 10583 10584 /* 10585 * "ch_setoptions()" function 10586 */ 10587 static void 10588 f_ch_setoptions(typval_T *argvars, typval_T *rettv UNUSED) 10589 { 10590 channel_T *channel; 10591 jobopt_T opt; 10592 10593 channel = get_channel_arg(&argvars[0], FALSE, FALSE, 0); 10594 if (channel == NULL) 10595 return; 10596 clear_job_options(&opt); 10597 if (get_job_options(&argvars[1], &opt, 10598 JO_CB_ALL + JO_TIMEOUT_ALL + JO_MODE_ALL) == OK) 10599 channel_set_options(channel, &opt); 10600 free_job_options(&opt); 10601 } 10602 10603 /* 10604 * "ch_status()" function 10605 */ 10606 static void 10607 f_ch_status(typval_T *argvars, typval_T *rettv) 10608 { 10609 channel_T *channel; 10610 10611 /* return an empty string by default */ 10612 rettv->v_type = VAR_STRING; 10613 rettv->vval.v_string = NULL; 10614 10615 channel = get_channel_arg(&argvars[0], FALSE, FALSE, 0); 10616 rettv->vval.v_string = vim_strsave((char_u *)channel_status(channel)); 10617 } 10618 #endif 10619 10620 /* 10621 * "changenr()" function 10622 */ 10623 static void 10624 f_changenr(typval_T *argvars UNUSED, typval_T *rettv) 10625 { 10626 rettv->vval.v_number = curbuf->b_u_seq_cur; 10627 } 10628 10629 /* 10630 * "char2nr(string)" function 10631 */ 10632 static void 10633 f_char2nr(typval_T *argvars, typval_T *rettv) 10634 { 10635 #ifdef FEAT_MBYTE 10636 if (has_mbyte) 10637 { 10638 int utf8 = 0; 10639 10640 if (argvars[1].v_type != VAR_UNKNOWN) 10641 utf8 = get_tv_number_chk(&argvars[1], NULL); 10642 10643 if (utf8) 10644 rettv->vval.v_number = (*utf_ptr2char)(get_tv_string(&argvars[0])); 10645 else 10646 rettv->vval.v_number = (*mb_ptr2char)(get_tv_string(&argvars[0])); 10647 } 10648 else 10649 #endif 10650 rettv->vval.v_number = get_tv_string(&argvars[0])[0]; 10651 } 10652 10653 /* 10654 * "cindent(lnum)" function 10655 */ 10656 static void 10657 f_cindent(typval_T *argvars UNUSED, typval_T *rettv) 10658 { 10659 #ifdef FEAT_CINDENT 10660 pos_T pos; 10661 linenr_T lnum; 10662 10663 pos = curwin->w_cursor; 10664 lnum = get_tv_lnum(argvars); 10665 if (lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count) 10666 { 10667 curwin->w_cursor.lnum = lnum; 10668 rettv->vval.v_number = get_c_indent(); 10669 curwin->w_cursor = pos; 10670 } 10671 else 10672 #endif 10673 rettv->vval.v_number = -1; 10674 } 10675 10676 /* 10677 * "clearmatches()" function 10678 */ 10679 static void 10680 f_clearmatches(typval_T *argvars UNUSED, typval_T *rettv UNUSED) 10681 { 10682 #ifdef FEAT_SEARCH_EXTRA 10683 clear_matches(curwin); 10684 #endif 10685 } 10686 10687 /* 10688 * "col(string)" function 10689 */ 10690 static void 10691 f_col(typval_T *argvars, typval_T *rettv) 10692 { 10693 colnr_T col = 0; 10694 pos_T *fp; 10695 int fnum = curbuf->b_fnum; 10696 10697 fp = var2fpos(&argvars[0], FALSE, &fnum); 10698 if (fp != NULL && fnum == curbuf->b_fnum) 10699 { 10700 if (fp->col == MAXCOL) 10701 { 10702 /* '> can be MAXCOL, get the length of the line then */ 10703 if (fp->lnum <= curbuf->b_ml.ml_line_count) 10704 col = (colnr_T)STRLEN(ml_get(fp->lnum)) + 1; 10705 else 10706 col = MAXCOL; 10707 } 10708 else 10709 { 10710 col = fp->col + 1; 10711 #ifdef FEAT_VIRTUALEDIT 10712 /* col(".") when the cursor is on the NUL at the end of the line 10713 * because of "coladd" can be seen as an extra column. */ 10714 if (virtual_active() && fp == &curwin->w_cursor) 10715 { 10716 char_u *p = ml_get_cursor(); 10717 10718 if (curwin->w_cursor.coladd >= (colnr_T)chartabsize(p, 10719 curwin->w_virtcol - curwin->w_cursor.coladd)) 10720 { 10721 # ifdef FEAT_MBYTE 10722 int l; 10723 10724 if (*p != NUL && p[(l = (*mb_ptr2len)(p))] == NUL) 10725 col += l; 10726 # else 10727 if (*p != NUL && p[1] == NUL) 10728 ++col; 10729 # endif 10730 } 10731 } 10732 #endif 10733 } 10734 } 10735 rettv->vval.v_number = col; 10736 } 10737 10738 #if defined(FEAT_INS_EXPAND) 10739 /* 10740 * "complete()" function 10741 */ 10742 static void 10743 f_complete(typval_T *argvars, typval_T *rettv UNUSED) 10744 { 10745 int startcol; 10746 10747 if ((State & INSERT) == 0) 10748 { 10749 EMSG(_("E785: complete() can only be used in Insert mode")); 10750 return; 10751 } 10752 10753 /* Check for undo allowed here, because if something was already inserted 10754 * the line was already saved for undo and this check isn't done. */ 10755 if (!undo_allowed()) 10756 return; 10757 10758 if (argvars[1].v_type != VAR_LIST || argvars[1].vval.v_list == NULL) 10759 { 10760 EMSG(_(e_invarg)); 10761 return; 10762 } 10763 10764 startcol = get_tv_number_chk(&argvars[0], NULL); 10765 if (startcol <= 0) 10766 return; 10767 10768 set_completion(startcol - 1, argvars[1].vval.v_list); 10769 } 10770 10771 /* 10772 * "complete_add()" function 10773 */ 10774 static void 10775 f_complete_add(typval_T *argvars, typval_T *rettv) 10776 { 10777 rettv->vval.v_number = ins_compl_add_tv(&argvars[0], 0); 10778 } 10779 10780 /* 10781 * "complete_check()" function 10782 */ 10783 static void 10784 f_complete_check(typval_T *argvars UNUSED, typval_T *rettv) 10785 { 10786 int saved = RedrawingDisabled; 10787 10788 RedrawingDisabled = 0; 10789 ins_compl_check_keys(0); 10790 rettv->vval.v_number = compl_interrupted; 10791 RedrawingDisabled = saved; 10792 } 10793 #endif 10794 10795 /* 10796 * "confirm(message, buttons[, default [, type]])" function 10797 */ 10798 static void 10799 f_confirm(typval_T *argvars UNUSED, typval_T *rettv UNUSED) 10800 { 10801 #if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG) 10802 char_u *message; 10803 char_u *buttons = NULL; 10804 char_u buf[NUMBUFLEN]; 10805 char_u buf2[NUMBUFLEN]; 10806 int def = 1; 10807 int type = VIM_GENERIC; 10808 char_u *typestr; 10809 int error = FALSE; 10810 10811 message = get_tv_string_chk(&argvars[0]); 10812 if (message == NULL) 10813 error = TRUE; 10814 if (argvars[1].v_type != VAR_UNKNOWN) 10815 { 10816 buttons = get_tv_string_buf_chk(&argvars[1], buf); 10817 if (buttons == NULL) 10818 error = TRUE; 10819 if (argvars[2].v_type != VAR_UNKNOWN) 10820 { 10821 def = get_tv_number_chk(&argvars[2], &error); 10822 if (argvars[3].v_type != VAR_UNKNOWN) 10823 { 10824 typestr = get_tv_string_buf_chk(&argvars[3], buf2); 10825 if (typestr == NULL) 10826 error = TRUE; 10827 else 10828 { 10829 switch (TOUPPER_ASC(*typestr)) 10830 { 10831 case 'E': type = VIM_ERROR; break; 10832 case 'Q': type = VIM_QUESTION; break; 10833 case 'I': type = VIM_INFO; break; 10834 case 'W': type = VIM_WARNING; break; 10835 case 'G': type = VIM_GENERIC; break; 10836 } 10837 } 10838 } 10839 } 10840 } 10841 10842 if (buttons == NULL || *buttons == NUL) 10843 buttons = (char_u *)_("&Ok"); 10844 10845 if (!error) 10846 rettv->vval.v_number = do_dialog(type, NULL, message, buttons, 10847 def, NULL, FALSE); 10848 #endif 10849 } 10850 10851 /* 10852 * "copy()" function 10853 */ 10854 static void 10855 f_copy(typval_T *argvars, typval_T *rettv) 10856 { 10857 item_copy(&argvars[0], rettv, FALSE, 0); 10858 } 10859 10860 #ifdef FEAT_FLOAT 10861 /* 10862 * "cos()" function 10863 */ 10864 static void 10865 f_cos(typval_T *argvars, typval_T *rettv) 10866 { 10867 float_T f = 0.0; 10868 10869 rettv->v_type = VAR_FLOAT; 10870 if (get_float_arg(argvars, &f) == OK) 10871 rettv->vval.v_float = cos(f); 10872 else 10873 rettv->vval.v_float = 0.0; 10874 } 10875 10876 /* 10877 * "cosh()" function 10878 */ 10879 static void 10880 f_cosh(typval_T *argvars, typval_T *rettv) 10881 { 10882 float_T f = 0.0; 10883 10884 rettv->v_type = VAR_FLOAT; 10885 if (get_float_arg(argvars, &f) == OK) 10886 rettv->vval.v_float = cosh(f); 10887 else 10888 rettv->vval.v_float = 0.0; 10889 } 10890 #endif 10891 10892 /* 10893 * "count()" function 10894 */ 10895 static void 10896 f_count(typval_T *argvars, typval_T *rettv) 10897 { 10898 long n = 0; 10899 int ic = FALSE; 10900 10901 if (argvars[0].v_type == VAR_LIST) 10902 { 10903 listitem_T *li; 10904 list_T *l; 10905 long idx; 10906 10907 if ((l = argvars[0].vval.v_list) != NULL) 10908 { 10909 li = l->lv_first; 10910 if (argvars[2].v_type != VAR_UNKNOWN) 10911 { 10912 int error = FALSE; 10913 10914 ic = get_tv_number_chk(&argvars[2], &error); 10915 if (argvars[3].v_type != VAR_UNKNOWN) 10916 { 10917 idx = get_tv_number_chk(&argvars[3], &error); 10918 if (!error) 10919 { 10920 li = list_find(l, idx); 10921 if (li == NULL) 10922 EMSGN(_(e_listidx), idx); 10923 } 10924 } 10925 if (error) 10926 li = NULL; 10927 } 10928 10929 for ( ; li != NULL; li = li->li_next) 10930 if (tv_equal(&li->li_tv, &argvars[1], ic, FALSE)) 10931 ++n; 10932 } 10933 } 10934 else if (argvars[0].v_type == VAR_DICT) 10935 { 10936 int todo; 10937 dict_T *d; 10938 hashitem_T *hi; 10939 10940 if ((d = argvars[0].vval.v_dict) != NULL) 10941 { 10942 int error = FALSE; 10943 10944 if (argvars[2].v_type != VAR_UNKNOWN) 10945 { 10946 ic = get_tv_number_chk(&argvars[2], &error); 10947 if (argvars[3].v_type != VAR_UNKNOWN) 10948 EMSG(_(e_invarg)); 10949 } 10950 10951 todo = error ? 0 : (int)d->dv_hashtab.ht_used; 10952 for (hi = d->dv_hashtab.ht_array; todo > 0; ++hi) 10953 { 10954 if (!HASHITEM_EMPTY(hi)) 10955 { 10956 --todo; 10957 if (tv_equal(&HI2DI(hi)->di_tv, &argvars[1], ic, FALSE)) 10958 ++n; 10959 } 10960 } 10961 } 10962 } 10963 else 10964 EMSG2(_(e_listdictarg), "count()"); 10965 rettv->vval.v_number = n; 10966 } 10967 10968 /* 10969 * "cscope_connection([{num} , {dbpath} [, {prepend}]])" function 10970 * 10971 * Checks the existence of a cscope connection. 10972 */ 10973 static void 10974 f_cscope_connection(typval_T *argvars UNUSED, typval_T *rettv UNUSED) 10975 { 10976 #ifdef FEAT_CSCOPE 10977 int num = 0; 10978 char_u *dbpath = NULL; 10979 char_u *prepend = NULL; 10980 char_u buf[NUMBUFLEN]; 10981 10982 if (argvars[0].v_type != VAR_UNKNOWN 10983 && argvars[1].v_type != VAR_UNKNOWN) 10984 { 10985 num = (int)get_tv_number(&argvars[0]); 10986 dbpath = get_tv_string(&argvars[1]); 10987 if (argvars[2].v_type != VAR_UNKNOWN) 10988 prepend = get_tv_string_buf(&argvars[2], buf); 10989 } 10990 10991 rettv->vval.v_number = cs_connection(num, dbpath, prepend); 10992 #endif 10993 } 10994 10995 /* 10996 * "cursor(lnum, col)" function, or 10997 * "cursor(list)" 10998 * 10999 * Moves the cursor to the specified line and column. 11000 * Returns 0 when the position could be set, -1 otherwise. 11001 */ 11002 static void 11003 f_cursor(typval_T *argvars, typval_T *rettv) 11004 { 11005 long line, col; 11006 #ifdef FEAT_VIRTUALEDIT 11007 long coladd = 0; 11008 #endif 11009 int set_curswant = TRUE; 11010 11011 rettv->vval.v_number = -1; 11012 if (argvars[1].v_type == VAR_UNKNOWN) 11013 { 11014 pos_T pos; 11015 colnr_T curswant = -1; 11016 11017 if (list2fpos(argvars, &pos, NULL, &curswant) == FAIL) 11018 { 11019 EMSG(_(e_invarg)); 11020 return; 11021 } 11022 line = pos.lnum; 11023 col = pos.col; 11024 #ifdef FEAT_VIRTUALEDIT 11025 coladd = pos.coladd; 11026 #endif 11027 if (curswant >= 0) 11028 { 11029 curwin->w_curswant = curswant - 1; 11030 set_curswant = FALSE; 11031 } 11032 } 11033 else 11034 { 11035 line = get_tv_lnum(argvars); 11036 col = get_tv_number_chk(&argvars[1], NULL); 11037 #ifdef FEAT_VIRTUALEDIT 11038 if (argvars[2].v_type != VAR_UNKNOWN) 11039 coladd = get_tv_number_chk(&argvars[2], NULL); 11040 #endif 11041 } 11042 if (line < 0 || col < 0 11043 #ifdef FEAT_VIRTUALEDIT 11044 || coladd < 0 11045 #endif 11046 ) 11047 return; /* type error; errmsg already given */ 11048 if (line > 0) 11049 curwin->w_cursor.lnum = line; 11050 if (col > 0) 11051 curwin->w_cursor.col = col - 1; 11052 #ifdef FEAT_VIRTUALEDIT 11053 curwin->w_cursor.coladd = coladd; 11054 #endif 11055 11056 /* Make sure the cursor is in a valid position. */ 11057 check_cursor(); 11058 #ifdef FEAT_MBYTE 11059 /* Correct cursor for multi-byte character. */ 11060 if (has_mbyte) 11061 mb_adjust_cursor(); 11062 #endif 11063 11064 curwin->w_set_curswant = set_curswant; 11065 rettv->vval.v_number = 0; 11066 } 11067 11068 /* 11069 * "deepcopy()" function 11070 */ 11071 static void 11072 f_deepcopy(typval_T *argvars, typval_T *rettv) 11073 { 11074 int noref = 0; 11075 11076 if (argvars[1].v_type != VAR_UNKNOWN) 11077 noref = get_tv_number_chk(&argvars[1], NULL); 11078 if (noref < 0 || noref > 1) 11079 EMSG(_(e_invarg)); 11080 else 11081 { 11082 current_copyID += COPYID_INC; 11083 item_copy(&argvars[0], rettv, TRUE, noref == 0 ? current_copyID : 0); 11084 } 11085 } 11086 11087 /* 11088 * "delete()" function 11089 */ 11090 static void 11091 f_delete(typval_T *argvars, typval_T *rettv) 11092 { 11093 char_u nbuf[NUMBUFLEN]; 11094 char_u *name; 11095 char_u *flags; 11096 11097 rettv->vval.v_number = -1; 11098 if (check_restricted() || check_secure()) 11099 return; 11100 11101 name = get_tv_string(&argvars[0]); 11102 if (name == NULL || *name == NUL) 11103 { 11104 EMSG(_(e_invarg)); 11105 return; 11106 } 11107 11108 if (argvars[1].v_type != VAR_UNKNOWN) 11109 flags = get_tv_string_buf(&argvars[1], nbuf); 11110 else 11111 flags = (char_u *)""; 11112 11113 if (*flags == NUL) 11114 /* delete a file */ 11115 rettv->vval.v_number = mch_remove(name) == 0 ? 0 : -1; 11116 else if (STRCMP(flags, "d") == 0) 11117 /* delete an empty directory */ 11118 rettv->vval.v_number = mch_rmdir(name) == 0 ? 0 : -1; 11119 else if (STRCMP(flags, "rf") == 0) 11120 /* delete a directory recursively */ 11121 rettv->vval.v_number = delete_recursive(name); 11122 else 11123 EMSG2(_(e_invexpr2), flags); 11124 } 11125 11126 /* 11127 * "did_filetype()" function 11128 */ 11129 static void 11130 f_did_filetype(typval_T *argvars UNUSED, typval_T *rettv UNUSED) 11131 { 11132 #ifdef FEAT_AUTOCMD 11133 rettv->vval.v_number = did_filetype; 11134 #endif 11135 } 11136 11137 /* 11138 * "diff_filler()" function 11139 */ 11140 static void 11141 f_diff_filler(typval_T *argvars UNUSED, typval_T *rettv UNUSED) 11142 { 11143 #ifdef FEAT_DIFF 11144 rettv->vval.v_number = diff_check_fill(curwin, get_tv_lnum(argvars)); 11145 #endif 11146 } 11147 11148 /* 11149 * "diff_hlID()" function 11150 */ 11151 static void 11152 f_diff_hlID(typval_T *argvars UNUSED, typval_T *rettv UNUSED) 11153 { 11154 #ifdef FEAT_DIFF 11155 linenr_T lnum = get_tv_lnum(argvars); 11156 static linenr_T prev_lnum = 0; 11157 static int changedtick = 0; 11158 static int fnum = 0; 11159 static int change_start = 0; 11160 static int change_end = 0; 11161 static hlf_T hlID = (hlf_T)0; 11162 int filler_lines; 11163 int col; 11164 11165 if (lnum < 0) /* ignore type error in {lnum} arg */ 11166 lnum = 0; 11167 if (lnum != prev_lnum 11168 || changedtick != curbuf->b_changedtick 11169 || fnum != curbuf->b_fnum) 11170 { 11171 /* New line, buffer, change: need to get the values. */ 11172 filler_lines = diff_check(curwin, lnum); 11173 if (filler_lines < 0) 11174 { 11175 if (filler_lines == -1) 11176 { 11177 change_start = MAXCOL; 11178 change_end = -1; 11179 if (diff_find_change(curwin, lnum, &change_start, &change_end)) 11180 hlID = HLF_ADD; /* added line */ 11181 else 11182 hlID = HLF_CHD; /* changed line */ 11183 } 11184 else 11185 hlID = HLF_ADD; /* added line */ 11186 } 11187 else 11188 hlID = (hlf_T)0; 11189 prev_lnum = lnum; 11190 changedtick = curbuf->b_changedtick; 11191 fnum = curbuf->b_fnum; 11192 } 11193 11194 if (hlID == HLF_CHD || hlID == HLF_TXD) 11195 { 11196 col = get_tv_number(&argvars[1]) - 1; /* ignore type error in {col} */ 11197 if (col >= change_start && col <= change_end) 11198 hlID = HLF_TXD; /* changed text */ 11199 else 11200 hlID = HLF_CHD; /* changed line */ 11201 } 11202 rettv->vval.v_number = hlID == (hlf_T)0 ? 0 : (int)hlID; 11203 #endif 11204 } 11205 11206 /* 11207 * "empty({expr})" function 11208 */ 11209 static void 11210 f_empty(typval_T *argvars, typval_T *rettv) 11211 { 11212 int n = FALSE; 11213 11214 switch (argvars[0].v_type) 11215 { 11216 case VAR_STRING: 11217 case VAR_FUNC: 11218 n = argvars[0].vval.v_string == NULL 11219 || *argvars[0].vval.v_string == NUL; 11220 break; 11221 case VAR_PARTIAL: 11222 n = FALSE; 11223 break; 11224 case VAR_NUMBER: 11225 n = argvars[0].vval.v_number == 0; 11226 break; 11227 case VAR_FLOAT: 11228 #ifdef FEAT_FLOAT 11229 n = argvars[0].vval.v_float == 0.0; 11230 break; 11231 #endif 11232 case VAR_LIST: 11233 n = argvars[0].vval.v_list == NULL 11234 || argvars[0].vval.v_list->lv_first == NULL; 11235 break; 11236 case VAR_DICT: 11237 n = argvars[0].vval.v_dict == NULL 11238 || argvars[0].vval.v_dict->dv_hashtab.ht_used == 0; 11239 break; 11240 case VAR_SPECIAL: 11241 n = argvars[0].vval.v_number != VVAL_TRUE; 11242 break; 11243 11244 case VAR_JOB: 11245 #ifdef FEAT_JOB_CHANNEL 11246 n = argvars[0].vval.v_job == NULL 11247 || argvars[0].vval.v_job->jv_status != JOB_STARTED; 11248 break; 11249 #endif 11250 case VAR_CHANNEL: 11251 #ifdef FEAT_JOB_CHANNEL 11252 n = argvars[0].vval.v_channel == NULL 11253 || !channel_is_open(argvars[0].vval.v_channel); 11254 break; 11255 #endif 11256 case VAR_UNKNOWN: 11257 EMSG2(_(e_intern2), "f_empty(UNKNOWN)"); 11258 n = TRUE; 11259 break; 11260 } 11261 11262 rettv->vval.v_number = n; 11263 } 11264 11265 /* 11266 * "escape({string}, {chars})" function 11267 */ 11268 static void 11269 f_escape(typval_T *argvars, typval_T *rettv) 11270 { 11271 char_u buf[NUMBUFLEN]; 11272 11273 rettv->vval.v_string = vim_strsave_escaped(get_tv_string(&argvars[0]), 11274 get_tv_string_buf(&argvars[1], buf)); 11275 rettv->v_type = VAR_STRING; 11276 } 11277 11278 /* 11279 * "eval()" function 11280 */ 11281 static void 11282 f_eval(typval_T *argvars, typval_T *rettv) 11283 { 11284 char_u *s, *p; 11285 11286 s = get_tv_string_chk(&argvars[0]); 11287 if (s != NULL) 11288 s = skipwhite(s); 11289 11290 p = s; 11291 if (s == NULL || eval1(&s, rettv, TRUE) == FAIL) 11292 { 11293 if (p != NULL && !aborting()) 11294 EMSG2(_(e_invexpr2), p); 11295 need_clr_eos = FALSE; 11296 rettv->v_type = VAR_NUMBER; 11297 rettv->vval.v_number = 0; 11298 } 11299 else if (*s != NUL) 11300 EMSG(_(e_trailing)); 11301 } 11302 11303 /* 11304 * "eventhandler()" function 11305 */ 11306 static void 11307 f_eventhandler(typval_T *argvars UNUSED, typval_T *rettv) 11308 { 11309 rettv->vval.v_number = vgetc_busy; 11310 } 11311 11312 /* 11313 * "executable()" function 11314 */ 11315 static void 11316 f_executable(typval_T *argvars, typval_T *rettv) 11317 { 11318 char_u *name = get_tv_string(&argvars[0]); 11319 11320 /* Check in $PATH and also check directly if there is a directory name. */ 11321 rettv->vval.v_number = mch_can_exe(name, NULL, TRUE) 11322 || (gettail(name) != name && mch_can_exe(name, NULL, FALSE)); 11323 } 11324 11325 /* 11326 * "exepath()" function 11327 */ 11328 static void 11329 f_exepath(typval_T *argvars, typval_T *rettv) 11330 { 11331 char_u *p = NULL; 11332 11333 (void)mch_can_exe(get_tv_string(&argvars[0]), &p, TRUE); 11334 rettv->v_type = VAR_STRING; 11335 rettv->vval.v_string = p; 11336 } 11337 11338 /* 11339 * "exists()" function 11340 */ 11341 static void 11342 f_exists(typval_T *argvars, typval_T *rettv) 11343 { 11344 char_u *p; 11345 char_u *name; 11346 int n = FALSE; 11347 int len = 0; 11348 11349 p = get_tv_string(&argvars[0]); 11350 if (*p == '$') /* environment variable */ 11351 { 11352 /* first try "normal" environment variables (fast) */ 11353 if (mch_getenv(p + 1) != NULL) 11354 n = TRUE; 11355 else 11356 { 11357 /* try expanding things like $VIM and ${HOME} */ 11358 p = expand_env_save(p); 11359 if (p != NULL && *p != '$') 11360 n = TRUE; 11361 vim_free(p); 11362 } 11363 } 11364 else if (*p == '&' || *p == '+') /* option */ 11365 { 11366 n = (get_option_tv(&p, NULL, TRUE) == OK); 11367 if (*skipwhite(p) != NUL) 11368 n = FALSE; /* trailing garbage */ 11369 } 11370 else if (*p == '*') /* internal or user defined function */ 11371 { 11372 n = function_exists(p + 1); 11373 } 11374 else if (*p == ':') 11375 { 11376 n = cmd_exists(p + 1); 11377 } 11378 else if (*p == '#') 11379 { 11380 #ifdef FEAT_AUTOCMD 11381 if (p[1] == '#') 11382 n = autocmd_supported(p + 2); 11383 else 11384 n = au_exists(p + 1); 11385 #endif 11386 } 11387 else /* internal variable */ 11388 { 11389 char_u *tofree; 11390 typval_T tv; 11391 11392 /* get_name_len() takes care of expanding curly braces */ 11393 name = p; 11394 len = get_name_len(&p, &tofree, TRUE, FALSE); 11395 if (len > 0) 11396 { 11397 if (tofree != NULL) 11398 name = tofree; 11399 n = (get_var_tv(name, len, &tv, NULL, FALSE, TRUE) == OK); 11400 if (n) 11401 { 11402 /* handle d.key, l[idx], f(expr) */ 11403 n = (handle_subscript(&p, &tv, TRUE, FALSE) == OK); 11404 if (n) 11405 clear_tv(&tv); 11406 } 11407 } 11408 if (*p != NUL) 11409 n = FALSE; 11410 11411 vim_free(tofree); 11412 } 11413 11414 rettv->vval.v_number = n; 11415 } 11416 11417 #ifdef FEAT_FLOAT 11418 /* 11419 * "exp()" function 11420 */ 11421 static void 11422 f_exp(typval_T *argvars, typval_T *rettv) 11423 { 11424 float_T f = 0.0; 11425 11426 rettv->v_type = VAR_FLOAT; 11427 if (get_float_arg(argvars, &f) == OK) 11428 rettv->vval.v_float = exp(f); 11429 else 11430 rettv->vval.v_float = 0.0; 11431 } 11432 #endif 11433 11434 /* 11435 * "expand()" function 11436 */ 11437 static void 11438 f_expand(typval_T *argvars, typval_T *rettv) 11439 { 11440 char_u *s; 11441 int len; 11442 char_u *errormsg; 11443 int options = WILD_SILENT|WILD_USE_NL|WILD_LIST_NOTFOUND; 11444 expand_T xpc; 11445 int error = FALSE; 11446 char_u *result; 11447 11448 rettv->v_type = VAR_STRING; 11449 if (argvars[1].v_type != VAR_UNKNOWN 11450 && argvars[2].v_type != VAR_UNKNOWN 11451 && get_tv_number_chk(&argvars[2], &error) 11452 && !error) 11453 { 11454 rettv->v_type = VAR_LIST; 11455 rettv->vval.v_list = NULL; 11456 } 11457 11458 s = get_tv_string(&argvars[0]); 11459 if (*s == '%' || *s == '#' || *s == '<') 11460 { 11461 ++emsg_off; 11462 result = eval_vars(s, s, &len, NULL, &errormsg, NULL); 11463 --emsg_off; 11464 if (rettv->v_type == VAR_LIST) 11465 { 11466 if (rettv_list_alloc(rettv) != FAIL && result != NULL) 11467 list_append_string(rettv->vval.v_list, result, -1); 11468 else 11469 vim_free(result); 11470 } 11471 else 11472 rettv->vval.v_string = result; 11473 } 11474 else 11475 { 11476 /* When the optional second argument is non-zero, don't remove matches 11477 * for 'wildignore' and don't put matches for 'suffixes' at the end. */ 11478 if (argvars[1].v_type != VAR_UNKNOWN 11479 && get_tv_number_chk(&argvars[1], &error)) 11480 options |= WILD_KEEP_ALL; 11481 if (!error) 11482 { 11483 ExpandInit(&xpc); 11484 xpc.xp_context = EXPAND_FILES; 11485 if (p_wic) 11486 options += WILD_ICASE; 11487 if (rettv->v_type == VAR_STRING) 11488 rettv->vval.v_string = ExpandOne(&xpc, s, NULL, 11489 options, WILD_ALL); 11490 else if (rettv_list_alloc(rettv) != FAIL) 11491 { 11492 int i; 11493 11494 ExpandOne(&xpc, s, NULL, options, WILD_ALL_KEEP); 11495 for (i = 0; i < xpc.xp_numfiles; i++) 11496 list_append_string(rettv->vval.v_list, xpc.xp_files[i], -1); 11497 ExpandCleanup(&xpc); 11498 } 11499 } 11500 else 11501 rettv->vval.v_string = NULL; 11502 } 11503 } 11504 11505 /* 11506 * Go over all entries in "d2" and add them to "d1". 11507 * When "action" is "error" then a duplicate key is an error. 11508 * When "action" is "force" then a duplicate key is overwritten. 11509 * Otherwise duplicate keys are ignored ("action" is "keep"). 11510 */ 11511 void 11512 dict_extend(dict_T *d1, dict_T *d2, char_u *action) 11513 { 11514 dictitem_T *di1; 11515 hashitem_T *hi2; 11516 int todo; 11517 char_u *arg_errmsg = (char_u *)N_("extend() argument"); 11518 11519 todo = (int)d2->dv_hashtab.ht_used; 11520 for (hi2 = d2->dv_hashtab.ht_array; todo > 0; ++hi2) 11521 { 11522 if (!HASHITEM_EMPTY(hi2)) 11523 { 11524 --todo; 11525 di1 = dict_find(d1, hi2->hi_key, -1); 11526 if (d1->dv_scope != 0) 11527 { 11528 /* Disallow replacing a builtin function in l: and g:. 11529 * Check the key to be valid when adding to any 11530 * scope. */ 11531 if (d1->dv_scope == VAR_DEF_SCOPE 11532 && HI2DI(hi2)->di_tv.v_type == VAR_FUNC 11533 && var_check_func_name(hi2->hi_key, 11534 di1 == NULL)) 11535 break; 11536 if (!valid_varname(hi2->hi_key)) 11537 break; 11538 } 11539 if (di1 == NULL) 11540 { 11541 di1 = dictitem_copy(HI2DI(hi2)); 11542 if (di1 != NULL && dict_add(d1, di1) == FAIL) 11543 dictitem_free(di1); 11544 } 11545 else if (*action == 'e') 11546 { 11547 EMSG2(_("E737: Key already exists: %s"), hi2->hi_key); 11548 break; 11549 } 11550 else if (*action == 'f' && HI2DI(hi2) != di1) 11551 { 11552 if (tv_check_lock(di1->di_tv.v_lock, arg_errmsg, TRUE) 11553 || var_check_ro(di1->di_flags, arg_errmsg, TRUE)) 11554 break; 11555 clear_tv(&di1->di_tv); 11556 copy_tv(&HI2DI(hi2)->di_tv, &di1->di_tv); 11557 } 11558 } 11559 } 11560 } 11561 11562 /* 11563 * "extend(list, list [, idx])" function 11564 * "extend(dict, dict [, action])" function 11565 */ 11566 static void 11567 f_extend(typval_T *argvars, typval_T *rettv) 11568 { 11569 char_u *arg_errmsg = (char_u *)N_("extend() argument"); 11570 11571 if (argvars[0].v_type == VAR_LIST && argvars[1].v_type == VAR_LIST) 11572 { 11573 list_T *l1, *l2; 11574 listitem_T *item; 11575 long before; 11576 int error = FALSE; 11577 11578 l1 = argvars[0].vval.v_list; 11579 l2 = argvars[1].vval.v_list; 11580 if (l1 != NULL && !tv_check_lock(l1->lv_lock, arg_errmsg, TRUE) 11581 && l2 != NULL) 11582 { 11583 if (argvars[2].v_type != VAR_UNKNOWN) 11584 { 11585 before = get_tv_number_chk(&argvars[2], &error); 11586 if (error) 11587 return; /* type error; errmsg already given */ 11588 11589 if (before == l1->lv_len) 11590 item = NULL; 11591 else 11592 { 11593 item = list_find(l1, before); 11594 if (item == NULL) 11595 { 11596 EMSGN(_(e_listidx), before); 11597 return; 11598 } 11599 } 11600 } 11601 else 11602 item = NULL; 11603 list_extend(l1, l2, item); 11604 11605 copy_tv(&argvars[0], rettv); 11606 } 11607 } 11608 else if (argvars[0].v_type == VAR_DICT && argvars[1].v_type == VAR_DICT) 11609 { 11610 dict_T *d1, *d2; 11611 char_u *action; 11612 int i; 11613 11614 d1 = argvars[0].vval.v_dict; 11615 d2 = argvars[1].vval.v_dict; 11616 if (d1 != NULL && !tv_check_lock(d1->dv_lock, arg_errmsg, TRUE) 11617 && d2 != NULL) 11618 { 11619 /* Check the third argument. */ 11620 if (argvars[2].v_type != VAR_UNKNOWN) 11621 { 11622 static char *(av[]) = {"keep", "force", "error"}; 11623 11624 action = get_tv_string_chk(&argvars[2]); 11625 if (action == NULL) 11626 return; /* type error; errmsg already given */ 11627 for (i = 0; i < 3; ++i) 11628 if (STRCMP(action, av[i]) == 0) 11629 break; 11630 if (i == 3) 11631 { 11632 EMSG2(_(e_invarg2), action); 11633 return; 11634 } 11635 } 11636 else 11637 action = (char_u *)"force"; 11638 11639 dict_extend(d1, d2, action); 11640 11641 copy_tv(&argvars[0], rettv); 11642 } 11643 } 11644 else 11645 EMSG2(_(e_listdictarg), "extend()"); 11646 } 11647 11648 /* 11649 * "feedkeys()" function 11650 */ 11651 static void 11652 f_feedkeys(typval_T *argvars, typval_T *rettv UNUSED) 11653 { 11654 int remap = TRUE; 11655 int insert = FALSE; 11656 char_u *keys, *flags; 11657 char_u nbuf[NUMBUFLEN]; 11658 int typed = FALSE; 11659 int execute = FALSE; 11660 int dangerous = FALSE; 11661 char_u *keys_esc; 11662 11663 /* This is not allowed in the sandbox. If the commands would still be 11664 * executed in the sandbox it would be OK, but it probably happens later, 11665 * when "sandbox" is no longer set. */ 11666 if (check_secure()) 11667 return; 11668 11669 keys = get_tv_string(&argvars[0]); 11670 11671 if (argvars[1].v_type != VAR_UNKNOWN) 11672 { 11673 flags = get_tv_string_buf(&argvars[1], nbuf); 11674 for ( ; *flags != NUL; ++flags) 11675 { 11676 switch (*flags) 11677 { 11678 case 'n': remap = FALSE; break; 11679 case 'm': remap = TRUE; break; 11680 case 't': typed = TRUE; break; 11681 case 'i': insert = TRUE; break; 11682 case 'x': execute = TRUE; break; 11683 case '!': dangerous = TRUE; break; 11684 } 11685 } 11686 } 11687 11688 if (*keys != NUL || execute) 11689 { 11690 /* Need to escape K_SPECIAL and CSI before putting the string in the 11691 * typeahead buffer. */ 11692 keys_esc = vim_strsave_escape_csi(keys); 11693 if (keys_esc != NULL) 11694 { 11695 ins_typebuf(keys_esc, (remap ? REMAP_YES : REMAP_NONE), 11696 insert ? 0 : typebuf.tb_len, !typed, FALSE); 11697 vim_free(keys_esc); 11698 if (vgetc_busy) 11699 typebuf_was_filled = TRUE; 11700 if (execute) 11701 { 11702 int save_msg_scroll = msg_scroll; 11703 11704 /* Avoid a 1 second delay when the keys start Insert mode. */ 11705 msg_scroll = FALSE; 11706 11707 if (!dangerous) 11708 ++ex_normal_busy; 11709 exec_normal(TRUE); 11710 if (!dangerous) 11711 --ex_normal_busy; 11712 msg_scroll |= save_msg_scroll; 11713 } 11714 } 11715 } 11716 } 11717 11718 /* 11719 * "filereadable()" function 11720 */ 11721 static void 11722 f_filereadable(typval_T *argvars, typval_T *rettv) 11723 { 11724 int fd; 11725 char_u *p; 11726 int n; 11727 11728 #ifndef O_NONBLOCK 11729 # define O_NONBLOCK 0 11730 #endif 11731 p = get_tv_string(&argvars[0]); 11732 if (*p && !mch_isdir(p) && (fd = mch_open((char *)p, 11733 O_RDONLY | O_NONBLOCK, 0)) >= 0) 11734 { 11735 n = TRUE; 11736 close(fd); 11737 } 11738 else 11739 n = FALSE; 11740 11741 rettv->vval.v_number = n; 11742 } 11743 11744 /* 11745 * Return 0 for not writable, 1 for writable file, 2 for a dir which we have 11746 * rights to write into. 11747 */ 11748 static void 11749 f_filewritable(typval_T *argvars, typval_T *rettv) 11750 { 11751 rettv->vval.v_number = filewritable(get_tv_string(&argvars[0])); 11752 } 11753 11754 static void 11755 findfilendir( 11756 typval_T *argvars UNUSED, 11757 typval_T *rettv, 11758 int find_what UNUSED) 11759 { 11760 #ifdef FEAT_SEARCHPATH 11761 char_u *fname; 11762 char_u *fresult = NULL; 11763 char_u *path = *curbuf->b_p_path == NUL ? p_path : curbuf->b_p_path; 11764 char_u *p; 11765 char_u pathbuf[NUMBUFLEN]; 11766 int count = 1; 11767 int first = TRUE; 11768 int error = FALSE; 11769 #endif 11770 11771 rettv->vval.v_string = NULL; 11772 rettv->v_type = VAR_STRING; 11773 11774 #ifdef FEAT_SEARCHPATH 11775 fname = get_tv_string(&argvars[0]); 11776 11777 if (argvars[1].v_type != VAR_UNKNOWN) 11778 { 11779 p = get_tv_string_buf_chk(&argvars[1], pathbuf); 11780 if (p == NULL) 11781 error = TRUE; 11782 else 11783 { 11784 if (*p != NUL) 11785 path = p; 11786 11787 if (argvars[2].v_type != VAR_UNKNOWN) 11788 count = get_tv_number_chk(&argvars[2], &error); 11789 } 11790 } 11791 11792 if (count < 0 && rettv_list_alloc(rettv) == FAIL) 11793 error = TRUE; 11794 11795 if (*fname != NUL && !error) 11796 { 11797 do 11798 { 11799 if (rettv->v_type == VAR_STRING || rettv->v_type == VAR_LIST) 11800 vim_free(fresult); 11801 fresult = find_file_in_path_option(first ? fname : NULL, 11802 first ? (int)STRLEN(fname) : 0, 11803 0, first, path, 11804 find_what, 11805 curbuf->b_ffname, 11806 find_what == FINDFILE_DIR 11807 ? (char_u *)"" : curbuf->b_p_sua); 11808 first = FALSE; 11809 11810 if (fresult != NULL && rettv->v_type == VAR_LIST) 11811 list_append_string(rettv->vval.v_list, fresult, -1); 11812 11813 } while ((rettv->v_type == VAR_LIST || --count > 0) && fresult != NULL); 11814 } 11815 11816 if (rettv->v_type == VAR_STRING) 11817 rettv->vval.v_string = fresult; 11818 #endif 11819 } 11820 11821 static void filter_map(typval_T *argvars, typval_T *rettv, int map); 11822 static int filter_map_one(typval_T *tv, char_u *expr, int map, int *remp); 11823 11824 /* 11825 * Implementation of map() and filter(). 11826 */ 11827 static void 11828 filter_map(typval_T *argvars, typval_T *rettv, int map) 11829 { 11830 char_u buf[NUMBUFLEN]; 11831 char_u *expr; 11832 listitem_T *li, *nli; 11833 list_T *l = NULL; 11834 dictitem_T *di; 11835 hashtab_T *ht; 11836 hashitem_T *hi; 11837 dict_T *d = NULL; 11838 typval_T save_val; 11839 typval_T save_key; 11840 int rem; 11841 int todo; 11842 char_u *ermsg = (char_u *)(map ? "map()" : "filter()"); 11843 char_u *arg_errmsg = (char_u *)(map ? N_("map() argument") 11844 : N_("filter() argument")); 11845 int save_did_emsg; 11846 int idx = 0; 11847 11848 if (argvars[0].v_type == VAR_LIST) 11849 { 11850 if ((l = argvars[0].vval.v_list) == NULL 11851 || (!map && tv_check_lock(l->lv_lock, arg_errmsg, TRUE))) 11852 return; 11853 } 11854 else if (argvars[0].v_type == VAR_DICT) 11855 { 11856 if ((d = argvars[0].vval.v_dict) == NULL 11857 || (!map && tv_check_lock(d->dv_lock, arg_errmsg, TRUE))) 11858 return; 11859 } 11860 else 11861 { 11862 EMSG2(_(e_listdictarg), ermsg); 11863 return; 11864 } 11865 11866 expr = get_tv_string_buf_chk(&argvars[1], buf); 11867 /* On type errors, the preceding call has already displayed an error 11868 * message. Avoid a misleading error message for an empty string that 11869 * was not passed as argument. */ 11870 if (expr != NULL) 11871 { 11872 prepare_vimvar(VV_VAL, &save_val); 11873 expr = skipwhite(expr); 11874 11875 /* We reset "did_emsg" to be able to detect whether an error 11876 * occurred during evaluation of the expression. */ 11877 save_did_emsg = did_emsg; 11878 did_emsg = FALSE; 11879 11880 prepare_vimvar(VV_KEY, &save_key); 11881 if (argvars[0].v_type == VAR_DICT) 11882 { 11883 vimvars[VV_KEY].vv_type = VAR_STRING; 11884 11885 ht = &d->dv_hashtab; 11886 hash_lock(ht); 11887 todo = (int)ht->ht_used; 11888 for (hi = ht->ht_array; todo > 0; ++hi) 11889 { 11890 if (!HASHITEM_EMPTY(hi)) 11891 { 11892 int r; 11893 11894 --todo; 11895 di = HI2DI(hi); 11896 if (map && 11897 (tv_check_lock(di->di_tv.v_lock, arg_errmsg, TRUE) 11898 || var_check_ro(di->di_flags, arg_errmsg, TRUE))) 11899 break; 11900 vimvars[VV_KEY].vv_str = vim_strsave(di->di_key); 11901 r = filter_map_one(&di->di_tv, expr, map, &rem); 11902 clear_tv(&vimvars[VV_KEY].vv_tv); 11903 if (r == FAIL || did_emsg) 11904 break; 11905 if (!map && rem) 11906 { 11907 if (var_check_fixed(di->di_flags, arg_errmsg, TRUE) 11908 || var_check_ro(di->di_flags, arg_errmsg, TRUE)) 11909 break; 11910 dictitem_remove(d, di); 11911 } 11912 } 11913 } 11914 hash_unlock(ht); 11915 } 11916 else 11917 { 11918 vimvars[VV_KEY].vv_type = VAR_NUMBER; 11919 11920 for (li = l->lv_first; li != NULL; li = nli) 11921 { 11922 if (map && tv_check_lock(li->li_tv.v_lock, arg_errmsg, TRUE)) 11923 break; 11924 nli = li->li_next; 11925 vimvars[VV_KEY].vv_nr = idx; 11926 if (filter_map_one(&li->li_tv, expr, map, &rem) == FAIL 11927 || did_emsg) 11928 break; 11929 if (!map && rem) 11930 listitem_remove(l, li); 11931 ++idx; 11932 } 11933 } 11934 11935 restore_vimvar(VV_KEY, &save_key); 11936 restore_vimvar(VV_VAL, &save_val); 11937 11938 did_emsg |= save_did_emsg; 11939 } 11940 11941 copy_tv(&argvars[0], rettv); 11942 } 11943 11944 static int 11945 filter_map_one(typval_T *tv, char_u *expr, int map, int *remp) 11946 { 11947 typval_T rettv; 11948 char_u *s; 11949 int retval = FAIL; 11950 11951 copy_tv(tv, &vimvars[VV_VAL].vv_tv); 11952 s = expr; 11953 if (eval1(&s, &rettv, TRUE) == FAIL) 11954 goto theend; 11955 if (*s != NUL) /* check for trailing chars after expr */ 11956 { 11957 EMSG2(_(e_invexpr2), s); 11958 clear_tv(&rettv); 11959 goto theend; 11960 } 11961 if (map) 11962 { 11963 /* map(): replace the list item value */ 11964 clear_tv(tv); 11965 rettv.v_lock = 0; 11966 *tv = rettv; 11967 } 11968 else 11969 { 11970 int error = FALSE; 11971 11972 /* filter(): when expr is zero remove the item */ 11973 *remp = (get_tv_number_chk(&rettv, &error) == 0); 11974 clear_tv(&rettv); 11975 /* On type error, nothing has been removed; return FAIL to stop the 11976 * loop. The error message was given by get_tv_number_chk(). */ 11977 if (error) 11978 goto theend; 11979 } 11980 retval = OK; 11981 theend: 11982 clear_tv(&vimvars[VV_VAL].vv_tv); 11983 return retval; 11984 } 11985 11986 /* 11987 * "filter()" function 11988 */ 11989 static void 11990 f_filter(typval_T *argvars, typval_T *rettv) 11991 { 11992 filter_map(argvars, rettv, FALSE); 11993 } 11994 11995 /* 11996 * "finddir({fname}[, {path}[, {count}]])" function 11997 */ 11998 static void 11999 f_finddir(typval_T *argvars, typval_T *rettv) 12000 { 12001 findfilendir(argvars, rettv, FINDFILE_DIR); 12002 } 12003 12004 /* 12005 * "findfile({fname}[, {path}[, {count}]])" function 12006 */ 12007 static void 12008 f_findfile(typval_T *argvars, typval_T *rettv) 12009 { 12010 findfilendir(argvars, rettv, FINDFILE_FILE); 12011 } 12012 12013 #ifdef FEAT_FLOAT 12014 /* 12015 * "float2nr({float})" function 12016 */ 12017 static void 12018 f_float2nr(typval_T *argvars, typval_T *rettv) 12019 { 12020 float_T f = 0.0; 12021 12022 if (get_float_arg(argvars, &f) == OK) 12023 { 12024 if (f < -0x7fffffff) 12025 rettv->vval.v_number = -0x7fffffff; 12026 else if (f > 0x7fffffff) 12027 rettv->vval.v_number = 0x7fffffff; 12028 else 12029 rettv->vval.v_number = (varnumber_T)f; 12030 } 12031 } 12032 12033 /* 12034 * "floor({float})" function 12035 */ 12036 static void 12037 f_floor(typval_T *argvars, typval_T *rettv) 12038 { 12039 float_T f = 0.0; 12040 12041 rettv->v_type = VAR_FLOAT; 12042 if (get_float_arg(argvars, &f) == OK) 12043 rettv->vval.v_float = floor(f); 12044 else 12045 rettv->vval.v_float = 0.0; 12046 } 12047 12048 /* 12049 * "fmod()" function 12050 */ 12051 static void 12052 f_fmod(typval_T *argvars, typval_T *rettv) 12053 { 12054 float_T fx = 0.0, fy = 0.0; 12055 12056 rettv->v_type = VAR_FLOAT; 12057 if (get_float_arg(argvars, &fx) == OK 12058 && get_float_arg(&argvars[1], &fy) == OK) 12059 rettv->vval.v_float = fmod(fx, fy); 12060 else 12061 rettv->vval.v_float = 0.0; 12062 } 12063 #endif 12064 12065 /* 12066 * "fnameescape({string})" function 12067 */ 12068 static void 12069 f_fnameescape(typval_T *argvars, typval_T *rettv) 12070 { 12071 rettv->vval.v_string = vim_strsave_fnameescape( 12072 get_tv_string(&argvars[0]), FALSE); 12073 rettv->v_type = VAR_STRING; 12074 } 12075 12076 /* 12077 * "fnamemodify({fname}, {mods})" function 12078 */ 12079 static void 12080 f_fnamemodify(typval_T *argvars, typval_T *rettv) 12081 { 12082 char_u *fname; 12083 char_u *mods; 12084 int usedlen = 0; 12085 int len; 12086 char_u *fbuf = NULL; 12087 char_u buf[NUMBUFLEN]; 12088 12089 fname = get_tv_string_chk(&argvars[0]); 12090 mods = get_tv_string_buf_chk(&argvars[1], buf); 12091 if (fname == NULL || mods == NULL) 12092 fname = NULL; 12093 else 12094 { 12095 len = (int)STRLEN(fname); 12096 (void)modify_fname(mods, &usedlen, &fname, &fbuf, &len); 12097 } 12098 12099 rettv->v_type = VAR_STRING; 12100 if (fname == NULL) 12101 rettv->vval.v_string = NULL; 12102 else 12103 rettv->vval.v_string = vim_strnsave(fname, len); 12104 vim_free(fbuf); 12105 } 12106 12107 static void foldclosed_both(typval_T *argvars, typval_T *rettv, int end); 12108 12109 /* 12110 * "foldclosed()" function 12111 */ 12112 static void 12113 foldclosed_both( 12114 typval_T *argvars UNUSED, 12115 typval_T *rettv, 12116 int end UNUSED) 12117 { 12118 #ifdef FEAT_FOLDING 12119 linenr_T lnum; 12120 linenr_T first, last; 12121 12122 lnum = get_tv_lnum(argvars); 12123 if (lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count) 12124 { 12125 if (hasFoldingWin(curwin, lnum, &first, &last, FALSE, NULL)) 12126 { 12127 if (end) 12128 rettv->vval.v_number = (varnumber_T)last; 12129 else 12130 rettv->vval.v_number = (varnumber_T)first; 12131 return; 12132 } 12133 } 12134 #endif 12135 rettv->vval.v_number = -1; 12136 } 12137 12138 /* 12139 * "foldclosed()" function 12140 */ 12141 static void 12142 f_foldclosed(typval_T *argvars, typval_T *rettv) 12143 { 12144 foldclosed_both(argvars, rettv, FALSE); 12145 } 12146 12147 /* 12148 * "foldclosedend()" function 12149 */ 12150 static void 12151 f_foldclosedend(typval_T *argvars, typval_T *rettv) 12152 { 12153 foldclosed_both(argvars, rettv, TRUE); 12154 } 12155 12156 /* 12157 * "foldlevel()" function 12158 */ 12159 static void 12160 f_foldlevel(typval_T *argvars UNUSED, typval_T *rettv UNUSED) 12161 { 12162 #ifdef FEAT_FOLDING 12163 linenr_T lnum; 12164 12165 lnum = get_tv_lnum(argvars); 12166 if (lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count) 12167 rettv->vval.v_number = foldLevel(lnum); 12168 #endif 12169 } 12170 12171 /* 12172 * "foldtext()" function 12173 */ 12174 static void 12175 f_foldtext(typval_T *argvars UNUSED, typval_T *rettv) 12176 { 12177 #ifdef FEAT_FOLDING 12178 linenr_T lnum; 12179 char_u *s; 12180 char_u *r; 12181 int len; 12182 char *txt; 12183 #endif 12184 12185 rettv->v_type = VAR_STRING; 12186 rettv->vval.v_string = NULL; 12187 #ifdef FEAT_FOLDING 12188 if ((linenr_T)vimvars[VV_FOLDSTART].vv_nr > 0 12189 && (linenr_T)vimvars[VV_FOLDEND].vv_nr 12190 <= curbuf->b_ml.ml_line_count 12191 && vimvars[VV_FOLDDASHES].vv_str != NULL) 12192 { 12193 /* Find first non-empty line in the fold. */ 12194 lnum = (linenr_T)vimvars[VV_FOLDSTART].vv_nr; 12195 while (lnum < (linenr_T)vimvars[VV_FOLDEND].vv_nr) 12196 { 12197 if (!linewhite(lnum)) 12198 break; 12199 ++lnum; 12200 } 12201 12202 /* Find interesting text in this line. */ 12203 s = skipwhite(ml_get(lnum)); 12204 /* skip C comment-start */ 12205 if (s[0] == '/' && (s[1] == '*' || s[1] == '/')) 12206 { 12207 s = skipwhite(s + 2); 12208 if (*skipwhite(s) == NUL 12209 && lnum + 1 < (linenr_T)vimvars[VV_FOLDEND].vv_nr) 12210 { 12211 s = skipwhite(ml_get(lnum + 1)); 12212 if (*s == '*') 12213 s = skipwhite(s + 1); 12214 } 12215 } 12216 txt = _("+-%s%3ld lines: "); 12217 r = alloc((unsigned)(STRLEN(txt) 12218 + STRLEN(vimvars[VV_FOLDDASHES].vv_str) /* for %s */ 12219 + 20 /* for %3ld */ 12220 + STRLEN(s))); /* concatenated */ 12221 if (r != NULL) 12222 { 12223 sprintf((char *)r, txt, vimvars[VV_FOLDDASHES].vv_str, 12224 (long)((linenr_T)vimvars[VV_FOLDEND].vv_nr 12225 - (linenr_T)vimvars[VV_FOLDSTART].vv_nr + 1)); 12226 len = (int)STRLEN(r); 12227 STRCAT(r, s); 12228 /* remove 'foldmarker' and 'commentstring' */ 12229 foldtext_cleanup(r + len); 12230 rettv->vval.v_string = r; 12231 } 12232 } 12233 #endif 12234 } 12235 12236 /* 12237 * "foldtextresult(lnum)" function 12238 */ 12239 static void 12240 f_foldtextresult(typval_T *argvars UNUSED, typval_T *rettv) 12241 { 12242 #ifdef FEAT_FOLDING 12243 linenr_T lnum; 12244 char_u *text; 12245 char_u buf[51]; 12246 foldinfo_T foldinfo; 12247 int fold_count; 12248 #endif 12249 12250 rettv->v_type = VAR_STRING; 12251 rettv->vval.v_string = NULL; 12252 #ifdef FEAT_FOLDING 12253 lnum = get_tv_lnum(argvars); 12254 /* treat illegal types and illegal string values for {lnum} the same */ 12255 if (lnum < 0) 12256 lnum = 0; 12257 fold_count = foldedCount(curwin, lnum, &foldinfo); 12258 if (fold_count > 0) 12259 { 12260 text = get_foldtext(curwin, lnum, lnum + fold_count - 1, 12261 &foldinfo, buf); 12262 if (text == buf) 12263 text = vim_strsave(text); 12264 rettv->vval.v_string = text; 12265 } 12266 #endif 12267 } 12268 12269 /* 12270 * "foreground()" function 12271 */ 12272 static void 12273 f_foreground(typval_T *argvars UNUSED, typval_T *rettv UNUSED) 12274 { 12275 #ifdef FEAT_GUI 12276 if (gui.in_use) 12277 gui_mch_set_foreground(); 12278 #else 12279 # ifdef WIN32 12280 win32_set_foreground(); 12281 # endif 12282 #endif 12283 } 12284 12285 /* 12286 * "function()" function 12287 */ 12288 static void 12289 f_function(typval_T *argvars, typval_T *rettv) 12290 { 12291 char_u *s; 12292 char_u *name; 12293 int use_string = FALSE; 12294 partial_T *arg_pt = NULL; 12295 12296 if (argvars[0].v_type == VAR_FUNC) 12297 { 12298 /* function(MyFunc, [arg], dict) */ 12299 s = argvars[0].vval.v_string; 12300 } 12301 else if (argvars[0].v_type == VAR_PARTIAL 12302 && argvars[0].vval.v_partial != NULL) 12303 { 12304 /* function(dict.MyFunc, [arg]) */ 12305 arg_pt = argvars[0].vval.v_partial; 12306 s = arg_pt->pt_name; 12307 } 12308 else 12309 { 12310 /* function('MyFunc', [arg], dict) */ 12311 s = get_tv_string(&argvars[0]); 12312 use_string = TRUE; 12313 } 12314 12315 if (s == NULL || *s == NUL || (use_string && VIM_ISDIGIT(*s))) 12316 EMSG2(_(e_invarg2), s); 12317 /* Don't check an autoload name for existence here. */ 12318 else if (use_string && vim_strchr(s, AUTOLOAD_CHAR) == NULL 12319 && !function_exists(s)) 12320 EMSG2(_("E700: Unknown function: %s"), s); 12321 else 12322 { 12323 int dict_idx = 0; 12324 int arg_idx = 0; 12325 list_T *list = NULL; 12326 12327 if (STRNCMP(s, "s:", 2) == 0 || STRNCMP(s, "<SID>", 5) == 0) 12328 { 12329 char sid_buf[25]; 12330 int off = *s == 's' ? 2 : 5; 12331 12332 /* Expand s: and <SID> into <SNR>nr_, so that the function can 12333 * also be called from another script. Using trans_function_name() 12334 * would also work, but some plugins depend on the name being 12335 * printable text. */ 12336 sprintf(sid_buf, "<SNR>%ld_", (long)current_SID); 12337 name = alloc((int)(STRLEN(sid_buf) + STRLEN(s + off) + 1)); 12338 if (name != NULL) 12339 { 12340 STRCPY(name, sid_buf); 12341 STRCAT(name, s + off); 12342 } 12343 } 12344 else 12345 name = vim_strsave(s); 12346 12347 if (argvars[1].v_type != VAR_UNKNOWN) 12348 { 12349 if (argvars[2].v_type != VAR_UNKNOWN) 12350 { 12351 /* function(name, [args], dict) */ 12352 arg_idx = 1; 12353 dict_idx = 2; 12354 } 12355 else if (argvars[1].v_type == VAR_DICT) 12356 /* function(name, dict) */ 12357 dict_idx = 1; 12358 else 12359 /* function(name, [args]) */ 12360 arg_idx = 1; 12361 if (dict_idx > 0) 12362 { 12363 if (argvars[dict_idx].v_type != VAR_DICT) 12364 { 12365 EMSG(_("E922: expected a dict")); 12366 vim_free(name); 12367 return; 12368 } 12369 if (argvars[dict_idx].vval.v_dict == NULL) 12370 dict_idx = 0; 12371 } 12372 if (arg_idx > 0) 12373 { 12374 if (argvars[arg_idx].v_type != VAR_LIST) 12375 { 12376 EMSG(_("E923: Second argument of function() must be a list or a dict")); 12377 vim_free(name); 12378 return; 12379 } 12380 list = argvars[arg_idx].vval.v_list; 12381 if (list == NULL || list->lv_len == 0) 12382 arg_idx = 0; 12383 } 12384 } 12385 if (dict_idx > 0 || arg_idx > 0 || arg_pt != NULL) 12386 { 12387 partial_T *pt = (partial_T *)alloc_clear(sizeof(partial_T)); 12388 12389 /* result is a VAR_PARTIAL */ 12390 if (pt == NULL) 12391 vim_free(name); 12392 else 12393 { 12394 if (arg_idx > 0 || (arg_pt != NULL && arg_pt->pt_argc > 0)) 12395 { 12396 listitem_T *li; 12397 int i = 0; 12398 int arg_len = 0; 12399 int lv_len = 0; 12400 12401 if (arg_pt != NULL) 12402 arg_len = arg_pt->pt_argc; 12403 if (list != NULL) 12404 lv_len = list->lv_len; 12405 pt->pt_argc = arg_len + lv_len; 12406 pt->pt_argv = (typval_T *)alloc( 12407 sizeof(typval_T) * pt->pt_argc); 12408 if (pt->pt_argv == NULL) 12409 { 12410 vim_free(pt); 12411 vim_free(name); 12412 return; 12413 } 12414 else 12415 { 12416 for (i = 0; i < arg_len; i++) 12417 copy_tv(&arg_pt->pt_argv[i], &pt->pt_argv[i]); 12418 if (lv_len > 0) 12419 for (li = list->lv_first; li != NULL; 12420 li = li->li_next) 12421 copy_tv(&li->li_tv, &pt->pt_argv[i++]); 12422 } 12423 } 12424 12425 /* For "function(dict.func, [], dict)" and "func" is a partial 12426 * use "dict". That is backwards compatible. */ 12427 if (dict_idx > 0) 12428 { 12429 /* The dict is bound explicitly, pt_auto is FALSE. */ 12430 pt->pt_dict = argvars[dict_idx].vval.v_dict; 12431 ++pt->pt_dict->dv_refcount; 12432 } 12433 else if (arg_pt != NULL) 12434 { 12435 /* If the dict was bound automatically the result is also 12436 * bound automatically. */ 12437 pt->pt_dict = arg_pt->pt_dict; 12438 pt->pt_auto = arg_pt->pt_auto; 12439 if (pt->pt_dict != NULL) 12440 ++pt->pt_dict->dv_refcount; 12441 } 12442 12443 pt->pt_refcount = 1; 12444 pt->pt_name = name; 12445 func_ref(pt->pt_name); 12446 } 12447 rettv->v_type = VAR_PARTIAL; 12448 rettv->vval.v_partial = pt; 12449 } 12450 else 12451 { 12452 /* result is a VAR_FUNC */ 12453 rettv->v_type = VAR_FUNC; 12454 rettv->vval.v_string = name; 12455 func_ref(name); 12456 } 12457 } 12458 } 12459 12460 /* 12461 * "garbagecollect()" function 12462 */ 12463 static void 12464 f_garbagecollect(typval_T *argvars, typval_T *rettv UNUSED) 12465 { 12466 /* This is postponed until we are back at the toplevel, because we may be 12467 * using Lists and Dicts internally. E.g.: ":echo [garbagecollect()]". */ 12468 want_garbage_collect = TRUE; 12469 12470 if (argvars[0].v_type != VAR_UNKNOWN && get_tv_number(&argvars[0]) == 1) 12471 garbage_collect_at_exit = TRUE; 12472 } 12473 12474 /* 12475 * "get()" function 12476 */ 12477 static void 12478 f_get(typval_T *argvars, typval_T *rettv) 12479 { 12480 listitem_T *li; 12481 list_T *l; 12482 dictitem_T *di; 12483 dict_T *d; 12484 typval_T *tv = NULL; 12485 12486 if (argvars[0].v_type == VAR_LIST) 12487 { 12488 if ((l = argvars[0].vval.v_list) != NULL) 12489 { 12490 int error = FALSE; 12491 12492 li = list_find(l, get_tv_number_chk(&argvars[1], &error)); 12493 if (!error && li != NULL) 12494 tv = &li->li_tv; 12495 } 12496 } 12497 else if (argvars[0].v_type == VAR_DICT) 12498 { 12499 if ((d = argvars[0].vval.v_dict) != NULL) 12500 { 12501 di = dict_find(d, get_tv_string(&argvars[1]), -1); 12502 if (di != NULL) 12503 tv = &di->di_tv; 12504 } 12505 } 12506 else if (argvars[0].v_type == VAR_PARTIAL || argvars[0].v_type == VAR_FUNC) 12507 { 12508 partial_T *pt; 12509 partial_T fref_pt; 12510 12511 if (argvars[0].v_type == VAR_PARTIAL) 12512 pt = argvars[0].vval.v_partial; 12513 else 12514 { 12515 vim_memset(&fref_pt, 0, sizeof(fref_pt)); 12516 fref_pt.pt_name = argvars[0].vval.v_string; 12517 pt = &fref_pt; 12518 } 12519 12520 if (pt != NULL) 12521 { 12522 char_u *what = get_tv_string(&argvars[1]); 12523 12524 if (STRCMP(what, "func") == 0 || STRCMP(what, "name") == 0) 12525 { 12526 rettv->v_type = (*what == 'f' ? VAR_FUNC : VAR_STRING); 12527 if (pt->pt_name == NULL) 12528 rettv->vval.v_string = NULL; 12529 else 12530 rettv->vval.v_string = vim_strsave(pt->pt_name); 12531 } 12532 else if (STRCMP(what, "dict") == 0) 12533 { 12534 rettv->v_type = VAR_DICT; 12535 rettv->vval.v_dict = pt->pt_dict; 12536 if (pt->pt_dict != NULL) 12537 ++pt->pt_dict->dv_refcount; 12538 } 12539 else if (STRCMP(what, "args") == 0) 12540 { 12541 rettv->v_type = VAR_LIST; 12542 if (rettv_list_alloc(rettv) == OK) 12543 { 12544 int i; 12545 12546 for (i = 0; i < pt->pt_argc; ++i) 12547 list_append_tv(rettv->vval.v_list, &pt->pt_argv[i]); 12548 } 12549 } 12550 else 12551 EMSG2(_(e_invarg2), what); 12552 return; 12553 } 12554 } 12555 else 12556 EMSG2(_(e_listdictarg), "get()"); 12557 12558 if (tv == NULL) 12559 { 12560 if (argvars[2].v_type != VAR_UNKNOWN) 12561 copy_tv(&argvars[2], rettv); 12562 } 12563 else 12564 copy_tv(tv, rettv); 12565 } 12566 12567 static void get_buffer_lines(buf_T *buf, linenr_T start, linenr_T end, int retlist, typval_T *rettv); 12568 12569 /* 12570 * Get line or list of lines from buffer "buf" into "rettv". 12571 * Return a range (from start to end) of lines in rettv from the specified 12572 * buffer. 12573 * If 'retlist' is TRUE, then the lines are returned as a Vim List. 12574 */ 12575 static void 12576 get_buffer_lines( 12577 buf_T *buf, 12578 linenr_T start, 12579 linenr_T end, 12580 int retlist, 12581 typval_T *rettv) 12582 { 12583 char_u *p; 12584 12585 rettv->v_type = VAR_STRING; 12586 rettv->vval.v_string = NULL; 12587 if (retlist && rettv_list_alloc(rettv) == FAIL) 12588 return; 12589 12590 if (buf == NULL || buf->b_ml.ml_mfp == NULL || start < 0) 12591 return; 12592 12593 if (!retlist) 12594 { 12595 if (start >= 1 && start <= buf->b_ml.ml_line_count) 12596 p = ml_get_buf(buf, start, FALSE); 12597 else 12598 p = (char_u *)""; 12599 rettv->vval.v_string = vim_strsave(p); 12600 } 12601 else 12602 { 12603 if (end < start) 12604 return; 12605 12606 if (start < 1) 12607 start = 1; 12608 if (end > buf->b_ml.ml_line_count) 12609 end = buf->b_ml.ml_line_count; 12610 while (start <= end) 12611 if (list_append_string(rettv->vval.v_list, 12612 ml_get_buf(buf, start++, FALSE), -1) == FAIL) 12613 break; 12614 } 12615 } 12616 12617 /* 12618 * "getbufline()" function 12619 */ 12620 static void 12621 f_getbufline(typval_T *argvars, typval_T *rettv) 12622 { 12623 linenr_T lnum; 12624 linenr_T end; 12625 buf_T *buf; 12626 12627 (void)get_tv_number(&argvars[0]); /* issue errmsg if type error */ 12628 ++emsg_off; 12629 buf = get_buf_tv(&argvars[0], FALSE); 12630 --emsg_off; 12631 12632 lnum = get_tv_lnum_buf(&argvars[1], buf); 12633 if (argvars[2].v_type == VAR_UNKNOWN) 12634 end = lnum; 12635 else 12636 end = get_tv_lnum_buf(&argvars[2], buf); 12637 12638 get_buffer_lines(buf, lnum, end, TRUE, rettv); 12639 } 12640 12641 /* 12642 * "getbufvar()" function 12643 */ 12644 static void 12645 f_getbufvar(typval_T *argvars, typval_T *rettv) 12646 { 12647 buf_T *buf; 12648 buf_T *save_curbuf; 12649 char_u *varname; 12650 dictitem_T *v; 12651 int done = FALSE; 12652 12653 (void)get_tv_number(&argvars[0]); /* issue errmsg if type error */ 12654 varname = get_tv_string_chk(&argvars[1]); 12655 ++emsg_off; 12656 buf = get_buf_tv(&argvars[0], FALSE); 12657 12658 rettv->v_type = VAR_STRING; 12659 rettv->vval.v_string = NULL; 12660 12661 if (buf != NULL && varname != NULL) 12662 { 12663 /* set curbuf to be our buf, temporarily */ 12664 save_curbuf = curbuf; 12665 curbuf = buf; 12666 12667 if (*varname == '&') /* buffer-local-option */ 12668 { 12669 if (get_option_tv(&varname, rettv, TRUE) == OK) 12670 done = TRUE; 12671 } 12672 else if (STRCMP(varname, "changedtick") == 0) 12673 { 12674 rettv->v_type = VAR_NUMBER; 12675 rettv->vval.v_number = curbuf->b_changedtick; 12676 done = TRUE; 12677 } 12678 else 12679 { 12680 /* Look up the variable. */ 12681 /* Let getbufvar({nr}, "") return the "b:" dictionary. */ 12682 v = find_var_in_ht(&curbuf->b_vars->dv_hashtab, 12683 'b', varname, FALSE); 12684 if (v != NULL) 12685 { 12686 copy_tv(&v->di_tv, rettv); 12687 done = TRUE; 12688 } 12689 } 12690 12691 /* restore previous notion of curbuf */ 12692 curbuf = save_curbuf; 12693 } 12694 12695 if (!done && argvars[2].v_type != VAR_UNKNOWN) 12696 /* use the default value */ 12697 copy_tv(&argvars[2], rettv); 12698 12699 --emsg_off; 12700 } 12701 12702 /* 12703 * "getchar()" function 12704 */ 12705 static void 12706 f_getchar(typval_T *argvars, typval_T *rettv) 12707 { 12708 varnumber_T n; 12709 int error = FALSE; 12710 12711 /* Position the cursor. Needed after a message that ends in a space. */ 12712 windgoto(msg_row, msg_col); 12713 12714 ++no_mapping; 12715 ++allow_keys; 12716 for (;;) 12717 { 12718 if (argvars[0].v_type == VAR_UNKNOWN) 12719 /* getchar(): blocking wait. */ 12720 n = safe_vgetc(); 12721 else if (get_tv_number_chk(&argvars[0], &error) == 1) 12722 /* getchar(1): only check if char avail */ 12723 n = vpeekc_any(); 12724 else if (error || vpeekc_any() == NUL) 12725 /* illegal argument or getchar(0) and no char avail: return zero */ 12726 n = 0; 12727 else 12728 /* getchar(0) and char avail: return char */ 12729 n = safe_vgetc(); 12730 12731 if (n == K_IGNORE) 12732 continue; 12733 break; 12734 } 12735 --no_mapping; 12736 --allow_keys; 12737 12738 vimvars[VV_MOUSE_WIN].vv_nr = 0; 12739 vimvars[VV_MOUSE_LNUM].vv_nr = 0; 12740 vimvars[VV_MOUSE_COL].vv_nr = 0; 12741 12742 rettv->vval.v_number = n; 12743 if (IS_SPECIAL(n) || mod_mask != 0) 12744 { 12745 char_u temp[10]; /* modifier: 3, mbyte-char: 6, NUL: 1 */ 12746 int i = 0; 12747 12748 /* Turn a special key into three bytes, plus modifier. */ 12749 if (mod_mask != 0) 12750 { 12751 temp[i++] = K_SPECIAL; 12752 temp[i++] = KS_MODIFIER; 12753 temp[i++] = mod_mask; 12754 } 12755 if (IS_SPECIAL(n)) 12756 { 12757 temp[i++] = K_SPECIAL; 12758 temp[i++] = K_SECOND(n); 12759 temp[i++] = K_THIRD(n); 12760 } 12761 #ifdef FEAT_MBYTE 12762 else if (has_mbyte) 12763 i += (*mb_char2bytes)(n, temp + i); 12764 #endif 12765 else 12766 temp[i++] = n; 12767 temp[i++] = NUL; 12768 rettv->v_type = VAR_STRING; 12769 rettv->vval.v_string = vim_strsave(temp); 12770 12771 #ifdef FEAT_MOUSE 12772 if (is_mouse_key(n)) 12773 { 12774 int row = mouse_row; 12775 int col = mouse_col; 12776 win_T *win; 12777 linenr_T lnum; 12778 # ifdef FEAT_WINDOWS 12779 win_T *wp; 12780 # endif 12781 int winnr = 1; 12782 12783 if (row >= 0 && col >= 0) 12784 { 12785 /* Find the window at the mouse coordinates and compute the 12786 * text position. */ 12787 win = mouse_find_win(&row, &col); 12788 (void)mouse_comp_pos(win, &row, &col, &lnum); 12789 # ifdef FEAT_WINDOWS 12790 for (wp = firstwin; wp != win; wp = wp->w_next) 12791 ++winnr; 12792 # endif 12793 vimvars[VV_MOUSE_WIN].vv_nr = winnr; 12794 vimvars[VV_MOUSE_LNUM].vv_nr = lnum; 12795 vimvars[VV_MOUSE_COL].vv_nr = col + 1; 12796 } 12797 } 12798 #endif 12799 } 12800 } 12801 12802 /* 12803 * "getcharmod()" function 12804 */ 12805 static void 12806 f_getcharmod(typval_T *argvars UNUSED, typval_T *rettv) 12807 { 12808 rettv->vval.v_number = mod_mask; 12809 } 12810 12811 /* 12812 * "getcharsearch()" function 12813 */ 12814 static void 12815 f_getcharsearch(typval_T *argvars UNUSED, typval_T *rettv) 12816 { 12817 if (rettv_dict_alloc(rettv) != FAIL) 12818 { 12819 dict_T *dict = rettv->vval.v_dict; 12820 12821 dict_add_nr_str(dict, "char", 0L, last_csearch()); 12822 dict_add_nr_str(dict, "forward", last_csearch_forward(), NULL); 12823 dict_add_nr_str(dict, "until", last_csearch_until(), NULL); 12824 } 12825 } 12826 12827 /* 12828 * "getcmdline()" function 12829 */ 12830 static void 12831 f_getcmdline(typval_T *argvars UNUSED, typval_T *rettv) 12832 { 12833 rettv->v_type = VAR_STRING; 12834 rettv->vval.v_string = get_cmdline_str(); 12835 } 12836 12837 /* 12838 * "getcmdpos()" function 12839 */ 12840 static void 12841 f_getcmdpos(typval_T *argvars UNUSED, typval_T *rettv) 12842 { 12843 rettv->vval.v_number = get_cmdline_pos() + 1; 12844 } 12845 12846 /* 12847 * "getcmdtype()" function 12848 */ 12849 static void 12850 f_getcmdtype(typval_T *argvars UNUSED, typval_T *rettv) 12851 { 12852 rettv->v_type = VAR_STRING; 12853 rettv->vval.v_string = alloc(2); 12854 if (rettv->vval.v_string != NULL) 12855 { 12856 rettv->vval.v_string[0] = get_cmdline_type(); 12857 rettv->vval.v_string[1] = NUL; 12858 } 12859 } 12860 12861 /* 12862 * "getcmdwintype()" function 12863 */ 12864 static void 12865 f_getcmdwintype(typval_T *argvars UNUSED, typval_T *rettv) 12866 { 12867 rettv->v_type = VAR_STRING; 12868 rettv->vval.v_string = NULL; 12869 #ifdef FEAT_CMDWIN 12870 rettv->vval.v_string = alloc(2); 12871 if (rettv->vval.v_string != NULL) 12872 { 12873 rettv->vval.v_string[0] = cmdwin_type; 12874 rettv->vval.v_string[1] = NUL; 12875 } 12876 #endif 12877 } 12878 12879 /* 12880 * "getcwd()" function 12881 */ 12882 static void 12883 f_getcwd(typval_T *argvars, typval_T *rettv) 12884 { 12885 win_T *wp = NULL; 12886 char_u *cwd; 12887 12888 rettv->v_type = VAR_STRING; 12889 rettv->vval.v_string = NULL; 12890 12891 wp = find_tabwin(&argvars[0], &argvars[1]); 12892 if (wp != NULL) 12893 { 12894 if (wp->w_localdir != NULL) 12895 rettv->vval.v_string = vim_strsave(wp->w_localdir); 12896 else if(globaldir != NULL) 12897 rettv->vval.v_string = vim_strsave(globaldir); 12898 else 12899 { 12900 cwd = alloc(MAXPATHL); 12901 if (cwd != NULL) 12902 { 12903 if (mch_dirname(cwd, MAXPATHL) != FAIL) 12904 rettv->vval.v_string = vim_strsave(cwd); 12905 vim_free(cwd); 12906 } 12907 } 12908 #ifdef BACKSLASH_IN_FILENAME 12909 if (rettv->vval.v_string != NULL) 12910 slash_adjust(rettv->vval.v_string); 12911 #endif 12912 } 12913 } 12914 12915 /* 12916 * "getfontname()" function 12917 */ 12918 static void 12919 f_getfontname(typval_T *argvars UNUSED, typval_T *rettv) 12920 { 12921 rettv->v_type = VAR_STRING; 12922 rettv->vval.v_string = NULL; 12923 #ifdef FEAT_GUI 12924 if (gui.in_use) 12925 { 12926 GuiFont font; 12927 char_u *name = NULL; 12928 12929 if (argvars[0].v_type == VAR_UNKNOWN) 12930 { 12931 /* Get the "Normal" font. Either the name saved by 12932 * hl_set_font_name() or from the font ID. */ 12933 font = gui.norm_font; 12934 name = hl_get_font_name(); 12935 } 12936 else 12937 { 12938 name = get_tv_string(&argvars[0]); 12939 if (STRCMP(name, "*") == 0) /* don't use font dialog */ 12940 return; 12941 font = gui_mch_get_font(name, FALSE); 12942 if (font == NOFONT) 12943 return; /* Invalid font name, return empty string. */ 12944 } 12945 rettv->vval.v_string = gui_mch_get_fontname(font, name); 12946 if (argvars[0].v_type != VAR_UNKNOWN) 12947 gui_mch_free_font(font); 12948 } 12949 #endif 12950 } 12951 12952 /* 12953 * "getfperm({fname})" function 12954 */ 12955 static void 12956 f_getfperm(typval_T *argvars, typval_T *rettv) 12957 { 12958 char_u *fname; 12959 struct stat st; 12960 char_u *perm = NULL; 12961 char_u flags[] = "rwx"; 12962 int i; 12963 12964 fname = get_tv_string(&argvars[0]); 12965 12966 rettv->v_type = VAR_STRING; 12967 if (mch_stat((char *)fname, &st) >= 0) 12968 { 12969 perm = vim_strsave((char_u *)"---------"); 12970 if (perm != NULL) 12971 { 12972 for (i = 0; i < 9; i++) 12973 { 12974 if (st.st_mode & (1 << (8 - i))) 12975 perm[i] = flags[i % 3]; 12976 } 12977 } 12978 } 12979 rettv->vval.v_string = perm; 12980 } 12981 12982 /* 12983 * "getfsize({fname})" function 12984 */ 12985 static void 12986 f_getfsize(typval_T *argvars, typval_T *rettv) 12987 { 12988 char_u *fname; 12989 struct stat st; 12990 12991 fname = get_tv_string(&argvars[0]); 12992 12993 rettv->v_type = VAR_NUMBER; 12994 12995 if (mch_stat((char *)fname, &st) >= 0) 12996 { 12997 if (mch_isdir(fname)) 12998 rettv->vval.v_number = 0; 12999 else 13000 { 13001 rettv->vval.v_number = (varnumber_T)st.st_size; 13002 13003 /* non-perfect check for overflow */ 13004 if ((off_t)rettv->vval.v_number != (off_t)st.st_size) 13005 rettv->vval.v_number = -2; 13006 } 13007 } 13008 else 13009 rettv->vval.v_number = -1; 13010 } 13011 13012 /* 13013 * "getftime({fname})" function 13014 */ 13015 static void 13016 f_getftime(typval_T *argvars, typval_T *rettv) 13017 { 13018 char_u *fname; 13019 struct stat st; 13020 13021 fname = get_tv_string(&argvars[0]); 13022 13023 if (mch_stat((char *)fname, &st) >= 0) 13024 rettv->vval.v_number = (varnumber_T)st.st_mtime; 13025 else 13026 rettv->vval.v_number = -1; 13027 } 13028 13029 /* 13030 * "getftype({fname})" function 13031 */ 13032 static void 13033 f_getftype(typval_T *argvars, typval_T *rettv) 13034 { 13035 char_u *fname; 13036 struct stat st; 13037 char_u *type = NULL; 13038 char *t; 13039 13040 fname = get_tv_string(&argvars[0]); 13041 13042 rettv->v_type = VAR_STRING; 13043 if (mch_lstat((char *)fname, &st) >= 0) 13044 { 13045 #ifdef S_ISREG 13046 if (S_ISREG(st.st_mode)) 13047 t = "file"; 13048 else if (S_ISDIR(st.st_mode)) 13049 t = "dir"; 13050 # ifdef S_ISLNK 13051 else if (S_ISLNK(st.st_mode)) 13052 t = "link"; 13053 # endif 13054 # ifdef S_ISBLK 13055 else if (S_ISBLK(st.st_mode)) 13056 t = "bdev"; 13057 # endif 13058 # ifdef S_ISCHR 13059 else if (S_ISCHR(st.st_mode)) 13060 t = "cdev"; 13061 # endif 13062 # ifdef S_ISFIFO 13063 else if (S_ISFIFO(st.st_mode)) 13064 t = "fifo"; 13065 # endif 13066 # ifdef S_ISSOCK 13067 else if (S_ISSOCK(st.st_mode)) 13068 t = "fifo"; 13069 # endif 13070 else 13071 t = "other"; 13072 #else 13073 # ifdef S_IFMT 13074 switch (st.st_mode & S_IFMT) 13075 { 13076 case S_IFREG: t = "file"; break; 13077 case S_IFDIR: t = "dir"; break; 13078 # ifdef S_IFLNK 13079 case S_IFLNK: t = "link"; break; 13080 # endif 13081 # ifdef S_IFBLK 13082 case S_IFBLK: t = "bdev"; break; 13083 # endif 13084 # ifdef S_IFCHR 13085 case S_IFCHR: t = "cdev"; break; 13086 # endif 13087 # ifdef S_IFIFO 13088 case S_IFIFO: t = "fifo"; break; 13089 # endif 13090 # ifdef S_IFSOCK 13091 case S_IFSOCK: t = "socket"; break; 13092 # endif 13093 default: t = "other"; 13094 } 13095 # else 13096 if (mch_isdir(fname)) 13097 t = "dir"; 13098 else 13099 t = "file"; 13100 # endif 13101 #endif 13102 type = vim_strsave((char_u *)t); 13103 } 13104 rettv->vval.v_string = type; 13105 } 13106 13107 /* 13108 * "getline(lnum, [end])" function 13109 */ 13110 static void 13111 f_getline(typval_T *argvars, typval_T *rettv) 13112 { 13113 linenr_T lnum; 13114 linenr_T end; 13115 int retlist; 13116 13117 lnum = get_tv_lnum(argvars); 13118 if (argvars[1].v_type == VAR_UNKNOWN) 13119 { 13120 end = 0; 13121 retlist = FALSE; 13122 } 13123 else 13124 { 13125 end = get_tv_lnum(&argvars[1]); 13126 retlist = TRUE; 13127 } 13128 13129 get_buffer_lines(curbuf, lnum, end, retlist, rettv); 13130 } 13131 13132 /* 13133 * "getmatches()" function 13134 */ 13135 static void 13136 f_getmatches(typval_T *argvars UNUSED, typval_T *rettv UNUSED) 13137 { 13138 #ifdef FEAT_SEARCH_EXTRA 13139 dict_T *dict; 13140 matchitem_T *cur = curwin->w_match_head; 13141 int i; 13142 13143 if (rettv_list_alloc(rettv) == OK) 13144 { 13145 while (cur != NULL) 13146 { 13147 dict = dict_alloc(); 13148 if (dict == NULL) 13149 return; 13150 if (cur->match.regprog == NULL) 13151 { 13152 /* match added with matchaddpos() */ 13153 for (i = 0; i < MAXPOSMATCH; ++i) 13154 { 13155 llpos_T *llpos; 13156 char buf[6]; 13157 list_T *l; 13158 13159 llpos = &cur->pos.pos[i]; 13160 if (llpos->lnum == 0) 13161 break; 13162 l = list_alloc(); 13163 if (l == NULL) 13164 break; 13165 list_append_number(l, (varnumber_T)llpos->lnum); 13166 if (llpos->col > 0) 13167 { 13168 list_append_number(l, (varnumber_T)llpos->col); 13169 list_append_number(l, (varnumber_T)llpos->len); 13170 } 13171 sprintf(buf, "pos%d", i + 1); 13172 dict_add_list(dict, buf, l); 13173 } 13174 } 13175 else 13176 { 13177 dict_add_nr_str(dict, "pattern", 0L, cur->pattern); 13178 } 13179 dict_add_nr_str(dict, "group", 0L, syn_id2name(cur->hlg_id)); 13180 dict_add_nr_str(dict, "priority", (long)cur->priority, NULL); 13181 dict_add_nr_str(dict, "id", (long)cur->id, NULL); 13182 # if defined(FEAT_CONCEAL) && defined(FEAT_MBYTE) 13183 if (cur->conceal_char) 13184 { 13185 char_u buf[MB_MAXBYTES + 1]; 13186 13187 buf[(*mb_char2bytes)((int)cur->conceal_char, buf)] = NUL; 13188 dict_add_nr_str(dict, "conceal", 0L, (char_u *)&buf); 13189 } 13190 # endif 13191 list_append_dict(rettv->vval.v_list, dict); 13192 cur = cur->next; 13193 } 13194 } 13195 #endif 13196 } 13197 13198 /* 13199 * "getpid()" function 13200 */ 13201 static void 13202 f_getpid(typval_T *argvars UNUSED, typval_T *rettv) 13203 { 13204 rettv->vval.v_number = mch_get_pid(); 13205 } 13206 13207 static void 13208 getpos_both( 13209 typval_T *argvars, 13210 typval_T *rettv, 13211 int getcurpos) 13212 { 13213 pos_T *fp; 13214 list_T *l; 13215 int fnum = -1; 13216 13217 if (rettv_list_alloc(rettv) == OK) 13218 { 13219 l = rettv->vval.v_list; 13220 if (getcurpos) 13221 fp = &curwin->w_cursor; 13222 else 13223 fp = var2fpos(&argvars[0], TRUE, &fnum); 13224 if (fnum != -1) 13225 list_append_number(l, (varnumber_T)fnum); 13226 else 13227 list_append_number(l, (varnumber_T)0); 13228 list_append_number(l, (fp != NULL) ? (varnumber_T)fp->lnum 13229 : (varnumber_T)0); 13230 list_append_number(l, (fp != NULL) 13231 ? (varnumber_T)(fp->col == MAXCOL ? MAXCOL : fp->col + 1) 13232 : (varnumber_T)0); 13233 list_append_number(l, 13234 #ifdef FEAT_VIRTUALEDIT 13235 (fp != NULL) ? (varnumber_T)fp->coladd : 13236 #endif 13237 (varnumber_T)0); 13238 if (getcurpos) 13239 { 13240 update_curswant(); 13241 list_append_number(l, curwin->w_curswant == MAXCOL ? 13242 (varnumber_T)MAXCOL : (varnumber_T)curwin->w_curswant + 1); 13243 } 13244 } 13245 else 13246 rettv->vval.v_number = FALSE; 13247 } 13248 13249 13250 /* 13251 * "getcurpos()" function 13252 */ 13253 static void 13254 f_getcurpos(typval_T *argvars, typval_T *rettv) 13255 { 13256 getpos_both(argvars, rettv, TRUE); 13257 } 13258 13259 /* 13260 * "getpos(string)" function 13261 */ 13262 static void 13263 f_getpos(typval_T *argvars, typval_T *rettv) 13264 { 13265 getpos_both(argvars, rettv, FALSE); 13266 } 13267 13268 /* 13269 * "getqflist()" and "getloclist()" functions 13270 */ 13271 static void 13272 f_getqflist(typval_T *argvars UNUSED, typval_T *rettv UNUSED) 13273 { 13274 #ifdef FEAT_QUICKFIX 13275 win_T *wp; 13276 #endif 13277 13278 #ifdef FEAT_QUICKFIX 13279 if (rettv_list_alloc(rettv) == OK) 13280 { 13281 wp = NULL; 13282 if (argvars[0].v_type != VAR_UNKNOWN) /* getloclist() */ 13283 { 13284 wp = find_win_by_nr(&argvars[0], NULL); 13285 if (wp == NULL) 13286 return; 13287 } 13288 13289 (void)get_errorlist(wp, rettv->vval.v_list); 13290 } 13291 #endif 13292 } 13293 13294 /* 13295 * "getreg()" function 13296 */ 13297 static void 13298 f_getreg(typval_T *argvars, typval_T *rettv) 13299 { 13300 char_u *strregname; 13301 int regname; 13302 int arg2 = FALSE; 13303 int return_list = FALSE; 13304 int error = FALSE; 13305 13306 if (argvars[0].v_type != VAR_UNKNOWN) 13307 { 13308 strregname = get_tv_string_chk(&argvars[0]); 13309 error = strregname == NULL; 13310 if (argvars[1].v_type != VAR_UNKNOWN) 13311 { 13312 arg2 = get_tv_number_chk(&argvars[1], &error); 13313 if (!error && argvars[2].v_type != VAR_UNKNOWN) 13314 return_list = get_tv_number_chk(&argvars[2], &error); 13315 } 13316 } 13317 else 13318 strregname = vimvars[VV_REG].vv_str; 13319 13320 if (error) 13321 return; 13322 13323 regname = (strregname == NULL ? '"' : *strregname); 13324 if (regname == 0) 13325 regname = '"'; 13326 13327 if (return_list) 13328 { 13329 rettv->v_type = VAR_LIST; 13330 rettv->vval.v_list = (list_T *)get_reg_contents(regname, 13331 (arg2 ? GREG_EXPR_SRC : 0) | GREG_LIST); 13332 if (rettv->vval.v_list == NULL) 13333 (void)rettv_list_alloc(rettv); 13334 else 13335 ++rettv->vval.v_list->lv_refcount; 13336 } 13337 else 13338 { 13339 rettv->v_type = VAR_STRING; 13340 rettv->vval.v_string = get_reg_contents(regname, 13341 arg2 ? GREG_EXPR_SRC : 0); 13342 } 13343 } 13344 13345 /* 13346 * "getregtype()" function 13347 */ 13348 static void 13349 f_getregtype(typval_T *argvars, typval_T *rettv) 13350 { 13351 char_u *strregname; 13352 int regname; 13353 char_u buf[NUMBUFLEN + 2]; 13354 long reglen = 0; 13355 13356 if (argvars[0].v_type != VAR_UNKNOWN) 13357 { 13358 strregname = get_tv_string_chk(&argvars[0]); 13359 if (strregname == NULL) /* type error; errmsg already given */ 13360 { 13361 rettv->v_type = VAR_STRING; 13362 rettv->vval.v_string = NULL; 13363 return; 13364 } 13365 } 13366 else 13367 /* Default to v:register */ 13368 strregname = vimvars[VV_REG].vv_str; 13369 13370 regname = (strregname == NULL ? '"' : *strregname); 13371 if (regname == 0) 13372 regname = '"'; 13373 13374 buf[0] = NUL; 13375 buf[1] = NUL; 13376 switch (get_reg_type(regname, ®len)) 13377 { 13378 case MLINE: buf[0] = 'V'; break; 13379 case MCHAR: buf[0] = 'v'; break; 13380 case MBLOCK: 13381 buf[0] = Ctrl_V; 13382 sprintf((char *)buf + 1, "%ld", reglen + 1); 13383 break; 13384 } 13385 rettv->v_type = VAR_STRING; 13386 rettv->vval.v_string = vim_strsave(buf); 13387 } 13388 13389 /* 13390 * "gettabvar()" function 13391 */ 13392 static void 13393 f_gettabvar(typval_T *argvars, typval_T *rettv) 13394 { 13395 win_T *oldcurwin; 13396 tabpage_T *tp, *oldtabpage; 13397 dictitem_T *v; 13398 char_u *varname; 13399 int done = FALSE; 13400 13401 rettv->v_type = VAR_STRING; 13402 rettv->vval.v_string = NULL; 13403 13404 varname = get_tv_string_chk(&argvars[1]); 13405 tp = find_tabpage((int)get_tv_number_chk(&argvars[0], NULL)); 13406 if (tp != NULL && varname != NULL) 13407 { 13408 /* Set tp to be our tabpage, temporarily. Also set the window to the 13409 * first window in the tabpage, otherwise the window is not valid. */ 13410 if (switch_win(&oldcurwin, &oldtabpage, 13411 tp->tp_firstwin == NULL ? firstwin : tp->tp_firstwin, tp, TRUE) 13412 == OK) 13413 { 13414 /* look up the variable */ 13415 /* Let gettabvar({nr}, "") return the "t:" dictionary. */ 13416 v = find_var_in_ht(&tp->tp_vars->dv_hashtab, 't', varname, FALSE); 13417 if (v != NULL) 13418 { 13419 copy_tv(&v->di_tv, rettv); 13420 done = TRUE; 13421 } 13422 } 13423 13424 /* restore previous notion of curwin */ 13425 restore_win(oldcurwin, oldtabpage, TRUE); 13426 } 13427 13428 if (!done && argvars[2].v_type != VAR_UNKNOWN) 13429 copy_tv(&argvars[2], rettv); 13430 } 13431 13432 /* 13433 * "gettabwinvar()" function 13434 */ 13435 static void 13436 f_gettabwinvar(typval_T *argvars, typval_T *rettv) 13437 { 13438 getwinvar(argvars, rettv, 1); 13439 } 13440 13441 /* 13442 * "getwinposx()" function 13443 */ 13444 static void 13445 f_getwinposx(typval_T *argvars UNUSED, typval_T *rettv) 13446 { 13447 rettv->vval.v_number = -1; 13448 #ifdef FEAT_GUI 13449 if (gui.in_use) 13450 { 13451 int x, y; 13452 13453 if (gui_mch_get_winpos(&x, &y) == OK) 13454 rettv->vval.v_number = x; 13455 } 13456 #endif 13457 } 13458 13459 /* 13460 * "win_findbuf()" function 13461 */ 13462 static void 13463 f_win_findbuf(typval_T *argvars, typval_T *rettv) 13464 { 13465 if (rettv_list_alloc(rettv) != FAIL) 13466 win_findbuf(argvars, rettv->vval.v_list); 13467 } 13468 13469 /* 13470 * "win_getid()" function 13471 */ 13472 static void 13473 f_win_getid(typval_T *argvars, typval_T *rettv) 13474 { 13475 rettv->vval.v_number = win_getid(argvars); 13476 } 13477 13478 /* 13479 * "win_gotoid()" function 13480 */ 13481 static void 13482 f_win_gotoid(typval_T *argvars, typval_T *rettv) 13483 { 13484 rettv->vval.v_number = win_gotoid(argvars); 13485 } 13486 13487 /* 13488 * "win_id2tabwin()" function 13489 */ 13490 static void 13491 f_win_id2tabwin(typval_T *argvars, typval_T *rettv) 13492 { 13493 if (rettv_list_alloc(rettv) != FAIL) 13494 win_id2tabwin(argvars, rettv->vval.v_list); 13495 } 13496 13497 /* 13498 * "win_id2win()" function 13499 */ 13500 static void 13501 f_win_id2win(typval_T *argvars, typval_T *rettv) 13502 { 13503 rettv->vval.v_number = win_id2win(argvars); 13504 } 13505 13506 /* 13507 * "getwinposy()" function 13508 */ 13509 static void 13510 f_getwinposy(typval_T *argvars UNUSED, typval_T *rettv) 13511 { 13512 rettv->vval.v_number = -1; 13513 #ifdef FEAT_GUI 13514 if (gui.in_use) 13515 { 13516 int x, y; 13517 13518 if (gui_mch_get_winpos(&x, &y) == OK) 13519 rettv->vval.v_number = y; 13520 } 13521 #endif 13522 } 13523 13524 /* 13525 * Find window specified by "vp" in tabpage "tp". 13526 */ 13527 static win_T * 13528 find_win_by_nr( 13529 typval_T *vp, 13530 tabpage_T *tp UNUSED) /* NULL for current tab page */ 13531 { 13532 #ifdef FEAT_WINDOWS 13533 win_T *wp; 13534 #endif 13535 int nr; 13536 13537 nr = get_tv_number_chk(vp, NULL); 13538 13539 #ifdef FEAT_WINDOWS 13540 if (nr < 0) 13541 return NULL; 13542 if (nr == 0) 13543 return curwin; 13544 13545 for (wp = (tp == NULL || tp == curtab) ? firstwin : tp->tp_firstwin; 13546 wp != NULL; wp = wp->w_next) 13547 if (--nr <= 0) 13548 break; 13549 return wp; 13550 #else 13551 if (nr == 0 || nr == 1) 13552 return curwin; 13553 return NULL; 13554 #endif 13555 } 13556 13557 /* 13558 * Find window specified by "wvp" in tabpage "tvp". 13559 */ 13560 static win_T * 13561 find_tabwin( 13562 typval_T *wvp, /* VAR_UNKNOWN for current window */ 13563 typval_T *tvp) /* VAR_UNKNOWN for current tab page */ 13564 { 13565 win_T *wp = NULL; 13566 tabpage_T *tp = NULL; 13567 long n; 13568 13569 if (wvp->v_type != VAR_UNKNOWN) 13570 { 13571 if (tvp->v_type != VAR_UNKNOWN) 13572 { 13573 n = get_tv_number(tvp); 13574 if (n >= 0) 13575 tp = find_tabpage(n); 13576 } 13577 else 13578 tp = curtab; 13579 13580 if (tp != NULL) 13581 wp = find_win_by_nr(wvp, tp); 13582 } 13583 else 13584 wp = curwin; 13585 13586 return wp; 13587 } 13588 13589 /* 13590 * "getwinvar()" function 13591 */ 13592 static void 13593 f_getwinvar(typval_T *argvars, typval_T *rettv) 13594 { 13595 getwinvar(argvars, rettv, 0); 13596 } 13597 13598 /* 13599 * getwinvar() and gettabwinvar() 13600 */ 13601 static void 13602 getwinvar( 13603 typval_T *argvars, 13604 typval_T *rettv, 13605 int off) /* 1 for gettabwinvar() */ 13606 { 13607 win_T *win; 13608 char_u *varname; 13609 dictitem_T *v; 13610 tabpage_T *tp = NULL; 13611 int done = FALSE; 13612 #ifdef FEAT_WINDOWS 13613 win_T *oldcurwin; 13614 tabpage_T *oldtabpage; 13615 int need_switch_win; 13616 #endif 13617 13618 #ifdef FEAT_WINDOWS 13619 if (off == 1) 13620 tp = find_tabpage((int)get_tv_number_chk(&argvars[0], NULL)); 13621 else 13622 tp = curtab; 13623 #endif 13624 win = find_win_by_nr(&argvars[off], tp); 13625 varname = get_tv_string_chk(&argvars[off + 1]); 13626 ++emsg_off; 13627 13628 rettv->v_type = VAR_STRING; 13629 rettv->vval.v_string = NULL; 13630 13631 if (win != NULL && varname != NULL) 13632 { 13633 #ifdef FEAT_WINDOWS 13634 /* Set curwin to be our win, temporarily. Also set the tabpage, 13635 * otherwise the window is not valid. Only do this when needed, 13636 * autocommands get blocked. */ 13637 need_switch_win = !(tp == curtab && win == curwin); 13638 if (!need_switch_win 13639 || switch_win(&oldcurwin, &oldtabpage, win, tp, TRUE) == OK) 13640 #endif 13641 { 13642 if (*varname == '&') /* window-local-option */ 13643 { 13644 if (get_option_tv(&varname, rettv, 1) == OK) 13645 done = TRUE; 13646 } 13647 else 13648 { 13649 /* Look up the variable. */ 13650 /* Let getwinvar({nr}, "") return the "w:" dictionary. */ 13651 v = find_var_in_ht(&win->w_vars->dv_hashtab, 'w', 13652 varname, FALSE); 13653 if (v != NULL) 13654 { 13655 copy_tv(&v->di_tv, rettv); 13656 done = TRUE; 13657 } 13658 } 13659 } 13660 13661 #ifdef FEAT_WINDOWS 13662 if (need_switch_win) 13663 /* restore previous notion of curwin */ 13664 restore_win(oldcurwin, oldtabpage, TRUE); 13665 #endif 13666 } 13667 13668 if (!done && argvars[off + 2].v_type != VAR_UNKNOWN) 13669 /* use the default return value */ 13670 copy_tv(&argvars[off + 2], rettv); 13671 13672 --emsg_off; 13673 } 13674 13675 /* 13676 * "glob()" function 13677 */ 13678 static void 13679 f_glob(typval_T *argvars, typval_T *rettv) 13680 { 13681 int options = WILD_SILENT|WILD_USE_NL; 13682 expand_T xpc; 13683 int error = FALSE; 13684 13685 /* When the optional second argument is non-zero, don't remove matches 13686 * for 'wildignore' and don't put matches for 'suffixes' at the end. */ 13687 rettv->v_type = VAR_STRING; 13688 if (argvars[1].v_type != VAR_UNKNOWN) 13689 { 13690 if (get_tv_number_chk(&argvars[1], &error)) 13691 options |= WILD_KEEP_ALL; 13692 if (argvars[2].v_type != VAR_UNKNOWN) 13693 { 13694 if (get_tv_number_chk(&argvars[2], &error)) 13695 { 13696 rettv->v_type = VAR_LIST; 13697 rettv->vval.v_list = NULL; 13698 } 13699 if (argvars[3].v_type != VAR_UNKNOWN 13700 && get_tv_number_chk(&argvars[3], &error)) 13701 options |= WILD_ALLLINKS; 13702 } 13703 } 13704 if (!error) 13705 { 13706 ExpandInit(&xpc); 13707 xpc.xp_context = EXPAND_FILES; 13708 if (p_wic) 13709 options += WILD_ICASE; 13710 if (rettv->v_type == VAR_STRING) 13711 rettv->vval.v_string = ExpandOne(&xpc, get_tv_string(&argvars[0]), 13712 NULL, options, WILD_ALL); 13713 else if (rettv_list_alloc(rettv) != FAIL) 13714 { 13715 int i; 13716 13717 ExpandOne(&xpc, get_tv_string(&argvars[0]), 13718 NULL, options, WILD_ALL_KEEP); 13719 for (i = 0; i < xpc.xp_numfiles; i++) 13720 list_append_string(rettv->vval.v_list, xpc.xp_files[i], -1); 13721 13722 ExpandCleanup(&xpc); 13723 } 13724 } 13725 else 13726 rettv->vval.v_string = NULL; 13727 } 13728 13729 /* 13730 * "globpath()" function 13731 */ 13732 static void 13733 f_globpath(typval_T *argvars, typval_T *rettv) 13734 { 13735 int flags = 0; 13736 char_u buf1[NUMBUFLEN]; 13737 char_u *file = get_tv_string_buf_chk(&argvars[1], buf1); 13738 int error = FALSE; 13739 garray_T ga; 13740 int i; 13741 13742 /* When the optional second argument is non-zero, don't remove matches 13743 * for 'wildignore' and don't put matches for 'suffixes' at the end. */ 13744 rettv->v_type = VAR_STRING; 13745 if (argvars[2].v_type != VAR_UNKNOWN) 13746 { 13747 if (get_tv_number_chk(&argvars[2], &error)) 13748 flags |= WILD_KEEP_ALL; 13749 if (argvars[3].v_type != VAR_UNKNOWN) 13750 { 13751 if (get_tv_number_chk(&argvars[3], &error)) 13752 { 13753 rettv->v_type = VAR_LIST; 13754 rettv->vval.v_list = NULL; 13755 } 13756 if (argvars[4].v_type != VAR_UNKNOWN 13757 && get_tv_number_chk(&argvars[4], &error)) 13758 flags |= WILD_ALLLINKS; 13759 } 13760 } 13761 if (file != NULL && !error) 13762 { 13763 ga_init2(&ga, (int)sizeof(char_u *), 10); 13764 globpath(get_tv_string(&argvars[0]), file, &ga, flags); 13765 if (rettv->v_type == VAR_STRING) 13766 rettv->vval.v_string = ga_concat_strings(&ga, "\n"); 13767 else if (rettv_list_alloc(rettv) != FAIL) 13768 for (i = 0; i < ga.ga_len; ++i) 13769 list_append_string(rettv->vval.v_list, 13770 ((char_u **)(ga.ga_data))[i], -1); 13771 ga_clear_strings(&ga); 13772 } 13773 else 13774 rettv->vval.v_string = NULL; 13775 } 13776 13777 /* 13778 * "glob2regpat()" function 13779 */ 13780 static void 13781 f_glob2regpat(typval_T *argvars, typval_T *rettv) 13782 { 13783 char_u *pat = get_tv_string_chk(&argvars[0]); 13784 13785 rettv->v_type = VAR_STRING; 13786 rettv->vval.v_string = (pat == NULL) 13787 ? NULL : file_pat_to_reg_pat(pat, NULL, NULL, FALSE); 13788 } 13789 13790 /* 13791 * "has()" function 13792 */ 13793 static void 13794 f_has(typval_T *argvars, typval_T *rettv) 13795 { 13796 int i; 13797 char_u *name; 13798 int n = FALSE; 13799 static char *(has_list[]) = 13800 { 13801 #ifdef AMIGA 13802 "amiga", 13803 # ifdef FEAT_ARP 13804 "arp", 13805 # endif 13806 #endif 13807 #ifdef __BEOS__ 13808 "beos", 13809 #endif 13810 #ifdef MACOS 13811 "mac", 13812 #endif 13813 #if defined(MACOS_X_UNIX) 13814 "macunix", /* built with 'darwin' enabled */ 13815 #endif 13816 #if defined(__APPLE__) && __APPLE__ == 1 13817 "osx", /* built with or without 'darwin' enabled */ 13818 #endif 13819 #ifdef __QNX__ 13820 "qnx", 13821 #endif 13822 #ifdef UNIX 13823 "unix", 13824 #endif 13825 #ifdef VMS 13826 "vms", 13827 #endif 13828 #ifdef WIN32 13829 "win32", 13830 #endif 13831 #if defined(UNIX) && (defined(__CYGWIN32__) || defined(__CYGWIN__)) 13832 "win32unix", 13833 #endif 13834 #if defined(WIN64) || defined(_WIN64) 13835 "win64", 13836 #endif 13837 #ifdef EBCDIC 13838 "ebcdic", 13839 #endif 13840 #ifndef CASE_INSENSITIVE_FILENAME 13841 "fname_case", 13842 #endif 13843 #ifdef HAVE_ACL 13844 "acl", 13845 #endif 13846 #ifdef FEAT_ARABIC 13847 "arabic", 13848 #endif 13849 #ifdef FEAT_AUTOCMD 13850 "autocmd", 13851 #endif 13852 #ifdef FEAT_BEVAL 13853 "balloon_eval", 13854 # ifndef FEAT_GUI_W32 /* other GUIs always have multiline balloons */ 13855 "balloon_multiline", 13856 # endif 13857 #endif 13858 #if defined(SOME_BUILTIN_TCAPS) || defined(ALL_BUILTIN_TCAPS) 13859 "builtin_terms", 13860 # ifdef ALL_BUILTIN_TCAPS 13861 "all_builtin_terms", 13862 # endif 13863 #endif 13864 #if defined(FEAT_BROWSE) && (defined(USE_FILE_CHOOSER) \ 13865 || defined(FEAT_GUI_W32) \ 13866 || defined(FEAT_GUI_MOTIF)) 13867 "browsefilter", 13868 #endif 13869 #ifdef FEAT_BYTEOFF 13870 "byte_offset", 13871 #endif 13872 #ifdef FEAT_JOB_CHANNEL 13873 "channel", 13874 #endif 13875 #ifdef FEAT_CINDENT 13876 "cindent", 13877 #endif 13878 #ifdef FEAT_CLIENTSERVER 13879 "clientserver", 13880 #endif 13881 #ifdef FEAT_CLIPBOARD 13882 "clipboard", 13883 #endif 13884 #ifdef FEAT_CMDL_COMPL 13885 "cmdline_compl", 13886 #endif 13887 #ifdef FEAT_CMDHIST 13888 "cmdline_hist", 13889 #endif 13890 #ifdef FEAT_COMMENTS 13891 "comments", 13892 #endif 13893 #ifdef FEAT_CONCEAL 13894 "conceal", 13895 #endif 13896 #ifdef FEAT_CRYPT 13897 "cryptv", 13898 "crypt-blowfish", 13899 "crypt-blowfish2", 13900 #endif 13901 #ifdef FEAT_CSCOPE 13902 "cscope", 13903 #endif 13904 #ifdef FEAT_CURSORBIND 13905 "cursorbind", 13906 #endif 13907 #ifdef CURSOR_SHAPE 13908 "cursorshape", 13909 #endif 13910 #ifdef DEBUG 13911 "debug", 13912 #endif 13913 #ifdef FEAT_CON_DIALOG 13914 "dialog_con", 13915 #endif 13916 #ifdef FEAT_GUI_DIALOG 13917 "dialog_gui", 13918 #endif 13919 #ifdef FEAT_DIFF 13920 "diff", 13921 #endif 13922 #ifdef FEAT_DIGRAPHS 13923 "digraphs", 13924 #endif 13925 #ifdef FEAT_DIRECTX 13926 "directx", 13927 #endif 13928 #ifdef FEAT_DND 13929 "dnd", 13930 #endif 13931 #ifdef FEAT_EMACS_TAGS 13932 "emacs_tags", 13933 #endif 13934 "eval", /* always present, of course! */ 13935 "ex_extra", /* graduated feature */ 13936 #ifdef FEAT_SEARCH_EXTRA 13937 "extra_search", 13938 #endif 13939 #ifdef FEAT_FKMAP 13940 "farsi", 13941 #endif 13942 #ifdef FEAT_SEARCHPATH 13943 "file_in_path", 13944 #endif 13945 #ifdef FEAT_FILTERPIPE 13946 "filterpipe", 13947 #endif 13948 #ifdef FEAT_FIND_ID 13949 "find_in_path", 13950 #endif 13951 #ifdef FEAT_FLOAT 13952 "float", 13953 #endif 13954 #ifdef FEAT_FOLDING 13955 "folding", 13956 #endif 13957 #ifdef FEAT_FOOTER 13958 "footer", 13959 #endif 13960 #if !defined(USE_SYSTEM) && defined(UNIX) 13961 "fork", 13962 #endif 13963 #ifdef FEAT_GETTEXT 13964 "gettext", 13965 #endif 13966 #ifdef FEAT_GUI 13967 "gui", 13968 #endif 13969 #ifdef FEAT_GUI_ATHENA 13970 # ifdef FEAT_GUI_NEXTAW 13971 "gui_neXtaw", 13972 # else 13973 "gui_athena", 13974 # endif 13975 #endif 13976 #ifdef FEAT_GUI_GTK 13977 "gui_gtk", 13978 # ifdef USE_GTK3 13979 "gui_gtk3", 13980 # else 13981 "gui_gtk2", 13982 # endif 13983 #endif 13984 #ifdef FEAT_GUI_GNOME 13985 "gui_gnome", 13986 #endif 13987 #ifdef FEAT_GUI_MAC 13988 "gui_mac", 13989 #endif 13990 #ifdef FEAT_GUI_MOTIF 13991 "gui_motif", 13992 #endif 13993 #ifdef FEAT_GUI_PHOTON 13994 "gui_photon", 13995 #endif 13996 #ifdef FEAT_GUI_W32 13997 "gui_win32", 13998 #endif 13999 #ifdef FEAT_HANGULIN 14000 "hangul_input", 14001 #endif 14002 #if defined(HAVE_ICONV_H) && defined(USE_ICONV) 14003 "iconv", 14004 #endif 14005 #ifdef FEAT_INS_EXPAND 14006 "insert_expand", 14007 #endif 14008 #ifdef FEAT_JOB_CHANNEL 14009 "job", 14010 #endif 14011 #ifdef FEAT_JUMPLIST 14012 "jumplist", 14013 #endif 14014 #ifdef FEAT_KEYMAP 14015 "keymap", 14016 #endif 14017 #ifdef FEAT_LANGMAP 14018 "langmap", 14019 #endif 14020 #ifdef FEAT_LIBCALL 14021 "libcall", 14022 #endif 14023 #ifdef FEAT_LINEBREAK 14024 "linebreak", 14025 #endif 14026 #ifdef FEAT_LISP 14027 "lispindent", 14028 #endif 14029 #ifdef FEAT_LISTCMDS 14030 "listcmds", 14031 #endif 14032 #ifdef FEAT_LOCALMAP 14033 "localmap", 14034 #endif 14035 #ifdef FEAT_LUA 14036 # ifndef DYNAMIC_LUA 14037 "lua", 14038 # endif 14039 #endif 14040 #ifdef FEAT_MENU 14041 "menu", 14042 #endif 14043 #ifdef FEAT_SESSION 14044 "mksession", 14045 #endif 14046 #ifdef FEAT_MODIFY_FNAME 14047 "modify_fname", 14048 #endif 14049 #ifdef FEAT_MOUSE 14050 "mouse", 14051 #endif 14052 #ifdef FEAT_MOUSESHAPE 14053 "mouseshape", 14054 #endif 14055 #if defined(UNIX) || defined(VMS) 14056 # ifdef FEAT_MOUSE_DEC 14057 "mouse_dec", 14058 # endif 14059 # ifdef FEAT_MOUSE_GPM 14060 "mouse_gpm", 14061 # endif 14062 # ifdef FEAT_MOUSE_JSB 14063 "mouse_jsbterm", 14064 # endif 14065 # ifdef FEAT_MOUSE_NET 14066 "mouse_netterm", 14067 # endif 14068 # ifdef FEAT_MOUSE_PTERM 14069 "mouse_pterm", 14070 # endif 14071 # ifdef FEAT_MOUSE_SGR 14072 "mouse_sgr", 14073 # endif 14074 # ifdef FEAT_SYSMOUSE 14075 "mouse_sysmouse", 14076 # endif 14077 # ifdef FEAT_MOUSE_URXVT 14078 "mouse_urxvt", 14079 # endif 14080 # ifdef FEAT_MOUSE_XTERM 14081 "mouse_xterm", 14082 # endif 14083 #endif 14084 #ifdef FEAT_MBYTE 14085 "multi_byte", 14086 #endif 14087 #ifdef FEAT_MBYTE_IME 14088 "multi_byte_ime", 14089 #endif 14090 #ifdef FEAT_MULTI_LANG 14091 "multi_lang", 14092 #endif 14093 #ifdef FEAT_MZSCHEME 14094 #ifndef DYNAMIC_MZSCHEME 14095 "mzscheme", 14096 #endif 14097 #endif 14098 #ifdef FEAT_OLE 14099 "ole", 14100 #endif 14101 "packages", 14102 #ifdef FEAT_PATH_EXTRA 14103 "path_extra", 14104 #endif 14105 #ifdef FEAT_PERL 14106 #ifndef DYNAMIC_PERL 14107 "perl", 14108 #endif 14109 #endif 14110 #ifdef FEAT_PERSISTENT_UNDO 14111 "persistent_undo", 14112 #endif 14113 #ifdef FEAT_PYTHON 14114 #ifndef DYNAMIC_PYTHON 14115 "python", 14116 #endif 14117 #endif 14118 #ifdef FEAT_PYTHON3 14119 #ifndef DYNAMIC_PYTHON3 14120 "python3", 14121 #endif 14122 #endif 14123 #ifdef FEAT_POSTSCRIPT 14124 "postscript", 14125 #endif 14126 #ifdef FEAT_PRINTER 14127 "printer", 14128 #endif 14129 #ifdef FEAT_PROFILE 14130 "profile", 14131 #endif 14132 #ifdef FEAT_RELTIME 14133 "reltime", 14134 #endif 14135 #ifdef FEAT_QUICKFIX 14136 "quickfix", 14137 #endif 14138 #ifdef FEAT_RIGHTLEFT 14139 "rightleft", 14140 #endif 14141 #if defined(FEAT_RUBY) && !defined(DYNAMIC_RUBY) 14142 "ruby", 14143 #endif 14144 #ifdef FEAT_SCROLLBIND 14145 "scrollbind", 14146 #endif 14147 #ifdef FEAT_CMDL_INFO 14148 "showcmd", 14149 "cmdline_info", 14150 #endif 14151 #ifdef FEAT_SIGNS 14152 "signs", 14153 #endif 14154 #ifdef FEAT_SMARTINDENT 14155 "smartindent", 14156 #endif 14157 #ifdef STARTUPTIME 14158 "startuptime", 14159 #endif 14160 #ifdef FEAT_STL_OPT 14161 "statusline", 14162 #endif 14163 #ifdef FEAT_SUN_WORKSHOP 14164 "sun_workshop", 14165 #endif 14166 #ifdef FEAT_NETBEANS_INTG 14167 "netbeans_intg", 14168 #endif 14169 #ifdef FEAT_SPELL 14170 "spell", 14171 #endif 14172 #ifdef FEAT_SYN_HL 14173 "syntax", 14174 #endif 14175 #if defined(USE_SYSTEM) || !defined(UNIX) 14176 "system", 14177 #endif 14178 #ifdef FEAT_TAG_BINS 14179 "tag_binary", 14180 #endif 14181 #ifdef FEAT_TAG_OLDSTATIC 14182 "tag_old_static", 14183 #endif 14184 #ifdef FEAT_TAG_ANYWHITE 14185 "tag_any_white", 14186 #endif 14187 #ifdef FEAT_TCL 14188 # ifndef DYNAMIC_TCL 14189 "tcl", 14190 # endif 14191 #endif 14192 #ifdef FEAT_TERMGUICOLORS 14193 "termguicolors", 14194 #endif 14195 #ifdef TERMINFO 14196 "terminfo", 14197 #endif 14198 #ifdef FEAT_TERMRESPONSE 14199 "termresponse", 14200 #endif 14201 #ifdef FEAT_TEXTOBJ 14202 "textobjects", 14203 #endif 14204 #ifdef HAVE_TGETENT 14205 "tgetent", 14206 #endif 14207 #ifdef FEAT_TIMERS 14208 "timers", 14209 #endif 14210 #ifdef FEAT_TITLE 14211 "title", 14212 #endif 14213 #ifdef FEAT_TOOLBAR 14214 "toolbar", 14215 #endif 14216 #if defined(FEAT_CLIPBOARD) && defined(FEAT_X11) 14217 "unnamedplus", 14218 #endif 14219 #ifdef FEAT_USR_CMDS 14220 "user-commands", /* was accidentally included in 5.4 */ 14221 "user_commands", 14222 #endif 14223 #ifdef FEAT_VIMINFO 14224 "viminfo", 14225 #endif 14226 #ifdef FEAT_WINDOWS 14227 "vertsplit", 14228 #endif 14229 #ifdef FEAT_VIRTUALEDIT 14230 "virtualedit", 14231 #endif 14232 "visual", 14233 #ifdef FEAT_VISUALEXTRA 14234 "visualextra", 14235 #endif 14236 #ifdef FEAT_VREPLACE 14237 "vreplace", 14238 #endif 14239 #ifdef FEAT_WILDIGN 14240 "wildignore", 14241 #endif 14242 #ifdef FEAT_WILDMENU 14243 "wildmenu", 14244 #endif 14245 #ifdef FEAT_WINDOWS 14246 "windows", 14247 #endif 14248 #ifdef FEAT_WAK 14249 "winaltkeys", 14250 #endif 14251 #ifdef FEAT_WRITEBACKUP 14252 "writebackup", 14253 #endif 14254 #ifdef FEAT_XIM 14255 "xim", 14256 #endif 14257 #ifdef FEAT_XFONTSET 14258 "xfontset", 14259 #endif 14260 #ifdef FEAT_XPM_W32 14261 "xpm", 14262 "xpm_w32", /* for backward compatibility */ 14263 #else 14264 # if defined(HAVE_XPM) 14265 "xpm", 14266 # endif 14267 #endif 14268 #ifdef USE_XSMP 14269 "xsmp", 14270 #endif 14271 #ifdef USE_XSMP_INTERACT 14272 "xsmp_interact", 14273 #endif 14274 #ifdef FEAT_XCLIPBOARD 14275 "xterm_clipboard", 14276 #endif 14277 #ifdef FEAT_XTERM_SAVE 14278 "xterm_save", 14279 #endif 14280 #if defined(UNIX) && defined(FEAT_X11) 14281 "X11", 14282 #endif 14283 NULL 14284 }; 14285 14286 name = get_tv_string(&argvars[0]); 14287 for (i = 0; has_list[i] != NULL; ++i) 14288 if (STRICMP(name, has_list[i]) == 0) 14289 { 14290 n = TRUE; 14291 break; 14292 } 14293 14294 if (n == FALSE) 14295 { 14296 if (STRNICMP(name, "patch", 5) == 0) 14297 { 14298 if (name[5] == '-' 14299 && STRLEN(name) >= 11 14300 && vim_isdigit(name[6]) 14301 && vim_isdigit(name[8]) 14302 && vim_isdigit(name[10])) 14303 { 14304 int major = atoi((char *)name + 6); 14305 int minor = atoi((char *)name + 8); 14306 14307 /* Expect "patch-9.9.01234". */ 14308 n = (major < VIM_VERSION_MAJOR 14309 || (major == VIM_VERSION_MAJOR 14310 && (minor < VIM_VERSION_MINOR 14311 || (minor == VIM_VERSION_MINOR 14312 && has_patch(atoi((char *)name + 10)))))); 14313 } 14314 else 14315 n = has_patch(atoi((char *)name + 5)); 14316 } 14317 else if (STRICMP(name, "vim_starting") == 0) 14318 n = (starting != 0); 14319 #ifdef FEAT_MBYTE 14320 else if (STRICMP(name, "multi_byte_encoding") == 0) 14321 n = has_mbyte; 14322 #endif 14323 #if defined(FEAT_BEVAL) && defined(FEAT_GUI_W32) 14324 else if (STRICMP(name, "balloon_multiline") == 0) 14325 n = multiline_balloon_available(); 14326 #endif 14327 #ifdef DYNAMIC_TCL 14328 else if (STRICMP(name, "tcl") == 0) 14329 n = tcl_enabled(FALSE); 14330 #endif 14331 #if defined(USE_ICONV) && defined(DYNAMIC_ICONV) 14332 else if (STRICMP(name, "iconv") == 0) 14333 n = iconv_enabled(FALSE); 14334 #endif 14335 #ifdef DYNAMIC_LUA 14336 else if (STRICMP(name, "lua") == 0) 14337 n = lua_enabled(FALSE); 14338 #endif 14339 #ifdef DYNAMIC_MZSCHEME 14340 else if (STRICMP(name, "mzscheme") == 0) 14341 n = mzscheme_enabled(FALSE); 14342 #endif 14343 #ifdef DYNAMIC_RUBY 14344 else if (STRICMP(name, "ruby") == 0) 14345 n = ruby_enabled(FALSE); 14346 #endif 14347 #ifdef FEAT_PYTHON 14348 #ifdef DYNAMIC_PYTHON 14349 else if (STRICMP(name, "python") == 0) 14350 n = python_enabled(FALSE); 14351 #endif 14352 #endif 14353 #ifdef FEAT_PYTHON3 14354 #ifdef DYNAMIC_PYTHON3 14355 else if (STRICMP(name, "python3") == 0) 14356 n = python3_enabled(FALSE); 14357 #endif 14358 #endif 14359 #ifdef DYNAMIC_PERL 14360 else if (STRICMP(name, "perl") == 0) 14361 n = perl_enabled(FALSE); 14362 #endif 14363 #ifdef FEAT_GUI 14364 else if (STRICMP(name, "gui_running") == 0) 14365 n = (gui.in_use || gui.starting); 14366 # ifdef FEAT_GUI_W32 14367 else if (STRICMP(name, "gui_win32s") == 0) 14368 n = gui_is_win32s(); 14369 # endif 14370 # ifdef FEAT_BROWSE 14371 else if (STRICMP(name, "browse") == 0) 14372 n = gui.in_use; /* gui_mch_browse() works when GUI is running */ 14373 # endif 14374 #endif 14375 #ifdef FEAT_SYN_HL 14376 else if (STRICMP(name, "syntax_items") == 0) 14377 n = syntax_present(curwin); 14378 #endif 14379 #if defined(WIN3264) 14380 else if (STRICMP(name, "win95") == 0) 14381 n = mch_windows95(); 14382 #endif 14383 #ifdef FEAT_NETBEANS_INTG 14384 else if (STRICMP(name, "netbeans_enabled") == 0) 14385 n = netbeans_active(); 14386 #endif 14387 } 14388 14389 rettv->vval.v_number = n; 14390 } 14391 14392 /* 14393 * "has_key()" function 14394 */ 14395 static void 14396 f_has_key(typval_T *argvars, typval_T *rettv) 14397 { 14398 if (argvars[0].v_type != VAR_DICT) 14399 { 14400 EMSG(_(e_dictreq)); 14401 return; 14402 } 14403 if (argvars[0].vval.v_dict == NULL) 14404 return; 14405 14406 rettv->vval.v_number = dict_find(argvars[0].vval.v_dict, 14407 get_tv_string(&argvars[1]), -1) != NULL; 14408 } 14409 14410 /* 14411 * "haslocaldir()" function 14412 */ 14413 static void 14414 f_haslocaldir(typval_T *argvars, typval_T *rettv) 14415 { 14416 win_T *wp = NULL; 14417 14418 wp = find_tabwin(&argvars[0], &argvars[1]); 14419 rettv->vval.v_number = (wp != NULL && wp->w_localdir != NULL); 14420 } 14421 14422 /* 14423 * "hasmapto()" function 14424 */ 14425 static void 14426 f_hasmapto(typval_T *argvars, typval_T *rettv) 14427 { 14428 char_u *name; 14429 char_u *mode; 14430 char_u buf[NUMBUFLEN]; 14431 int abbr = FALSE; 14432 14433 name = get_tv_string(&argvars[0]); 14434 if (argvars[1].v_type == VAR_UNKNOWN) 14435 mode = (char_u *)"nvo"; 14436 else 14437 { 14438 mode = get_tv_string_buf(&argvars[1], buf); 14439 if (argvars[2].v_type != VAR_UNKNOWN) 14440 abbr = get_tv_number(&argvars[2]); 14441 } 14442 14443 if (map_to_exists(name, mode, abbr)) 14444 rettv->vval.v_number = TRUE; 14445 else 14446 rettv->vval.v_number = FALSE; 14447 } 14448 14449 /* 14450 * "histadd()" function 14451 */ 14452 static void 14453 f_histadd(typval_T *argvars UNUSED, typval_T *rettv) 14454 { 14455 #ifdef FEAT_CMDHIST 14456 int histype; 14457 char_u *str; 14458 char_u buf[NUMBUFLEN]; 14459 #endif 14460 14461 rettv->vval.v_number = FALSE; 14462 if (check_restricted() || check_secure()) 14463 return; 14464 #ifdef FEAT_CMDHIST 14465 str = get_tv_string_chk(&argvars[0]); /* NULL on type error */ 14466 histype = str != NULL ? get_histtype(str) : -1; 14467 if (histype >= 0) 14468 { 14469 str = get_tv_string_buf(&argvars[1], buf); 14470 if (*str != NUL) 14471 { 14472 init_history(); 14473 add_to_history(histype, str, FALSE, NUL); 14474 rettv->vval.v_number = TRUE; 14475 return; 14476 } 14477 } 14478 #endif 14479 } 14480 14481 /* 14482 * "histdel()" function 14483 */ 14484 static void 14485 f_histdel(typval_T *argvars UNUSED, typval_T *rettv UNUSED) 14486 { 14487 #ifdef FEAT_CMDHIST 14488 int n; 14489 char_u buf[NUMBUFLEN]; 14490 char_u *str; 14491 14492 str = get_tv_string_chk(&argvars[0]); /* NULL on type error */ 14493 if (str == NULL) 14494 n = 0; 14495 else if (argvars[1].v_type == VAR_UNKNOWN) 14496 /* only one argument: clear entire history */ 14497 n = clr_history(get_histtype(str)); 14498 else if (argvars[1].v_type == VAR_NUMBER) 14499 /* index given: remove that entry */ 14500 n = del_history_idx(get_histtype(str), 14501 (int)get_tv_number(&argvars[1])); 14502 else 14503 /* string given: remove all matching entries */ 14504 n = del_history_entry(get_histtype(str), 14505 get_tv_string_buf(&argvars[1], buf)); 14506 rettv->vval.v_number = n; 14507 #endif 14508 } 14509 14510 /* 14511 * "histget()" function 14512 */ 14513 static void 14514 f_histget(typval_T *argvars UNUSED, typval_T *rettv) 14515 { 14516 #ifdef FEAT_CMDHIST 14517 int type; 14518 int idx; 14519 char_u *str; 14520 14521 str = get_tv_string_chk(&argvars[0]); /* NULL on type error */ 14522 if (str == NULL) 14523 rettv->vval.v_string = NULL; 14524 else 14525 { 14526 type = get_histtype(str); 14527 if (argvars[1].v_type == VAR_UNKNOWN) 14528 idx = get_history_idx(type); 14529 else 14530 idx = (int)get_tv_number_chk(&argvars[1], NULL); 14531 /* -1 on type error */ 14532 rettv->vval.v_string = vim_strsave(get_history_entry(type, idx)); 14533 } 14534 #else 14535 rettv->vval.v_string = NULL; 14536 #endif 14537 rettv->v_type = VAR_STRING; 14538 } 14539 14540 /* 14541 * "histnr()" function 14542 */ 14543 static void 14544 f_histnr(typval_T *argvars UNUSED, typval_T *rettv) 14545 { 14546 int i; 14547 14548 #ifdef FEAT_CMDHIST 14549 char_u *history = get_tv_string_chk(&argvars[0]); 14550 14551 i = history == NULL ? HIST_CMD - 1 : get_histtype(history); 14552 if (i >= HIST_CMD && i < HIST_COUNT) 14553 i = get_history_idx(i); 14554 else 14555 #endif 14556 i = -1; 14557 rettv->vval.v_number = i; 14558 } 14559 14560 /* 14561 * "highlightID(name)" function 14562 */ 14563 static void 14564 f_hlID(typval_T *argvars, typval_T *rettv) 14565 { 14566 rettv->vval.v_number = syn_name2id(get_tv_string(&argvars[0])); 14567 } 14568 14569 /* 14570 * "highlight_exists()" function 14571 */ 14572 static void 14573 f_hlexists(typval_T *argvars, typval_T *rettv) 14574 { 14575 rettv->vval.v_number = highlight_exists(get_tv_string(&argvars[0])); 14576 } 14577 14578 /* 14579 * "hostname()" function 14580 */ 14581 static void 14582 f_hostname(typval_T *argvars UNUSED, typval_T *rettv) 14583 { 14584 char_u hostname[256]; 14585 14586 mch_get_host_name(hostname, 256); 14587 rettv->v_type = VAR_STRING; 14588 rettv->vval.v_string = vim_strsave(hostname); 14589 } 14590 14591 /* 14592 * iconv() function 14593 */ 14594 static void 14595 f_iconv(typval_T *argvars UNUSED, typval_T *rettv) 14596 { 14597 #ifdef FEAT_MBYTE 14598 char_u buf1[NUMBUFLEN]; 14599 char_u buf2[NUMBUFLEN]; 14600 char_u *from, *to, *str; 14601 vimconv_T vimconv; 14602 #endif 14603 14604 rettv->v_type = VAR_STRING; 14605 rettv->vval.v_string = NULL; 14606 14607 #ifdef FEAT_MBYTE 14608 str = get_tv_string(&argvars[0]); 14609 from = enc_canonize(enc_skip(get_tv_string_buf(&argvars[1], buf1))); 14610 to = enc_canonize(enc_skip(get_tv_string_buf(&argvars[2], buf2))); 14611 vimconv.vc_type = CONV_NONE; 14612 convert_setup(&vimconv, from, to); 14613 14614 /* If the encodings are equal, no conversion needed. */ 14615 if (vimconv.vc_type == CONV_NONE) 14616 rettv->vval.v_string = vim_strsave(str); 14617 else 14618 rettv->vval.v_string = string_convert(&vimconv, str, NULL); 14619 14620 convert_setup(&vimconv, NULL, NULL); 14621 vim_free(from); 14622 vim_free(to); 14623 #endif 14624 } 14625 14626 /* 14627 * "indent()" function 14628 */ 14629 static void 14630 f_indent(typval_T *argvars, typval_T *rettv) 14631 { 14632 linenr_T lnum; 14633 14634 lnum = get_tv_lnum(argvars); 14635 if (lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count) 14636 rettv->vval.v_number = get_indent_lnum(lnum); 14637 else 14638 rettv->vval.v_number = -1; 14639 } 14640 14641 /* 14642 * "index()" function 14643 */ 14644 static void 14645 f_index(typval_T *argvars, typval_T *rettv) 14646 { 14647 list_T *l; 14648 listitem_T *item; 14649 long idx = 0; 14650 int ic = FALSE; 14651 14652 rettv->vval.v_number = -1; 14653 if (argvars[0].v_type != VAR_LIST) 14654 { 14655 EMSG(_(e_listreq)); 14656 return; 14657 } 14658 l = argvars[0].vval.v_list; 14659 if (l != NULL) 14660 { 14661 item = l->lv_first; 14662 if (argvars[2].v_type != VAR_UNKNOWN) 14663 { 14664 int error = FALSE; 14665 14666 /* Start at specified item. Use the cached index that list_find() 14667 * sets, so that a negative number also works. */ 14668 item = list_find(l, get_tv_number_chk(&argvars[2], &error)); 14669 idx = l->lv_idx; 14670 if (argvars[3].v_type != VAR_UNKNOWN) 14671 ic = get_tv_number_chk(&argvars[3], &error); 14672 if (error) 14673 item = NULL; 14674 } 14675 14676 for ( ; item != NULL; item = item->li_next, ++idx) 14677 if (tv_equal(&item->li_tv, &argvars[1], ic, FALSE)) 14678 { 14679 rettv->vval.v_number = idx; 14680 break; 14681 } 14682 } 14683 } 14684 14685 static int inputsecret_flag = 0; 14686 14687 static void get_user_input(typval_T *argvars, typval_T *rettv, int inputdialog); 14688 14689 /* 14690 * This function is used by f_input() and f_inputdialog() functions. The third 14691 * argument to f_input() specifies the type of completion to use at the 14692 * prompt. The third argument to f_inputdialog() specifies the value to return 14693 * when the user cancels the prompt. 14694 */ 14695 static void 14696 get_user_input( 14697 typval_T *argvars, 14698 typval_T *rettv, 14699 int inputdialog) 14700 { 14701 char_u *prompt = get_tv_string_chk(&argvars[0]); 14702 char_u *p = NULL; 14703 int c; 14704 char_u buf[NUMBUFLEN]; 14705 int cmd_silent_save = cmd_silent; 14706 char_u *defstr = (char_u *)""; 14707 int xp_type = EXPAND_NOTHING; 14708 char_u *xp_arg = NULL; 14709 14710 rettv->v_type = VAR_STRING; 14711 rettv->vval.v_string = NULL; 14712 14713 #ifdef NO_CONSOLE_INPUT 14714 /* While starting up, there is no place to enter text. */ 14715 if (no_console_input()) 14716 return; 14717 #endif 14718 14719 cmd_silent = FALSE; /* Want to see the prompt. */ 14720 if (prompt != NULL) 14721 { 14722 /* Only the part of the message after the last NL is considered as 14723 * prompt for the command line */ 14724 p = vim_strrchr(prompt, '\n'); 14725 if (p == NULL) 14726 p = prompt; 14727 else 14728 { 14729 ++p; 14730 c = *p; 14731 *p = NUL; 14732 msg_start(); 14733 msg_clr_eos(); 14734 msg_puts_attr(prompt, echo_attr); 14735 msg_didout = FALSE; 14736 msg_starthere(); 14737 *p = c; 14738 } 14739 cmdline_row = msg_row; 14740 14741 if (argvars[1].v_type != VAR_UNKNOWN) 14742 { 14743 defstr = get_tv_string_buf_chk(&argvars[1], buf); 14744 if (defstr != NULL) 14745 stuffReadbuffSpec(defstr); 14746 14747 if (!inputdialog && argvars[2].v_type != VAR_UNKNOWN) 14748 { 14749 char_u *xp_name; 14750 int xp_namelen; 14751 long argt; 14752 14753 /* input() with a third argument: completion */ 14754 rettv->vval.v_string = NULL; 14755 14756 xp_name = get_tv_string_buf_chk(&argvars[2], buf); 14757 if (xp_name == NULL) 14758 return; 14759 14760 xp_namelen = (int)STRLEN(xp_name); 14761 14762 if (parse_compl_arg(xp_name, xp_namelen, &xp_type, &argt, 14763 &xp_arg) == FAIL) 14764 return; 14765 } 14766 } 14767 14768 if (defstr != NULL) 14769 { 14770 int save_ex_normal_busy = ex_normal_busy; 14771 ex_normal_busy = 0; 14772 rettv->vval.v_string = 14773 getcmdline_prompt(inputsecret_flag ? NUL : '@', p, echo_attr, 14774 xp_type, xp_arg); 14775 ex_normal_busy = save_ex_normal_busy; 14776 } 14777 if (inputdialog && rettv->vval.v_string == NULL 14778 && argvars[1].v_type != VAR_UNKNOWN 14779 && argvars[2].v_type != VAR_UNKNOWN) 14780 rettv->vval.v_string = vim_strsave(get_tv_string_buf( 14781 &argvars[2], buf)); 14782 14783 vim_free(xp_arg); 14784 14785 /* since the user typed this, no need to wait for return */ 14786 need_wait_return = FALSE; 14787 msg_didout = FALSE; 14788 } 14789 cmd_silent = cmd_silent_save; 14790 } 14791 14792 /* 14793 * "input()" function 14794 * Also handles inputsecret() when inputsecret is set. 14795 */ 14796 static void 14797 f_input(typval_T *argvars, typval_T *rettv) 14798 { 14799 get_user_input(argvars, rettv, FALSE); 14800 } 14801 14802 /* 14803 * "inputdialog()" function 14804 */ 14805 static void 14806 f_inputdialog(typval_T *argvars, typval_T *rettv) 14807 { 14808 #if defined(FEAT_GUI_TEXTDIALOG) 14809 /* Use a GUI dialog if the GUI is running and 'c' is not in 'guioptions' */ 14810 if (gui.in_use && vim_strchr(p_go, GO_CONDIALOG) == NULL) 14811 { 14812 char_u *message; 14813 char_u buf[NUMBUFLEN]; 14814 char_u *defstr = (char_u *)""; 14815 14816 message = get_tv_string_chk(&argvars[0]); 14817 if (argvars[1].v_type != VAR_UNKNOWN 14818 && (defstr = get_tv_string_buf_chk(&argvars[1], buf)) != NULL) 14819 vim_strncpy(IObuff, defstr, IOSIZE - 1); 14820 else 14821 IObuff[0] = NUL; 14822 if (message != NULL && defstr != NULL 14823 && do_dialog(VIM_QUESTION, NULL, message, 14824 (char_u *)_("&OK\n&Cancel"), 1, IObuff, FALSE) == 1) 14825 rettv->vval.v_string = vim_strsave(IObuff); 14826 else 14827 { 14828 if (message != NULL && defstr != NULL 14829 && argvars[1].v_type != VAR_UNKNOWN 14830 && argvars[2].v_type != VAR_UNKNOWN) 14831 rettv->vval.v_string = vim_strsave( 14832 get_tv_string_buf(&argvars[2], buf)); 14833 else 14834 rettv->vval.v_string = NULL; 14835 } 14836 rettv->v_type = VAR_STRING; 14837 } 14838 else 14839 #endif 14840 get_user_input(argvars, rettv, TRUE); 14841 } 14842 14843 /* 14844 * "inputlist()" function 14845 */ 14846 static void 14847 f_inputlist(typval_T *argvars, typval_T *rettv) 14848 { 14849 listitem_T *li; 14850 int selected; 14851 int mouse_used; 14852 14853 #ifdef NO_CONSOLE_INPUT 14854 /* While starting up, there is no place to enter text. */ 14855 if (no_console_input()) 14856 return; 14857 #endif 14858 if (argvars[0].v_type != VAR_LIST || argvars[0].vval.v_list == NULL) 14859 { 14860 EMSG2(_(e_listarg), "inputlist()"); 14861 return; 14862 } 14863 14864 msg_start(); 14865 msg_row = Rows - 1; /* for when 'cmdheight' > 1 */ 14866 lines_left = Rows; /* avoid more prompt */ 14867 msg_scroll = TRUE; 14868 msg_clr_eos(); 14869 14870 for (li = argvars[0].vval.v_list->lv_first; li != NULL; li = li->li_next) 14871 { 14872 msg_puts(get_tv_string(&li->li_tv)); 14873 msg_putchar('\n'); 14874 } 14875 14876 /* Ask for choice. */ 14877 selected = prompt_for_number(&mouse_used); 14878 if (mouse_used) 14879 selected -= lines_left; 14880 14881 rettv->vval.v_number = selected; 14882 } 14883 14884 14885 static garray_T ga_userinput = {0, 0, sizeof(tasave_T), 4, NULL}; 14886 14887 /* 14888 * "inputrestore()" function 14889 */ 14890 static void 14891 f_inputrestore(typval_T *argvars UNUSED, typval_T *rettv) 14892 { 14893 if (ga_userinput.ga_len > 0) 14894 { 14895 --ga_userinput.ga_len; 14896 restore_typeahead((tasave_T *)(ga_userinput.ga_data) 14897 + ga_userinput.ga_len); 14898 /* default return is zero == OK */ 14899 } 14900 else if (p_verbose > 1) 14901 { 14902 verb_msg((char_u *)_("called inputrestore() more often than inputsave()")); 14903 rettv->vval.v_number = 1; /* Failed */ 14904 } 14905 } 14906 14907 /* 14908 * "inputsave()" function 14909 */ 14910 static void 14911 f_inputsave(typval_T *argvars UNUSED, typval_T *rettv) 14912 { 14913 /* Add an entry to the stack of typeahead storage. */ 14914 if (ga_grow(&ga_userinput, 1) == OK) 14915 { 14916 save_typeahead((tasave_T *)(ga_userinput.ga_data) 14917 + ga_userinput.ga_len); 14918 ++ga_userinput.ga_len; 14919 /* default return is zero == OK */ 14920 } 14921 else 14922 rettv->vval.v_number = 1; /* Failed */ 14923 } 14924 14925 /* 14926 * "inputsecret()" function 14927 */ 14928 static void 14929 f_inputsecret(typval_T *argvars, typval_T *rettv) 14930 { 14931 ++cmdline_star; 14932 ++inputsecret_flag; 14933 f_input(argvars, rettv); 14934 --cmdline_star; 14935 --inputsecret_flag; 14936 } 14937 14938 /* 14939 * "insert()" function 14940 */ 14941 static void 14942 f_insert(typval_T *argvars, typval_T *rettv) 14943 { 14944 long before = 0; 14945 listitem_T *item; 14946 list_T *l; 14947 int error = FALSE; 14948 14949 if (argvars[0].v_type != VAR_LIST) 14950 EMSG2(_(e_listarg), "insert()"); 14951 else if ((l = argvars[0].vval.v_list) != NULL 14952 && !tv_check_lock(l->lv_lock, (char_u *)N_("insert() argument"), TRUE)) 14953 { 14954 if (argvars[2].v_type != VAR_UNKNOWN) 14955 before = get_tv_number_chk(&argvars[2], &error); 14956 if (error) 14957 return; /* type error; errmsg already given */ 14958 14959 if (before == l->lv_len) 14960 item = NULL; 14961 else 14962 { 14963 item = list_find(l, before); 14964 if (item == NULL) 14965 { 14966 EMSGN(_(e_listidx), before); 14967 l = NULL; 14968 } 14969 } 14970 if (l != NULL) 14971 { 14972 list_insert_tv(l, &argvars[1], item); 14973 copy_tv(&argvars[0], rettv); 14974 } 14975 } 14976 } 14977 14978 /* 14979 * "invert(expr)" function 14980 */ 14981 static void 14982 f_invert(typval_T *argvars, typval_T *rettv) 14983 { 14984 rettv->vval.v_number = ~get_tv_number_chk(&argvars[0], NULL); 14985 } 14986 14987 /* 14988 * "isdirectory()" function 14989 */ 14990 static void 14991 f_isdirectory(typval_T *argvars, typval_T *rettv) 14992 { 14993 rettv->vval.v_number = mch_isdir(get_tv_string(&argvars[0])); 14994 } 14995 14996 /* 14997 * "islocked()" function 14998 */ 14999 static void 15000 f_islocked(typval_T *argvars, typval_T *rettv) 15001 { 15002 lval_T lv; 15003 char_u *end; 15004 dictitem_T *di; 15005 15006 rettv->vval.v_number = -1; 15007 end = get_lval(get_tv_string(&argvars[0]), NULL, &lv, FALSE, FALSE, 15008 GLV_NO_AUTOLOAD, FNE_CHECK_START); 15009 if (end != NULL && lv.ll_name != NULL) 15010 { 15011 if (*end != NUL) 15012 EMSG(_(e_trailing)); 15013 else 15014 { 15015 if (lv.ll_tv == NULL) 15016 { 15017 if (check_changedtick(lv.ll_name)) 15018 rettv->vval.v_number = 1; /* always locked */ 15019 else 15020 { 15021 di = find_var(lv.ll_name, NULL, TRUE); 15022 if (di != NULL) 15023 { 15024 /* Consider a variable locked when: 15025 * 1. the variable itself is locked 15026 * 2. the value of the variable is locked. 15027 * 3. the List or Dict value is locked. 15028 */ 15029 rettv->vval.v_number = ((di->di_flags & DI_FLAGS_LOCK) 15030 || tv_islocked(&di->di_tv)); 15031 } 15032 } 15033 } 15034 else if (lv.ll_range) 15035 EMSG(_("E786: Range not allowed")); 15036 else if (lv.ll_newkey != NULL) 15037 EMSG2(_(e_dictkey), lv.ll_newkey); 15038 else if (lv.ll_list != NULL) 15039 /* List item. */ 15040 rettv->vval.v_number = tv_islocked(&lv.ll_li->li_tv); 15041 else 15042 /* Dictionary item. */ 15043 rettv->vval.v_number = tv_islocked(&lv.ll_di->di_tv); 15044 } 15045 } 15046 15047 clear_lval(&lv); 15048 } 15049 15050 #if defined(FEAT_FLOAT) && defined(HAVE_MATH_H) 15051 /* 15052 * "isnan()" function 15053 */ 15054 static void 15055 f_isnan(typval_T *argvars, typval_T *rettv) 15056 { 15057 rettv->vval.v_number = argvars[0].v_type == VAR_FLOAT 15058 && isnan(argvars[0].vval.v_float); 15059 } 15060 #endif 15061 15062 static void dict_list(typval_T *argvars, typval_T *rettv, int what); 15063 15064 /* 15065 * Turn a dict into a list: 15066 * "what" == 0: list of keys 15067 * "what" == 1: list of values 15068 * "what" == 2: list of items 15069 */ 15070 static void 15071 dict_list(typval_T *argvars, typval_T *rettv, int what) 15072 { 15073 list_T *l2; 15074 dictitem_T *di; 15075 hashitem_T *hi; 15076 listitem_T *li; 15077 listitem_T *li2; 15078 dict_T *d; 15079 int todo; 15080 15081 if (argvars[0].v_type != VAR_DICT) 15082 { 15083 EMSG(_(e_dictreq)); 15084 return; 15085 } 15086 if ((d = argvars[0].vval.v_dict) == NULL) 15087 return; 15088 15089 if (rettv_list_alloc(rettv) == FAIL) 15090 return; 15091 15092 todo = (int)d->dv_hashtab.ht_used; 15093 for (hi = d->dv_hashtab.ht_array; todo > 0; ++hi) 15094 { 15095 if (!HASHITEM_EMPTY(hi)) 15096 { 15097 --todo; 15098 di = HI2DI(hi); 15099 15100 li = listitem_alloc(); 15101 if (li == NULL) 15102 break; 15103 list_append(rettv->vval.v_list, li); 15104 15105 if (what == 0) 15106 { 15107 /* keys() */ 15108 li->li_tv.v_type = VAR_STRING; 15109 li->li_tv.v_lock = 0; 15110 li->li_tv.vval.v_string = vim_strsave(di->di_key); 15111 } 15112 else if (what == 1) 15113 { 15114 /* values() */ 15115 copy_tv(&di->di_tv, &li->li_tv); 15116 } 15117 else 15118 { 15119 /* items() */ 15120 l2 = list_alloc(); 15121 li->li_tv.v_type = VAR_LIST; 15122 li->li_tv.v_lock = 0; 15123 li->li_tv.vval.v_list = l2; 15124 if (l2 == NULL) 15125 break; 15126 ++l2->lv_refcount; 15127 15128 li2 = listitem_alloc(); 15129 if (li2 == NULL) 15130 break; 15131 list_append(l2, li2); 15132 li2->li_tv.v_type = VAR_STRING; 15133 li2->li_tv.v_lock = 0; 15134 li2->li_tv.vval.v_string = vim_strsave(di->di_key); 15135 15136 li2 = listitem_alloc(); 15137 if (li2 == NULL) 15138 break; 15139 list_append(l2, li2); 15140 copy_tv(&di->di_tv, &li2->li_tv); 15141 } 15142 } 15143 } 15144 } 15145 15146 /* 15147 * "items(dict)" function 15148 */ 15149 static void 15150 f_items(typval_T *argvars, typval_T *rettv) 15151 { 15152 dict_list(argvars, rettv, 2); 15153 } 15154 15155 #if defined(FEAT_JOB_CHANNEL) || defined(PROTO) 15156 /* 15157 * Get the job from the argument. 15158 * Returns NULL if the job is invalid. 15159 */ 15160 static job_T * 15161 get_job_arg(typval_T *tv) 15162 { 15163 job_T *job; 15164 15165 if (tv->v_type != VAR_JOB) 15166 { 15167 EMSG2(_(e_invarg2), get_tv_string(tv)); 15168 return NULL; 15169 } 15170 job = tv->vval.v_job; 15171 15172 if (job == NULL) 15173 EMSG(_("E916: not a valid job")); 15174 return job; 15175 } 15176 15177 /* 15178 * "job_getchannel()" function 15179 */ 15180 static void 15181 f_job_getchannel(typval_T *argvars, typval_T *rettv) 15182 { 15183 job_T *job = get_job_arg(&argvars[0]); 15184 15185 if (job != NULL) 15186 { 15187 rettv->v_type = VAR_CHANNEL; 15188 rettv->vval.v_channel = job->jv_channel; 15189 if (job->jv_channel != NULL) 15190 ++job->jv_channel->ch_refcount; 15191 } 15192 } 15193 15194 /* 15195 * "job_info()" function 15196 */ 15197 static void 15198 f_job_info(typval_T *argvars, typval_T *rettv) 15199 { 15200 job_T *job = get_job_arg(&argvars[0]); 15201 15202 if (job != NULL && rettv_dict_alloc(rettv) != FAIL) 15203 job_info(job, rettv->vval.v_dict); 15204 } 15205 15206 /* 15207 * "job_setoptions()" function 15208 */ 15209 static void 15210 f_job_setoptions(typval_T *argvars, typval_T *rettv UNUSED) 15211 { 15212 job_T *job = get_job_arg(&argvars[0]); 15213 jobopt_T opt; 15214 15215 if (job == NULL) 15216 return; 15217 clear_job_options(&opt); 15218 if (get_job_options(&argvars[1], &opt, JO_STOPONEXIT + JO_EXIT_CB) == OK) 15219 job_set_options(job, &opt); 15220 free_job_options(&opt); 15221 } 15222 15223 /* 15224 * "job_start()" function 15225 */ 15226 static void 15227 f_job_start(typval_T *argvars, typval_T *rettv) 15228 { 15229 rettv->v_type = VAR_JOB; 15230 if (check_restricted() || check_secure()) 15231 return; 15232 rettv->vval.v_job = job_start(argvars); 15233 } 15234 15235 /* 15236 * "job_status()" function 15237 */ 15238 static void 15239 f_job_status(typval_T *argvars, typval_T *rettv) 15240 { 15241 job_T *job = get_job_arg(&argvars[0]); 15242 15243 if (job != NULL) 15244 { 15245 rettv->v_type = VAR_STRING; 15246 rettv->vval.v_string = vim_strsave((char_u *)job_status(job)); 15247 } 15248 } 15249 15250 /* 15251 * "job_stop()" function 15252 */ 15253 static void 15254 f_job_stop(typval_T *argvars, typval_T *rettv) 15255 { 15256 job_T *job = get_job_arg(&argvars[0]); 15257 15258 if (job != NULL) 15259 rettv->vval.v_number = job_stop(job, argvars); 15260 } 15261 #endif 15262 15263 /* 15264 * "join()" function 15265 */ 15266 static void 15267 f_join(typval_T *argvars, typval_T *rettv) 15268 { 15269 garray_T ga; 15270 char_u *sep; 15271 15272 if (argvars[0].v_type != VAR_LIST) 15273 { 15274 EMSG(_(e_listreq)); 15275 return; 15276 } 15277 if (argvars[0].vval.v_list == NULL) 15278 return; 15279 if (argvars[1].v_type == VAR_UNKNOWN) 15280 sep = (char_u *)" "; 15281 else 15282 sep = get_tv_string_chk(&argvars[1]); 15283 15284 rettv->v_type = VAR_STRING; 15285 15286 if (sep != NULL) 15287 { 15288 ga_init2(&ga, (int)sizeof(char), 80); 15289 list_join(&ga, argvars[0].vval.v_list, sep, TRUE, FALSE, 0); 15290 ga_append(&ga, NUL); 15291 rettv->vval.v_string = (char_u *)ga.ga_data; 15292 } 15293 else 15294 rettv->vval.v_string = NULL; 15295 } 15296 15297 /* 15298 * "js_decode()" function 15299 */ 15300 static void 15301 f_js_decode(typval_T *argvars, typval_T *rettv) 15302 { 15303 js_read_T reader; 15304 15305 reader.js_buf = get_tv_string(&argvars[0]); 15306 reader.js_fill = NULL; 15307 reader.js_used = 0; 15308 if (json_decode_all(&reader, rettv, JSON_JS) != OK) 15309 EMSG(_(e_invarg)); 15310 } 15311 15312 /* 15313 * "js_encode()" function 15314 */ 15315 static void 15316 f_js_encode(typval_T *argvars, typval_T *rettv) 15317 { 15318 rettv->v_type = VAR_STRING; 15319 rettv->vval.v_string = json_encode(&argvars[0], JSON_JS); 15320 } 15321 15322 /* 15323 * "json_decode()" function 15324 */ 15325 static void 15326 f_json_decode(typval_T *argvars, typval_T *rettv) 15327 { 15328 js_read_T reader; 15329 15330 reader.js_buf = get_tv_string(&argvars[0]); 15331 reader.js_fill = NULL; 15332 reader.js_used = 0; 15333 if (json_decode_all(&reader, rettv, 0) != OK) 15334 EMSG(_(e_invarg)); 15335 } 15336 15337 /* 15338 * "json_encode()" function 15339 */ 15340 static void 15341 f_json_encode(typval_T *argvars, typval_T *rettv) 15342 { 15343 rettv->v_type = VAR_STRING; 15344 rettv->vval.v_string = json_encode(&argvars[0], 0); 15345 } 15346 15347 /* 15348 * "keys()" function 15349 */ 15350 static void 15351 f_keys(typval_T *argvars, typval_T *rettv) 15352 { 15353 dict_list(argvars, rettv, 0); 15354 } 15355 15356 /* 15357 * "last_buffer_nr()" function. 15358 */ 15359 static void 15360 f_last_buffer_nr(typval_T *argvars UNUSED, typval_T *rettv) 15361 { 15362 int n = 0; 15363 buf_T *buf; 15364 15365 for (buf = firstbuf; buf != NULL; buf = buf->b_next) 15366 if (n < buf->b_fnum) 15367 n = buf->b_fnum; 15368 15369 rettv->vval.v_number = n; 15370 } 15371 15372 /* 15373 * "len()" function 15374 */ 15375 static void 15376 f_len(typval_T *argvars, typval_T *rettv) 15377 { 15378 switch (argvars[0].v_type) 15379 { 15380 case VAR_STRING: 15381 case VAR_NUMBER: 15382 rettv->vval.v_number = (varnumber_T)STRLEN( 15383 get_tv_string(&argvars[0])); 15384 break; 15385 case VAR_LIST: 15386 rettv->vval.v_number = list_len(argvars[0].vval.v_list); 15387 break; 15388 case VAR_DICT: 15389 rettv->vval.v_number = dict_len(argvars[0].vval.v_dict); 15390 break; 15391 case VAR_UNKNOWN: 15392 case VAR_SPECIAL: 15393 case VAR_FLOAT: 15394 case VAR_FUNC: 15395 case VAR_PARTIAL: 15396 case VAR_JOB: 15397 case VAR_CHANNEL: 15398 EMSG(_("E701: Invalid type for len()")); 15399 break; 15400 } 15401 } 15402 15403 static void libcall_common(typval_T *argvars, typval_T *rettv, int type); 15404 15405 static void 15406 libcall_common(typval_T *argvars, typval_T *rettv, int type) 15407 { 15408 #ifdef FEAT_LIBCALL 15409 char_u *string_in; 15410 char_u **string_result; 15411 int nr_result; 15412 #endif 15413 15414 rettv->v_type = type; 15415 if (type != VAR_NUMBER) 15416 rettv->vval.v_string = NULL; 15417 15418 if (check_restricted() || check_secure()) 15419 return; 15420 15421 #ifdef FEAT_LIBCALL 15422 /* The first two args must be strings, otherwise its meaningless */ 15423 if (argvars[0].v_type == VAR_STRING && argvars[1].v_type == VAR_STRING) 15424 { 15425 string_in = NULL; 15426 if (argvars[2].v_type == VAR_STRING) 15427 string_in = argvars[2].vval.v_string; 15428 if (type == VAR_NUMBER) 15429 string_result = NULL; 15430 else 15431 string_result = &rettv->vval.v_string; 15432 if (mch_libcall(argvars[0].vval.v_string, 15433 argvars[1].vval.v_string, 15434 string_in, 15435 argvars[2].vval.v_number, 15436 string_result, 15437 &nr_result) == OK 15438 && type == VAR_NUMBER) 15439 rettv->vval.v_number = nr_result; 15440 } 15441 #endif 15442 } 15443 15444 /* 15445 * "libcall()" function 15446 */ 15447 static void 15448 f_libcall(typval_T *argvars, typval_T *rettv) 15449 { 15450 libcall_common(argvars, rettv, VAR_STRING); 15451 } 15452 15453 /* 15454 * "libcallnr()" function 15455 */ 15456 static void 15457 f_libcallnr(typval_T *argvars, typval_T *rettv) 15458 { 15459 libcall_common(argvars, rettv, VAR_NUMBER); 15460 } 15461 15462 /* 15463 * "line(string)" function 15464 */ 15465 static void 15466 f_line(typval_T *argvars, typval_T *rettv) 15467 { 15468 linenr_T lnum = 0; 15469 pos_T *fp; 15470 int fnum; 15471 15472 fp = var2fpos(&argvars[0], TRUE, &fnum); 15473 if (fp != NULL) 15474 lnum = fp->lnum; 15475 rettv->vval.v_number = lnum; 15476 } 15477 15478 /* 15479 * "line2byte(lnum)" function 15480 */ 15481 static void 15482 f_line2byte(typval_T *argvars UNUSED, typval_T *rettv) 15483 { 15484 #ifndef FEAT_BYTEOFF 15485 rettv->vval.v_number = -1; 15486 #else 15487 linenr_T lnum; 15488 15489 lnum = get_tv_lnum(argvars); 15490 if (lnum < 1 || lnum > curbuf->b_ml.ml_line_count + 1) 15491 rettv->vval.v_number = -1; 15492 else 15493 rettv->vval.v_number = ml_find_line_or_offset(curbuf, lnum, NULL); 15494 if (rettv->vval.v_number >= 0) 15495 ++rettv->vval.v_number; 15496 #endif 15497 } 15498 15499 /* 15500 * "lispindent(lnum)" function 15501 */ 15502 static void 15503 f_lispindent(typval_T *argvars UNUSED, typval_T *rettv) 15504 { 15505 #ifdef FEAT_LISP 15506 pos_T pos; 15507 linenr_T lnum; 15508 15509 pos = curwin->w_cursor; 15510 lnum = get_tv_lnum(argvars); 15511 if (lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count) 15512 { 15513 curwin->w_cursor.lnum = lnum; 15514 rettv->vval.v_number = get_lisp_indent(); 15515 curwin->w_cursor = pos; 15516 } 15517 else 15518 #endif 15519 rettv->vval.v_number = -1; 15520 } 15521 15522 /* 15523 * "localtime()" function 15524 */ 15525 static void 15526 f_localtime(typval_T *argvars UNUSED, typval_T *rettv) 15527 { 15528 rettv->vval.v_number = (varnumber_T)time(NULL); 15529 } 15530 15531 static void get_maparg(typval_T *argvars, typval_T *rettv, int exact); 15532 15533 static void 15534 get_maparg(typval_T *argvars, typval_T *rettv, int exact) 15535 { 15536 char_u *keys; 15537 char_u *which; 15538 char_u buf[NUMBUFLEN]; 15539 char_u *keys_buf = NULL; 15540 char_u *rhs; 15541 int mode; 15542 int abbr = FALSE; 15543 int get_dict = FALSE; 15544 mapblock_T *mp; 15545 int buffer_local; 15546 15547 /* return empty string for failure */ 15548 rettv->v_type = VAR_STRING; 15549 rettv->vval.v_string = NULL; 15550 15551 keys = get_tv_string(&argvars[0]); 15552 if (*keys == NUL) 15553 return; 15554 15555 if (argvars[1].v_type != VAR_UNKNOWN) 15556 { 15557 which = get_tv_string_buf_chk(&argvars[1], buf); 15558 if (argvars[2].v_type != VAR_UNKNOWN) 15559 { 15560 abbr = get_tv_number(&argvars[2]); 15561 if (argvars[3].v_type != VAR_UNKNOWN) 15562 get_dict = get_tv_number(&argvars[3]); 15563 } 15564 } 15565 else 15566 which = (char_u *)""; 15567 if (which == NULL) 15568 return; 15569 15570 mode = get_map_mode(&which, 0); 15571 15572 keys = replace_termcodes(keys, &keys_buf, TRUE, TRUE, FALSE); 15573 rhs = check_map(keys, mode, exact, FALSE, abbr, &mp, &buffer_local); 15574 vim_free(keys_buf); 15575 15576 if (!get_dict) 15577 { 15578 /* Return a string. */ 15579 if (rhs != NULL) 15580 rettv->vval.v_string = str2special_save(rhs, FALSE); 15581 15582 } 15583 else if (rettv_dict_alloc(rettv) != FAIL && rhs != NULL) 15584 { 15585 /* Return a dictionary. */ 15586 char_u *lhs = str2special_save(mp->m_keys, TRUE); 15587 char_u *mapmode = map_mode_to_chars(mp->m_mode); 15588 dict_T *dict = rettv->vval.v_dict; 15589 15590 dict_add_nr_str(dict, "lhs", 0L, lhs); 15591 dict_add_nr_str(dict, "rhs", 0L, mp->m_orig_str); 15592 dict_add_nr_str(dict, "noremap", mp->m_noremap ? 1L : 0L , NULL); 15593 dict_add_nr_str(dict, "expr", mp->m_expr ? 1L : 0L, NULL); 15594 dict_add_nr_str(dict, "silent", mp->m_silent ? 1L : 0L, NULL); 15595 dict_add_nr_str(dict, "sid", (long)mp->m_script_ID, NULL); 15596 dict_add_nr_str(dict, "buffer", (long)buffer_local, NULL); 15597 dict_add_nr_str(dict, "nowait", mp->m_nowait ? 1L : 0L, NULL); 15598 dict_add_nr_str(dict, "mode", 0L, mapmode); 15599 15600 vim_free(lhs); 15601 vim_free(mapmode); 15602 } 15603 } 15604 15605 #ifdef FEAT_FLOAT 15606 /* 15607 * "log()" function 15608 */ 15609 static void 15610 f_log(typval_T *argvars, typval_T *rettv) 15611 { 15612 float_T f = 0.0; 15613 15614 rettv->v_type = VAR_FLOAT; 15615 if (get_float_arg(argvars, &f) == OK) 15616 rettv->vval.v_float = log(f); 15617 else 15618 rettv->vval.v_float = 0.0; 15619 } 15620 15621 /* 15622 * "log10()" function 15623 */ 15624 static void 15625 f_log10(typval_T *argvars, typval_T *rettv) 15626 { 15627 float_T f = 0.0; 15628 15629 rettv->v_type = VAR_FLOAT; 15630 if (get_float_arg(argvars, &f) == OK) 15631 rettv->vval.v_float = log10(f); 15632 else 15633 rettv->vval.v_float = 0.0; 15634 } 15635 #endif 15636 15637 #ifdef FEAT_LUA 15638 /* 15639 * "luaeval()" function 15640 */ 15641 static void 15642 f_luaeval(typval_T *argvars, typval_T *rettv) 15643 { 15644 char_u *str; 15645 char_u buf[NUMBUFLEN]; 15646 15647 str = get_tv_string_buf(&argvars[0], buf); 15648 do_luaeval(str, argvars + 1, rettv); 15649 } 15650 #endif 15651 15652 /* 15653 * "map()" function 15654 */ 15655 static void 15656 f_map(typval_T *argvars, typval_T *rettv) 15657 { 15658 filter_map(argvars, rettv, TRUE); 15659 } 15660 15661 /* 15662 * "maparg()" function 15663 */ 15664 static void 15665 f_maparg(typval_T *argvars, typval_T *rettv) 15666 { 15667 get_maparg(argvars, rettv, TRUE); 15668 } 15669 15670 /* 15671 * "mapcheck()" function 15672 */ 15673 static void 15674 f_mapcheck(typval_T *argvars, typval_T *rettv) 15675 { 15676 get_maparg(argvars, rettv, FALSE); 15677 } 15678 15679 static void find_some_match(typval_T *argvars, typval_T *rettv, int start); 15680 15681 static void 15682 find_some_match(typval_T *argvars, typval_T *rettv, int type) 15683 { 15684 char_u *str = NULL; 15685 long len = 0; 15686 char_u *expr = NULL; 15687 char_u *pat; 15688 regmatch_T regmatch; 15689 char_u patbuf[NUMBUFLEN]; 15690 char_u strbuf[NUMBUFLEN]; 15691 char_u *save_cpo; 15692 long start = 0; 15693 long nth = 1; 15694 colnr_T startcol = 0; 15695 int match = 0; 15696 list_T *l = NULL; 15697 listitem_T *li = NULL; 15698 long idx = 0; 15699 char_u *tofree = NULL; 15700 15701 /* Make 'cpoptions' empty, the 'l' flag should not be used here. */ 15702 save_cpo = p_cpo; 15703 p_cpo = (char_u *)""; 15704 15705 rettv->vval.v_number = -1; 15706 if (type == 3 || type == 4) 15707 { 15708 /* type 3: return empty list when there are no matches. 15709 * type 4: return ["", -1, -1, -1] */ 15710 if (rettv_list_alloc(rettv) == FAIL) 15711 goto theend; 15712 if (type == 4 15713 && (list_append_string(rettv->vval.v_list, 15714 (char_u *)"", 0) == FAIL 15715 || list_append_number(rettv->vval.v_list, 15716 (varnumber_T)-1) == FAIL 15717 || list_append_number(rettv->vval.v_list, 15718 (varnumber_T)-1) == FAIL 15719 || list_append_number(rettv->vval.v_list, 15720 (varnumber_T)-1) == FAIL)) 15721 { 15722 list_free(rettv->vval.v_list); 15723 rettv->vval.v_list = NULL; 15724 goto theend; 15725 } 15726 } 15727 else if (type == 2) 15728 { 15729 rettv->v_type = VAR_STRING; 15730 rettv->vval.v_string = NULL; 15731 } 15732 15733 if (argvars[0].v_type == VAR_LIST) 15734 { 15735 if ((l = argvars[0].vval.v_list) == NULL) 15736 goto theend; 15737 li = l->lv_first; 15738 } 15739 else 15740 { 15741 expr = str = get_tv_string(&argvars[0]); 15742 len = (long)STRLEN(str); 15743 } 15744 15745 pat = get_tv_string_buf_chk(&argvars[1], patbuf); 15746 if (pat == NULL) 15747 goto theend; 15748 15749 if (argvars[2].v_type != VAR_UNKNOWN) 15750 { 15751 int error = FALSE; 15752 15753 start = get_tv_number_chk(&argvars[2], &error); 15754 if (error) 15755 goto theend; 15756 if (l != NULL) 15757 { 15758 li = list_find(l, start); 15759 if (li == NULL) 15760 goto theend; 15761 idx = l->lv_idx; /* use the cached index */ 15762 } 15763 else 15764 { 15765 if (start < 0) 15766 start = 0; 15767 if (start > len) 15768 goto theend; 15769 /* When "count" argument is there ignore matches before "start", 15770 * otherwise skip part of the string. Differs when pattern is "^" 15771 * or "\<". */ 15772 if (argvars[3].v_type != VAR_UNKNOWN) 15773 startcol = start; 15774 else 15775 { 15776 str += start; 15777 len -= start; 15778 } 15779 } 15780 15781 if (argvars[3].v_type != VAR_UNKNOWN) 15782 nth = get_tv_number_chk(&argvars[3], &error); 15783 if (error) 15784 goto theend; 15785 } 15786 15787 regmatch.regprog = vim_regcomp(pat, RE_MAGIC + RE_STRING); 15788 if (regmatch.regprog != NULL) 15789 { 15790 regmatch.rm_ic = p_ic; 15791 15792 for (;;) 15793 { 15794 if (l != NULL) 15795 { 15796 if (li == NULL) 15797 { 15798 match = FALSE; 15799 break; 15800 } 15801 vim_free(tofree); 15802 expr = str = echo_string(&li->li_tv, &tofree, strbuf, 0); 15803 if (str == NULL) 15804 break; 15805 } 15806 15807 match = vim_regexec_nl(®match, str, (colnr_T)startcol); 15808 15809 if (match && --nth <= 0) 15810 break; 15811 if (l == NULL && !match) 15812 break; 15813 15814 /* Advance to just after the match. */ 15815 if (l != NULL) 15816 { 15817 li = li->li_next; 15818 ++idx; 15819 } 15820 else 15821 { 15822 #ifdef FEAT_MBYTE 15823 startcol = (colnr_T)(regmatch.startp[0] 15824 + (*mb_ptr2len)(regmatch.startp[0]) - str); 15825 #else 15826 startcol = (colnr_T)(regmatch.startp[0] + 1 - str); 15827 #endif 15828 if (startcol > (colnr_T)len 15829 || str + startcol <= regmatch.startp[0]) 15830 { 15831 match = FALSE; 15832 break; 15833 } 15834 } 15835 } 15836 15837 if (match) 15838 { 15839 if (type == 4) 15840 { 15841 listitem_T *li1 = rettv->vval.v_list->lv_first; 15842 listitem_T *li2 = li1->li_next; 15843 listitem_T *li3 = li2->li_next; 15844 listitem_T *li4 = li3->li_next; 15845 15846 vim_free(li1->li_tv.vval.v_string); 15847 li1->li_tv.vval.v_string = vim_strnsave(regmatch.startp[0], 15848 (int)(regmatch.endp[0] - regmatch.startp[0])); 15849 li3->li_tv.vval.v_number = 15850 (varnumber_T)(regmatch.startp[0] - expr); 15851 li4->li_tv.vval.v_number = 15852 (varnumber_T)(regmatch.endp[0] - expr); 15853 if (l != NULL) 15854 li2->li_tv.vval.v_number = (varnumber_T)idx; 15855 } 15856 else if (type == 3) 15857 { 15858 int i; 15859 15860 /* return list with matched string and submatches */ 15861 for (i = 0; i < NSUBEXP; ++i) 15862 { 15863 if (regmatch.endp[i] == NULL) 15864 { 15865 if (list_append_string(rettv->vval.v_list, 15866 (char_u *)"", 0) == FAIL) 15867 break; 15868 } 15869 else if (list_append_string(rettv->vval.v_list, 15870 regmatch.startp[i], 15871 (int)(regmatch.endp[i] - regmatch.startp[i])) 15872 == FAIL) 15873 break; 15874 } 15875 } 15876 else if (type == 2) 15877 { 15878 /* return matched string */ 15879 if (l != NULL) 15880 copy_tv(&li->li_tv, rettv); 15881 else 15882 rettv->vval.v_string = vim_strnsave(regmatch.startp[0], 15883 (int)(regmatch.endp[0] - regmatch.startp[0])); 15884 } 15885 else if (l != NULL) 15886 rettv->vval.v_number = idx; 15887 else 15888 { 15889 if (type != 0) 15890 rettv->vval.v_number = 15891 (varnumber_T)(regmatch.startp[0] - str); 15892 else 15893 rettv->vval.v_number = 15894 (varnumber_T)(regmatch.endp[0] - str); 15895 rettv->vval.v_number += (varnumber_T)(str - expr); 15896 } 15897 } 15898 vim_regfree(regmatch.regprog); 15899 } 15900 15901 if (type == 4 && l == NULL) 15902 /* matchstrpos() without a list: drop the second item. */ 15903 listitem_remove(rettv->vval.v_list, 15904 rettv->vval.v_list->lv_first->li_next); 15905 15906 theend: 15907 vim_free(tofree); 15908 p_cpo = save_cpo; 15909 } 15910 15911 /* 15912 * "match()" function 15913 */ 15914 static void 15915 f_match(typval_T *argvars, typval_T *rettv) 15916 { 15917 find_some_match(argvars, rettv, 1); 15918 } 15919 15920 /* 15921 * "matchadd()" function 15922 */ 15923 static void 15924 f_matchadd(typval_T *argvars UNUSED, typval_T *rettv UNUSED) 15925 { 15926 #ifdef FEAT_SEARCH_EXTRA 15927 char_u buf[NUMBUFLEN]; 15928 char_u *grp = get_tv_string_buf_chk(&argvars[0], buf); /* group */ 15929 char_u *pat = get_tv_string_buf_chk(&argvars[1], buf); /* pattern */ 15930 int prio = 10; /* default priority */ 15931 int id = -1; 15932 int error = FALSE; 15933 char_u *conceal_char = NULL; 15934 15935 rettv->vval.v_number = -1; 15936 15937 if (grp == NULL || pat == NULL) 15938 return; 15939 if (argvars[2].v_type != VAR_UNKNOWN) 15940 { 15941 prio = get_tv_number_chk(&argvars[2], &error); 15942 if (argvars[3].v_type != VAR_UNKNOWN) 15943 { 15944 id = get_tv_number_chk(&argvars[3], &error); 15945 if (argvars[4].v_type != VAR_UNKNOWN) 15946 { 15947 if (argvars[4].v_type != VAR_DICT) 15948 { 15949 EMSG(_(e_dictreq)); 15950 return; 15951 } 15952 if (dict_find(argvars[4].vval.v_dict, 15953 (char_u *)"conceal", -1) != NULL) 15954 conceal_char = get_dict_string(argvars[4].vval.v_dict, 15955 (char_u *)"conceal", FALSE); 15956 } 15957 } 15958 } 15959 if (error == TRUE) 15960 return; 15961 if (id >= 1 && id <= 3) 15962 { 15963 EMSGN("E798: ID is reserved for \":match\": %ld", id); 15964 return; 15965 } 15966 15967 rettv->vval.v_number = match_add(curwin, grp, pat, prio, id, NULL, 15968 conceal_char); 15969 #endif 15970 } 15971 15972 /* 15973 * "matchaddpos()" function 15974 */ 15975 static void 15976 f_matchaddpos(typval_T *argvars UNUSED, typval_T *rettv UNUSED) 15977 { 15978 #ifdef FEAT_SEARCH_EXTRA 15979 char_u buf[NUMBUFLEN]; 15980 char_u *group; 15981 int prio = 10; 15982 int id = -1; 15983 int error = FALSE; 15984 list_T *l; 15985 char_u *conceal_char = NULL; 15986 15987 rettv->vval.v_number = -1; 15988 15989 group = get_tv_string_buf_chk(&argvars[0], buf); 15990 if (group == NULL) 15991 return; 15992 15993 if (argvars[1].v_type != VAR_LIST) 15994 { 15995 EMSG2(_(e_listarg), "matchaddpos()"); 15996 return; 15997 } 15998 l = argvars[1].vval.v_list; 15999 if (l == NULL) 16000 return; 16001 16002 if (argvars[2].v_type != VAR_UNKNOWN) 16003 { 16004 prio = get_tv_number_chk(&argvars[2], &error); 16005 if (argvars[3].v_type != VAR_UNKNOWN) 16006 { 16007 id = get_tv_number_chk(&argvars[3], &error); 16008 if (argvars[4].v_type != VAR_UNKNOWN) 16009 { 16010 if (argvars[4].v_type != VAR_DICT) 16011 { 16012 EMSG(_(e_dictreq)); 16013 return; 16014 } 16015 if (dict_find(argvars[4].vval.v_dict, 16016 (char_u *)"conceal", -1) != NULL) 16017 conceal_char = get_dict_string(argvars[4].vval.v_dict, 16018 (char_u *)"conceal", FALSE); 16019 } 16020 } 16021 } 16022 if (error == TRUE) 16023 return; 16024 16025 /* id == 3 is ok because matchaddpos() is supposed to substitute :3match */ 16026 if (id == 1 || id == 2) 16027 { 16028 EMSGN("E798: ID is reserved for \":match\": %ld", id); 16029 return; 16030 } 16031 16032 rettv->vval.v_number = match_add(curwin, group, NULL, prio, id, l, 16033 conceal_char); 16034 #endif 16035 } 16036 16037 /* 16038 * "matcharg()" function 16039 */ 16040 static void 16041 f_matcharg(typval_T *argvars UNUSED, typval_T *rettv) 16042 { 16043 if (rettv_list_alloc(rettv) == OK) 16044 { 16045 #ifdef FEAT_SEARCH_EXTRA 16046 int id = get_tv_number(&argvars[0]); 16047 matchitem_T *m; 16048 16049 if (id >= 1 && id <= 3) 16050 { 16051 if ((m = (matchitem_T *)get_match(curwin, id)) != NULL) 16052 { 16053 list_append_string(rettv->vval.v_list, 16054 syn_id2name(m->hlg_id), -1); 16055 list_append_string(rettv->vval.v_list, m->pattern, -1); 16056 } 16057 else 16058 { 16059 list_append_string(rettv->vval.v_list, NULL, -1); 16060 list_append_string(rettv->vval.v_list, NULL, -1); 16061 } 16062 } 16063 #endif 16064 } 16065 } 16066 16067 /* 16068 * "matchdelete()" function 16069 */ 16070 static void 16071 f_matchdelete(typval_T *argvars UNUSED, typval_T *rettv UNUSED) 16072 { 16073 #ifdef FEAT_SEARCH_EXTRA 16074 rettv->vval.v_number = match_delete(curwin, 16075 (int)get_tv_number(&argvars[0]), TRUE); 16076 #endif 16077 } 16078 16079 /* 16080 * "matchend()" function 16081 */ 16082 static void 16083 f_matchend(typval_T *argvars, typval_T *rettv) 16084 { 16085 find_some_match(argvars, rettv, 0); 16086 } 16087 16088 /* 16089 * "matchlist()" function 16090 */ 16091 static void 16092 f_matchlist(typval_T *argvars, typval_T *rettv) 16093 { 16094 find_some_match(argvars, rettv, 3); 16095 } 16096 16097 /* 16098 * "matchstr()" function 16099 */ 16100 static void 16101 f_matchstr(typval_T *argvars, typval_T *rettv) 16102 { 16103 find_some_match(argvars, rettv, 2); 16104 } 16105 16106 /* 16107 * "matchstrpos()" function 16108 */ 16109 static void 16110 f_matchstrpos(typval_T *argvars, typval_T *rettv) 16111 { 16112 find_some_match(argvars, rettv, 4); 16113 } 16114 16115 static void max_min(typval_T *argvars, typval_T *rettv, int domax); 16116 16117 static void 16118 max_min(typval_T *argvars, typval_T *rettv, int domax) 16119 { 16120 long n = 0; 16121 long i; 16122 int error = FALSE; 16123 16124 if (argvars[0].v_type == VAR_LIST) 16125 { 16126 list_T *l; 16127 listitem_T *li; 16128 16129 l = argvars[0].vval.v_list; 16130 if (l != NULL) 16131 { 16132 li = l->lv_first; 16133 if (li != NULL) 16134 { 16135 n = get_tv_number_chk(&li->li_tv, &error); 16136 for (;;) 16137 { 16138 li = li->li_next; 16139 if (li == NULL) 16140 break; 16141 i = get_tv_number_chk(&li->li_tv, &error); 16142 if (domax ? i > n : i < n) 16143 n = i; 16144 } 16145 } 16146 } 16147 } 16148 else if (argvars[0].v_type == VAR_DICT) 16149 { 16150 dict_T *d; 16151 int first = TRUE; 16152 hashitem_T *hi; 16153 int todo; 16154 16155 d = argvars[0].vval.v_dict; 16156 if (d != NULL) 16157 { 16158 todo = (int)d->dv_hashtab.ht_used; 16159 for (hi = d->dv_hashtab.ht_array; todo > 0; ++hi) 16160 { 16161 if (!HASHITEM_EMPTY(hi)) 16162 { 16163 --todo; 16164 i = get_tv_number_chk(&HI2DI(hi)->di_tv, &error); 16165 if (first) 16166 { 16167 n = i; 16168 first = FALSE; 16169 } 16170 else if (domax ? i > n : i < n) 16171 n = i; 16172 } 16173 } 16174 } 16175 } 16176 else 16177 EMSG(_(e_listdictarg)); 16178 rettv->vval.v_number = error ? 0 : n; 16179 } 16180 16181 /* 16182 * "max()" function 16183 */ 16184 static void 16185 f_max(typval_T *argvars, typval_T *rettv) 16186 { 16187 max_min(argvars, rettv, TRUE); 16188 } 16189 16190 /* 16191 * "min()" function 16192 */ 16193 static void 16194 f_min(typval_T *argvars, typval_T *rettv) 16195 { 16196 max_min(argvars, rettv, FALSE); 16197 } 16198 16199 static int mkdir_recurse(char_u *dir, int prot); 16200 16201 /* 16202 * Create the directory in which "dir" is located, and higher levels when 16203 * needed. 16204 */ 16205 static int 16206 mkdir_recurse(char_u *dir, int prot) 16207 { 16208 char_u *p; 16209 char_u *updir; 16210 int r = FAIL; 16211 16212 /* Get end of directory name in "dir". 16213 * We're done when it's "/" or "c:/". */ 16214 p = gettail_sep(dir); 16215 if (p <= get_past_head(dir)) 16216 return OK; 16217 16218 /* If the directory exists we're done. Otherwise: create it.*/ 16219 updir = vim_strnsave(dir, (int)(p - dir)); 16220 if (updir == NULL) 16221 return FAIL; 16222 if (mch_isdir(updir)) 16223 r = OK; 16224 else if (mkdir_recurse(updir, prot) == OK) 16225 r = vim_mkdir_emsg(updir, prot); 16226 vim_free(updir); 16227 return r; 16228 } 16229 16230 #ifdef vim_mkdir 16231 /* 16232 * "mkdir()" function 16233 */ 16234 static void 16235 f_mkdir(typval_T *argvars, typval_T *rettv) 16236 { 16237 char_u *dir; 16238 char_u buf[NUMBUFLEN]; 16239 int prot = 0755; 16240 16241 rettv->vval.v_number = FAIL; 16242 if (check_restricted() || check_secure()) 16243 return; 16244 16245 dir = get_tv_string_buf(&argvars[0], buf); 16246 if (*dir == NUL) 16247 rettv->vval.v_number = FAIL; 16248 else 16249 { 16250 if (*gettail(dir) == NUL) 16251 /* remove trailing slashes */ 16252 *gettail_sep(dir) = NUL; 16253 16254 if (argvars[1].v_type != VAR_UNKNOWN) 16255 { 16256 if (argvars[2].v_type != VAR_UNKNOWN) 16257 prot = get_tv_number_chk(&argvars[2], NULL); 16258 if (prot != -1 && STRCMP(get_tv_string(&argvars[1]), "p") == 0) 16259 mkdir_recurse(dir, prot); 16260 } 16261 rettv->vval.v_number = prot == -1 ? FAIL : vim_mkdir_emsg(dir, prot); 16262 } 16263 } 16264 #endif 16265 16266 /* 16267 * "mode()" function 16268 */ 16269 static void 16270 f_mode(typval_T *argvars, typval_T *rettv) 16271 { 16272 char_u buf[3]; 16273 16274 buf[1] = NUL; 16275 buf[2] = NUL; 16276 16277 if (VIsual_active) 16278 { 16279 if (VIsual_select) 16280 buf[0] = VIsual_mode + 's' - 'v'; 16281 else 16282 buf[0] = VIsual_mode; 16283 } 16284 else if (State == HITRETURN || State == ASKMORE || State == SETWSIZE 16285 || State == CONFIRM) 16286 { 16287 buf[0] = 'r'; 16288 if (State == ASKMORE) 16289 buf[1] = 'm'; 16290 else if (State == CONFIRM) 16291 buf[1] = '?'; 16292 } 16293 else if (State == EXTERNCMD) 16294 buf[0] = '!'; 16295 else if (State & INSERT) 16296 { 16297 #ifdef FEAT_VREPLACE 16298 if (State & VREPLACE_FLAG) 16299 { 16300 buf[0] = 'R'; 16301 buf[1] = 'v'; 16302 } 16303 else 16304 #endif 16305 if (State & REPLACE_FLAG) 16306 buf[0] = 'R'; 16307 else 16308 buf[0] = 'i'; 16309 } 16310 else if (State & CMDLINE) 16311 { 16312 buf[0] = 'c'; 16313 if (exmode_active) 16314 buf[1] = 'v'; 16315 } 16316 else if (exmode_active) 16317 { 16318 buf[0] = 'c'; 16319 buf[1] = 'e'; 16320 } 16321 else 16322 { 16323 buf[0] = 'n'; 16324 if (finish_op) 16325 buf[1] = 'o'; 16326 } 16327 16328 /* Clear out the minor mode when the argument is not a non-zero number or 16329 * non-empty string. */ 16330 if (!non_zero_arg(&argvars[0])) 16331 buf[1] = NUL; 16332 16333 rettv->vval.v_string = vim_strsave(buf); 16334 rettv->v_type = VAR_STRING; 16335 } 16336 16337 #if defined(FEAT_MZSCHEME) || defined(PROTO) 16338 /* 16339 * "mzeval()" function 16340 */ 16341 static void 16342 f_mzeval(typval_T *argvars, typval_T *rettv) 16343 { 16344 char_u *str; 16345 char_u buf[NUMBUFLEN]; 16346 16347 str = get_tv_string_buf(&argvars[0], buf); 16348 do_mzeval(str, rettv); 16349 } 16350 16351 void 16352 mzscheme_call_vim(char_u *name, typval_T *args, typval_T *rettv) 16353 { 16354 typval_T argvars[3]; 16355 16356 argvars[0].v_type = VAR_STRING; 16357 argvars[0].vval.v_string = name; 16358 copy_tv(args, &argvars[1]); 16359 argvars[2].v_type = VAR_UNKNOWN; 16360 f_call(argvars, rettv); 16361 clear_tv(&argvars[1]); 16362 } 16363 #endif 16364 16365 /* 16366 * "nextnonblank()" function 16367 */ 16368 static void 16369 f_nextnonblank(typval_T *argvars, typval_T *rettv) 16370 { 16371 linenr_T lnum; 16372 16373 for (lnum = get_tv_lnum(argvars); ; ++lnum) 16374 { 16375 if (lnum < 0 || lnum > curbuf->b_ml.ml_line_count) 16376 { 16377 lnum = 0; 16378 break; 16379 } 16380 if (*skipwhite(ml_get(lnum)) != NUL) 16381 break; 16382 } 16383 rettv->vval.v_number = lnum; 16384 } 16385 16386 /* 16387 * "nr2char()" function 16388 */ 16389 static void 16390 f_nr2char(typval_T *argvars, typval_T *rettv) 16391 { 16392 char_u buf[NUMBUFLEN]; 16393 16394 #ifdef FEAT_MBYTE 16395 if (has_mbyte) 16396 { 16397 int utf8 = 0; 16398 16399 if (argvars[1].v_type != VAR_UNKNOWN) 16400 utf8 = get_tv_number_chk(&argvars[1], NULL); 16401 if (utf8) 16402 buf[(*utf_char2bytes)((int)get_tv_number(&argvars[0]), buf)] = NUL; 16403 else 16404 buf[(*mb_char2bytes)((int)get_tv_number(&argvars[0]), buf)] = NUL; 16405 } 16406 else 16407 #endif 16408 { 16409 buf[0] = (char_u)get_tv_number(&argvars[0]); 16410 buf[1] = NUL; 16411 } 16412 rettv->v_type = VAR_STRING; 16413 rettv->vval.v_string = vim_strsave(buf); 16414 } 16415 16416 /* 16417 * "or(expr, expr)" function 16418 */ 16419 static void 16420 f_or(typval_T *argvars, typval_T *rettv) 16421 { 16422 rettv->vval.v_number = get_tv_number_chk(&argvars[0], NULL) 16423 | get_tv_number_chk(&argvars[1], NULL); 16424 } 16425 16426 /* 16427 * "pathshorten()" function 16428 */ 16429 static void 16430 f_pathshorten(typval_T *argvars, typval_T *rettv) 16431 { 16432 char_u *p; 16433 16434 rettv->v_type = VAR_STRING; 16435 p = get_tv_string_chk(&argvars[0]); 16436 if (p == NULL) 16437 rettv->vval.v_string = NULL; 16438 else 16439 { 16440 p = vim_strsave(p); 16441 rettv->vval.v_string = p; 16442 if (p != NULL) 16443 shorten_dir(p); 16444 } 16445 } 16446 16447 #ifdef FEAT_PERL 16448 /* 16449 * "perleval()" function 16450 */ 16451 static void 16452 f_perleval(typval_T *argvars, typval_T *rettv) 16453 { 16454 char_u *str; 16455 char_u buf[NUMBUFLEN]; 16456 16457 str = get_tv_string_buf(&argvars[0], buf); 16458 do_perleval(str, rettv); 16459 } 16460 #endif 16461 16462 #ifdef FEAT_FLOAT 16463 /* 16464 * "pow()" function 16465 */ 16466 static void 16467 f_pow(typval_T *argvars, typval_T *rettv) 16468 { 16469 float_T fx = 0.0, fy = 0.0; 16470 16471 rettv->v_type = VAR_FLOAT; 16472 if (get_float_arg(argvars, &fx) == OK 16473 && get_float_arg(&argvars[1], &fy) == OK) 16474 rettv->vval.v_float = pow(fx, fy); 16475 else 16476 rettv->vval.v_float = 0.0; 16477 } 16478 #endif 16479 16480 /* 16481 * "prevnonblank()" function 16482 */ 16483 static void 16484 f_prevnonblank(typval_T *argvars, typval_T *rettv) 16485 { 16486 linenr_T lnum; 16487 16488 lnum = get_tv_lnum(argvars); 16489 if (lnum < 1 || lnum > curbuf->b_ml.ml_line_count) 16490 lnum = 0; 16491 else 16492 while (lnum >= 1 && *skipwhite(ml_get(lnum)) == NUL) 16493 --lnum; 16494 rettv->vval.v_number = lnum; 16495 } 16496 16497 /* This dummy va_list is here because: 16498 * - passing a NULL pointer doesn't work when va_list isn't a pointer 16499 * - locally in the function results in a "used before set" warning 16500 * - using va_start() to initialize it gives "function with fixed args" error */ 16501 static va_list ap; 16502 16503 /* 16504 * "printf()" function 16505 */ 16506 static void 16507 f_printf(typval_T *argvars, typval_T *rettv) 16508 { 16509 char_u buf[NUMBUFLEN]; 16510 int len; 16511 char_u *s; 16512 int saved_did_emsg = did_emsg; 16513 char *fmt; 16514 16515 rettv->v_type = VAR_STRING; 16516 rettv->vval.v_string = NULL; 16517 16518 /* Get the required length, allocate the buffer and do it for real. */ 16519 did_emsg = FALSE; 16520 fmt = (char *)get_tv_string_buf(&argvars[0], buf); 16521 len = vim_vsnprintf(NULL, 0, fmt, ap, argvars + 1); 16522 if (!did_emsg) 16523 { 16524 s = alloc(len + 1); 16525 if (s != NULL) 16526 { 16527 rettv->vval.v_string = s; 16528 (void)vim_vsnprintf((char *)s, len + 1, fmt, ap, argvars + 1); 16529 } 16530 } 16531 did_emsg |= saved_did_emsg; 16532 } 16533 16534 /* 16535 * "pumvisible()" function 16536 */ 16537 static void 16538 f_pumvisible(typval_T *argvars UNUSED, typval_T *rettv UNUSED) 16539 { 16540 #ifdef FEAT_INS_EXPAND 16541 if (pum_visible()) 16542 rettv->vval.v_number = 1; 16543 #endif 16544 } 16545 16546 #ifdef FEAT_PYTHON3 16547 /* 16548 * "py3eval()" function 16549 */ 16550 static void 16551 f_py3eval(typval_T *argvars, typval_T *rettv) 16552 { 16553 char_u *str; 16554 char_u buf[NUMBUFLEN]; 16555 16556 str = get_tv_string_buf(&argvars[0], buf); 16557 do_py3eval(str, rettv); 16558 } 16559 #endif 16560 16561 #ifdef FEAT_PYTHON 16562 /* 16563 * "pyeval()" function 16564 */ 16565 static void 16566 f_pyeval(typval_T *argvars, typval_T *rettv) 16567 { 16568 char_u *str; 16569 char_u buf[NUMBUFLEN]; 16570 16571 str = get_tv_string_buf(&argvars[0], buf); 16572 do_pyeval(str, rettv); 16573 } 16574 #endif 16575 16576 /* 16577 * "range()" function 16578 */ 16579 static void 16580 f_range(typval_T *argvars, typval_T *rettv) 16581 { 16582 long start; 16583 long end; 16584 long stride = 1; 16585 long i; 16586 int error = FALSE; 16587 16588 start = get_tv_number_chk(&argvars[0], &error); 16589 if (argvars[1].v_type == VAR_UNKNOWN) 16590 { 16591 end = start - 1; 16592 start = 0; 16593 } 16594 else 16595 { 16596 end = get_tv_number_chk(&argvars[1], &error); 16597 if (argvars[2].v_type != VAR_UNKNOWN) 16598 stride = get_tv_number_chk(&argvars[2], &error); 16599 } 16600 16601 if (error) 16602 return; /* type error; errmsg already given */ 16603 if (stride == 0) 16604 EMSG(_("E726: Stride is zero")); 16605 else if (stride > 0 ? end + 1 < start : end - 1 > start) 16606 EMSG(_("E727: Start past end")); 16607 else 16608 { 16609 if (rettv_list_alloc(rettv) == OK) 16610 for (i = start; stride > 0 ? i <= end : i >= end; i += stride) 16611 if (list_append_number(rettv->vval.v_list, 16612 (varnumber_T)i) == FAIL) 16613 break; 16614 } 16615 } 16616 16617 /* 16618 * "readfile()" function 16619 */ 16620 static void 16621 f_readfile(typval_T *argvars, typval_T *rettv) 16622 { 16623 int binary = FALSE; 16624 int failed = FALSE; 16625 char_u *fname; 16626 FILE *fd; 16627 char_u buf[(IOSIZE/256)*256]; /* rounded to avoid odd + 1 */ 16628 int io_size = sizeof(buf); 16629 int readlen; /* size of last fread() */ 16630 char_u *prev = NULL; /* previously read bytes, if any */ 16631 long prevlen = 0; /* length of data in prev */ 16632 long prevsize = 0; /* size of prev buffer */ 16633 long maxline = MAXLNUM; 16634 long cnt = 0; 16635 char_u *p; /* position in buf */ 16636 char_u *start; /* start of current line */ 16637 16638 if (argvars[1].v_type != VAR_UNKNOWN) 16639 { 16640 if (STRCMP(get_tv_string(&argvars[1]), "b") == 0) 16641 binary = TRUE; 16642 if (argvars[2].v_type != VAR_UNKNOWN) 16643 maxline = get_tv_number(&argvars[2]); 16644 } 16645 16646 if (rettv_list_alloc(rettv) == FAIL) 16647 return; 16648 16649 /* Always open the file in binary mode, library functions have a mind of 16650 * their own about CR-LF conversion. */ 16651 fname = get_tv_string(&argvars[0]); 16652 if (*fname == NUL || (fd = mch_fopen((char *)fname, READBIN)) == NULL) 16653 { 16654 EMSG2(_(e_notopen), *fname == NUL ? (char_u *)_("<empty>") : fname); 16655 return; 16656 } 16657 16658 while (cnt < maxline || maxline < 0) 16659 { 16660 readlen = (int)fread(buf, 1, io_size, fd); 16661 16662 /* This for loop processes what was read, but is also entered at end 16663 * of file so that either: 16664 * - an incomplete line gets written 16665 * - a "binary" file gets an empty line at the end if it ends in a 16666 * newline. */ 16667 for (p = buf, start = buf; 16668 p < buf + readlen || (readlen <= 0 && (prevlen > 0 || binary)); 16669 ++p) 16670 { 16671 if (*p == '\n' || readlen <= 0) 16672 { 16673 listitem_T *li; 16674 char_u *s = NULL; 16675 long_u len = p - start; 16676 16677 /* Finished a line. Remove CRs before NL. */ 16678 if (readlen > 0 && !binary) 16679 { 16680 while (len > 0 && start[len - 1] == '\r') 16681 --len; 16682 /* removal may cross back to the "prev" string */ 16683 if (len == 0) 16684 while (prevlen > 0 && prev[prevlen - 1] == '\r') 16685 --prevlen; 16686 } 16687 if (prevlen == 0) 16688 s = vim_strnsave(start, (int)len); 16689 else 16690 { 16691 /* Change "prev" buffer to be the right size. This way 16692 * the bytes are only copied once, and very long lines are 16693 * allocated only once. */ 16694 if ((s = vim_realloc(prev, prevlen + len + 1)) != NULL) 16695 { 16696 mch_memmove(s + prevlen, start, len); 16697 s[prevlen + len] = NUL; 16698 prev = NULL; /* the list will own the string */ 16699 prevlen = prevsize = 0; 16700 } 16701 } 16702 if (s == NULL) 16703 { 16704 do_outofmem_msg((long_u) prevlen + len + 1); 16705 failed = TRUE; 16706 break; 16707 } 16708 16709 if ((li = listitem_alloc()) == NULL) 16710 { 16711 vim_free(s); 16712 failed = TRUE; 16713 break; 16714 } 16715 li->li_tv.v_type = VAR_STRING; 16716 li->li_tv.v_lock = 0; 16717 li->li_tv.vval.v_string = s; 16718 list_append(rettv->vval.v_list, li); 16719 16720 start = p + 1; /* step over newline */ 16721 if ((++cnt >= maxline && maxline >= 0) || readlen <= 0) 16722 break; 16723 } 16724 else if (*p == NUL) 16725 *p = '\n'; 16726 #ifdef FEAT_MBYTE 16727 /* Check for utf8 "bom"; U+FEFF is encoded as EF BB BF. Do this 16728 * when finding the BF and check the previous two bytes. */ 16729 else if (*p == 0xbf && enc_utf8 && !binary) 16730 { 16731 /* Find the two bytes before the 0xbf. If p is at buf, or buf 16732 * + 1, these may be in the "prev" string. */ 16733 char_u back1 = p >= buf + 1 ? p[-1] 16734 : prevlen >= 1 ? prev[prevlen - 1] : NUL; 16735 char_u back2 = p >= buf + 2 ? p[-2] 16736 : p == buf + 1 && prevlen >= 1 ? prev[prevlen - 1] 16737 : prevlen >= 2 ? prev[prevlen - 2] : NUL; 16738 16739 if (back2 == 0xef && back1 == 0xbb) 16740 { 16741 char_u *dest = p - 2; 16742 16743 /* Usually a BOM is at the beginning of a file, and so at 16744 * the beginning of a line; then we can just step over it. 16745 */ 16746 if (start == dest) 16747 start = p + 1; 16748 else 16749 { 16750 /* have to shuffle buf to close gap */ 16751 int adjust_prevlen = 0; 16752 16753 if (dest < buf) 16754 { 16755 adjust_prevlen = (int)(buf - dest); /* must be 1 or 2 */ 16756 dest = buf; 16757 } 16758 if (readlen > p - buf + 1) 16759 mch_memmove(dest, p + 1, readlen - (p - buf) - 1); 16760 readlen -= 3 - adjust_prevlen; 16761 prevlen -= adjust_prevlen; 16762 p = dest - 1; 16763 } 16764 } 16765 } 16766 #endif 16767 } /* for */ 16768 16769 if (failed || (cnt >= maxline && maxline >= 0) || readlen <= 0) 16770 break; 16771 if (start < p) 16772 { 16773 /* There's part of a line in buf, store it in "prev". */ 16774 if (p - start + prevlen >= prevsize) 16775 { 16776 /* need bigger "prev" buffer */ 16777 char_u *newprev; 16778 16779 /* A common use case is ordinary text files and "prev" gets a 16780 * fragment of a line, so the first allocation is made 16781 * small, to avoid repeatedly 'allocing' large and 16782 * 'reallocing' small. */ 16783 if (prevsize == 0) 16784 prevsize = (long)(p - start); 16785 else 16786 { 16787 long grow50pc = (prevsize * 3) / 2; 16788 long growmin = (long)((p - start) * 2 + prevlen); 16789 prevsize = grow50pc > growmin ? grow50pc : growmin; 16790 } 16791 newprev = prev == NULL ? alloc(prevsize) 16792 : vim_realloc(prev, prevsize); 16793 if (newprev == NULL) 16794 { 16795 do_outofmem_msg((long_u)prevsize); 16796 failed = TRUE; 16797 break; 16798 } 16799 prev = newprev; 16800 } 16801 /* Add the line part to end of "prev". */ 16802 mch_memmove(prev + prevlen, start, p - start); 16803 prevlen += (long)(p - start); 16804 } 16805 } /* while */ 16806 16807 /* 16808 * For a negative line count use only the lines at the end of the file, 16809 * free the rest. 16810 */ 16811 if (!failed && maxline < 0) 16812 while (cnt > -maxline) 16813 { 16814 listitem_remove(rettv->vval.v_list, rettv->vval.v_list->lv_first); 16815 --cnt; 16816 } 16817 16818 if (failed) 16819 { 16820 list_free(rettv->vval.v_list); 16821 /* readfile doc says an empty list is returned on error */ 16822 rettv->vval.v_list = list_alloc(); 16823 } 16824 16825 vim_free(prev); 16826 fclose(fd); 16827 } 16828 16829 #if defined(FEAT_RELTIME) 16830 static int list2proftime(typval_T *arg, proftime_T *tm); 16831 16832 /* 16833 * Convert a List to proftime_T. 16834 * Return FAIL when there is something wrong. 16835 */ 16836 static int 16837 list2proftime(typval_T *arg, proftime_T *tm) 16838 { 16839 long n1, n2; 16840 int error = FALSE; 16841 16842 if (arg->v_type != VAR_LIST || arg->vval.v_list == NULL 16843 || arg->vval.v_list->lv_len != 2) 16844 return FAIL; 16845 n1 = list_find_nr(arg->vval.v_list, 0L, &error); 16846 n2 = list_find_nr(arg->vval.v_list, 1L, &error); 16847 # ifdef WIN3264 16848 tm->HighPart = n1; 16849 tm->LowPart = n2; 16850 # else 16851 tm->tv_sec = n1; 16852 tm->tv_usec = n2; 16853 # endif 16854 return error ? FAIL : OK; 16855 } 16856 #endif /* FEAT_RELTIME */ 16857 16858 /* 16859 * "reltime()" function 16860 */ 16861 static void 16862 f_reltime(typval_T *argvars UNUSED, typval_T *rettv UNUSED) 16863 { 16864 #ifdef FEAT_RELTIME 16865 proftime_T res; 16866 proftime_T start; 16867 16868 if (argvars[0].v_type == VAR_UNKNOWN) 16869 { 16870 /* No arguments: get current time. */ 16871 profile_start(&res); 16872 } 16873 else if (argvars[1].v_type == VAR_UNKNOWN) 16874 { 16875 if (list2proftime(&argvars[0], &res) == FAIL) 16876 return; 16877 profile_end(&res); 16878 } 16879 else 16880 { 16881 /* Two arguments: compute the difference. */ 16882 if (list2proftime(&argvars[0], &start) == FAIL 16883 || list2proftime(&argvars[1], &res) == FAIL) 16884 return; 16885 profile_sub(&res, &start); 16886 } 16887 16888 if (rettv_list_alloc(rettv) == OK) 16889 { 16890 long n1, n2; 16891 16892 # ifdef WIN3264 16893 n1 = res.HighPart; 16894 n2 = res.LowPart; 16895 # else 16896 n1 = res.tv_sec; 16897 n2 = res.tv_usec; 16898 # endif 16899 list_append_number(rettv->vval.v_list, (varnumber_T)n1); 16900 list_append_number(rettv->vval.v_list, (varnumber_T)n2); 16901 } 16902 #endif 16903 } 16904 16905 #ifdef FEAT_FLOAT 16906 /* 16907 * "reltimefloat()" function 16908 */ 16909 static void 16910 f_reltimefloat(typval_T *argvars UNUSED, typval_T *rettv) 16911 { 16912 # ifdef FEAT_RELTIME 16913 proftime_T tm; 16914 # endif 16915 16916 rettv->v_type = VAR_FLOAT; 16917 rettv->vval.v_float = 0; 16918 # ifdef FEAT_RELTIME 16919 if (list2proftime(&argvars[0], &tm) == OK) 16920 rettv->vval.v_float = profile_float(&tm); 16921 # endif 16922 } 16923 #endif 16924 16925 /* 16926 * "reltimestr()" function 16927 */ 16928 static void 16929 f_reltimestr(typval_T *argvars UNUSED, typval_T *rettv) 16930 { 16931 #ifdef FEAT_RELTIME 16932 proftime_T tm; 16933 #endif 16934 16935 rettv->v_type = VAR_STRING; 16936 rettv->vval.v_string = NULL; 16937 #ifdef FEAT_RELTIME 16938 if (list2proftime(&argvars[0], &tm) == OK) 16939 rettv->vval.v_string = vim_strsave((char_u *)profile_msg(&tm)); 16940 #endif 16941 } 16942 16943 #if defined(FEAT_CLIENTSERVER) && defined(FEAT_X11) 16944 static void make_connection(void); 16945 static int check_connection(void); 16946 16947 static void 16948 make_connection(void) 16949 { 16950 if (X_DISPLAY == NULL 16951 # ifdef FEAT_GUI 16952 && !gui.in_use 16953 # endif 16954 ) 16955 { 16956 x_force_connect = TRUE; 16957 setup_term_clip(); 16958 x_force_connect = FALSE; 16959 } 16960 } 16961 16962 static int 16963 check_connection(void) 16964 { 16965 make_connection(); 16966 if (X_DISPLAY == NULL) 16967 { 16968 EMSG(_("E240: No connection to Vim server")); 16969 return FAIL; 16970 } 16971 return OK; 16972 } 16973 #endif 16974 16975 #ifdef FEAT_CLIENTSERVER 16976 static void 16977 remote_common(typval_T *argvars, typval_T *rettv, int expr) 16978 { 16979 char_u *server_name; 16980 char_u *keys; 16981 char_u *r = NULL; 16982 char_u buf[NUMBUFLEN]; 16983 # ifdef WIN32 16984 HWND w; 16985 # else 16986 Window w; 16987 # endif 16988 16989 if (check_restricted() || check_secure()) 16990 return; 16991 16992 # ifdef FEAT_X11 16993 if (check_connection() == FAIL) 16994 return; 16995 # endif 16996 16997 server_name = get_tv_string_chk(&argvars[0]); 16998 if (server_name == NULL) 16999 return; /* type error; errmsg already given */ 17000 keys = get_tv_string_buf(&argvars[1], buf); 17001 # ifdef WIN32 17002 if (serverSendToVim(server_name, keys, &r, &w, expr, TRUE) < 0) 17003 # else 17004 if (serverSendToVim(X_DISPLAY, server_name, keys, &r, &w, expr, 0, TRUE) 17005 < 0) 17006 # endif 17007 { 17008 if (r != NULL) 17009 EMSG(r); /* sending worked but evaluation failed */ 17010 else 17011 EMSG2(_("E241: Unable to send to %s"), server_name); 17012 return; 17013 } 17014 17015 rettv->vval.v_string = r; 17016 17017 if (argvars[2].v_type != VAR_UNKNOWN) 17018 { 17019 dictitem_T v; 17020 char_u str[30]; 17021 char_u *idvar; 17022 17023 sprintf((char *)str, PRINTF_HEX_LONG_U, (long_u)w); 17024 v.di_tv.v_type = VAR_STRING; 17025 v.di_tv.vval.v_string = vim_strsave(str); 17026 idvar = get_tv_string_chk(&argvars[2]); 17027 if (idvar != NULL) 17028 set_var(idvar, &v.di_tv, FALSE); 17029 vim_free(v.di_tv.vval.v_string); 17030 } 17031 } 17032 #endif 17033 17034 /* 17035 * "remote_expr()" function 17036 */ 17037 static void 17038 f_remote_expr(typval_T *argvars UNUSED, typval_T *rettv) 17039 { 17040 rettv->v_type = VAR_STRING; 17041 rettv->vval.v_string = NULL; 17042 #ifdef FEAT_CLIENTSERVER 17043 remote_common(argvars, rettv, TRUE); 17044 #endif 17045 } 17046 17047 /* 17048 * "remote_foreground()" function 17049 */ 17050 static void 17051 f_remote_foreground(typval_T *argvars UNUSED, typval_T *rettv UNUSED) 17052 { 17053 #ifdef FEAT_CLIENTSERVER 17054 # ifdef WIN32 17055 /* On Win32 it's done in this application. */ 17056 { 17057 char_u *server_name = get_tv_string_chk(&argvars[0]); 17058 17059 if (server_name != NULL) 17060 serverForeground(server_name); 17061 } 17062 # else 17063 /* Send a foreground() expression to the server. */ 17064 argvars[1].v_type = VAR_STRING; 17065 argvars[1].vval.v_string = vim_strsave((char_u *)"foreground()"); 17066 argvars[2].v_type = VAR_UNKNOWN; 17067 remote_common(argvars, rettv, TRUE); 17068 vim_free(argvars[1].vval.v_string); 17069 # endif 17070 #endif 17071 } 17072 17073 static void 17074 f_remote_peek(typval_T *argvars UNUSED, typval_T *rettv) 17075 { 17076 #ifdef FEAT_CLIENTSERVER 17077 dictitem_T v; 17078 char_u *s = NULL; 17079 # ifdef WIN32 17080 long_u n = 0; 17081 # endif 17082 char_u *serverid; 17083 17084 if (check_restricted() || check_secure()) 17085 { 17086 rettv->vval.v_number = -1; 17087 return; 17088 } 17089 serverid = get_tv_string_chk(&argvars[0]); 17090 if (serverid == NULL) 17091 { 17092 rettv->vval.v_number = -1; 17093 return; /* type error; errmsg already given */ 17094 } 17095 # ifdef WIN32 17096 sscanf((const char *)serverid, SCANF_HEX_LONG_U, &n); 17097 if (n == 0) 17098 rettv->vval.v_number = -1; 17099 else 17100 { 17101 s = serverGetReply((HWND)n, FALSE, FALSE, FALSE); 17102 rettv->vval.v_number = (s != NULL); 17103 } 17104 # else 17105 if (check_connection() == FAIL) 17106 return; 17107 17108 rettv->vval.v_number = serverPeekReply(X_DISPLAY, 17109 serverStrToWin(serverid), &s); 17110 # endif 17111 17112 if (argvars[1].v_type != VAR_UNKNOWN && rettv->vval.v_number > 0) 17113 { 17114 char_u *retvar; 17115 17116 v.di_tv.v_type = VAR_STRING; 17117 v.di_tv.vval.v_string = vim_strsave(s); 17118 retvar = get_tv_string_chk(&argvars[1]); 17119 if (retvar != NULL) 17120 set_var(retvar, &v.di_tv, FALSE); 17121 vim_free(v.di_tv.vval.v_string); 17122 } 17123 #else 17124 rettv->vval.v_number = -1; 17125 #endif 17126 } 17127 17128 static void 17129 f_remote_read(typval_T *argvars UNUSED, typval_T *rettv) 17130 { 17131 char_u *r = NULL; 17132 17133 #ifdef FEAT_CLIENTSERVER 17134 char_u *serverid = get_tv_string_chk(&argvars[0]); 17135 17136 if (serverid != NULL && !check_restricted() && !check_secure()) 17137 { 17138 # ifdef WIN32 17139 /* The server's HWND is encoded in the 'id' parameter */ 17140 long_u n = 0; 17141 17142 sscanf((char *)serverid, SCANF_HEX_LONG_U, &n); 17143 if (n != 0) 17144 r = serverGetReply((HWND)n, FALSE, TRUE, TRUE); 17145 if (r == NULL) 17146 # else 17147 if (check_connection() == FAIL || serverReadReply(X_DISPLAY, 17148 serverStrToWin(serverid), &r, FALSE) < 0) 17149 # endif 17150 EMSG(_("E277: Unable to read a server reply")); 17151 } 17152 #endif 17153 rettv->v_type = VAR_STRING; 17154 rettv->vval.v_string = r; 17155 } 17156 17157 /* 17158 * "remote_send()" function 17159 */ 17160 static void 17161 f_remote_send(typval_T *argvars UNUSED, typval_T *rettv) 17162 { 17163 rettv->v_type = VAR_STRING; 17164 rettv->vval.v_string = NULL; 17165 #ifdef FEAT_CLIENTSERVER 17166 remote_common(argvars, rettv, FALSE); 17167 #endif 17168 } 17169 17170 /* 17171 * "remove()" function 17172 */ 17173 static void 17174 f_remove(typval_T *argvars, typval_T *rettv) 17175 { 17176 list_T *l; 17177 listitem_T *item, *item2; 17178 listitem_T *li; 17179 long idx; 17180 long end; 17181 char_u *key; 17182 dict_T *d; 17183 dictitem_T *di; 17184 char_u *arg_errmsg = (char_u *)N_("remove() argument"); 17185 17186 if (argvars[0].v_type == VAR_DICT) 17187 { 17188 if (argvars[2].v_type != VAR_UNKNOWN) 17189 EMSG2(_(e_toomanyarg), "remove()"); 17190 else if ((d = argvars[0].vval.v_dict) != NULL 17191 && !tv_check_lock(d->dv_lock, arg_errmsg, TRUE)) 17192 { 17193 key = get_tv_string_chk(&argvars[1]); 17194 if (key != NULL) 17195 { 17196 di = dict_find(d, key, -1); 17197 if (di == NULL) 17198 EMSG2(_(e_dictkey), key); 17199 else if (!var_check_fixed(di->di_flags, arg_errmsg, TRUE) 17200 && !var_check_ro(di->di_flags, arg_errmsg, TRUE)) 17201 { 17202 *rettv = di->di_tv; 17203 init_tv(&di->di_tv); 17204 dictitem_remove(d, di); 17205 } 17206 } 17207 } 17208 } 17209 else if (argvars[0].v_type != VAR_LIST) 17210 EMSG2(_(e_listdictarg), "remove()"); 17211 else if ((l = argvars[0].vval.v_list) != NULL 17212 && !tv_check_lock(l->lv_lock, arg_errmsg, TRUE)) 17213 { 17214 int error = FALSE; 17215 17216 idx = get_tv_number_chk(&argvars[1], &error); 17217 if (error) 17218 ; /* type error: do nothing, errmsg already given */ 17219 else if ((item = list_find(l, idx)) == NULL) 17220 EMSGN(_(e_listidx), idx); 17221 else 17222 { 17223 if (argvars[2].v_type == VAR_UNKNOWN) 17224 { 17225 /* Remove one item, return its value. */ 17226 vimlist_remove(l, item, item); 17227 *rettv = item->li_tv; 17228 vim_free(item); 17229 } 17230 else 17231 { 17232 /* Remove range of items, return list with values. */ 17233 end = get_tv_number_chk(&argvars[2], &error); 17234 if (error) 17235 ; /* type error: do nothing */ 17236 else if ((item2 = list_find(l, end)) == NULL) 17237 EMSGN(_(e_listidx), end); 17238 else 17239 { 17240 int cnt = 0; 17241 17242 for (li = item; li != NULL; li = li->li_next) 17243 { 17244 ++cnt; 17245 if (li == item2) 17246 break; 17247 } 17248 if (li == NULL) /* didn't find "item2" after "item" */ 17249 EMSG(_(e_invrange)); 17250 else 17251 { 17252 vimlist_remove(l, item, item2); 17253 if (rettv_list_alloc(rettv) == OK) 17254 { 17255 l = rettv->vval.v_list; 17256 l->lv_first = item; 17257 l->lv_last = item2; 17258 item->li_prev = NULL; 17259 item2->li_next = NULL; 17260 l->lv_len = cnt; 17261 } 17262 } 17263 } 17264 } 17265 } 17266 } 17267 } 17268 17269 /* 17270 * "rename({from}, {to})" function 17271 */ 17272 static void 17273 f_rename(typval_T *argvars, typval_T *rettv) 17274 { 17275 char_u buf[NUMBUFLEN]; 17276 17277 if (check_restricted() || check_secure()) 17278 rettv->vval.v_number = -1; 17279 else 17280 rettv->vval.v_number = vim_rename(get_tv_string(&argvars[0]), 17281 get_tv_string_buf(&argvars[1], buf)); 17282 } 17283 17284 /* 17285 * "repeat()" function 17286 */ 17287 static void 17288 f_repeat(typval_T *argvars, typval_T *rettv) 17289 { 17290 char_u *p; 17291 int n; 17292 int slen; 17293 int len; 17294 char_u *r; 17295 int i; 17296 17297 n = get_tv_number(&argvars[1]); 17298 if (argvars[0].v_type == VAR_LIST) 17299 { 17300 if (rettv_list_alloc(rettv) == OK && argvars[0].vval.v_list != NULL) 17301 while (n-- > 0) 17302 if (list_extend(rettv->vval.v_list, 17303 argvars[0].vval.v_list, NULL) == FAIL) 17304 break; 17305 } 17306 else 17307 { 17308 p = get_tv_string(&argvars[0]); 17309 rettv->v_type = VAR_STRING; 17310 rettv->vval.v_string = NULL; 17311 17312 slen = (int)STRLEN(p); 17313 len = slen * n; 17314 if (len <= 0) 17315 return; 17316 17317 r = alloc(len + 1); 17318 if (r != NULL) 17319 { 17320 for (i = 0; i < n; i++) 17321 mch_memmove(r + i * slen, p, (size_t)slen); 17322 r[len] = NUL; 17323 } 17324 17325 rettv->vval.v_string = r; 17326 } 17327 } 17328 17329 /* 17330 * "resolve()" function 17331 */ 17332 static void 17333 f_resolve(typval_T *argvars, typval_T *rettv) 17334 { 17335 char_u *p; 17336 #ifdef HAVE_READLINK 17337 char_u *buf = NULL; 17338 #endif 17339 17340 p = get_tv_string(&argvars[0]); 17341 #ifdef FEAT_SHORTCUT 17342 { 17343 char_u *v = NULL; 17344 17345 v = mch_resolve_shortcut(p); 17346 if (v != NULL) 17347 rettv->vval.v_string = v; 17348 else 17349 rettv->vval.v_string = vim_strsave(p); 17350 } 17351 #else 17352 # ifdef HAVE_READLINK 17353 { 17354 char_u *cpy; 17355 int len; 17356 char_u *remain = NULL; 17357 char_u *q; 17358 int is_relative_to_current = FALSE; 17359 int has_trailing_pathsep = FALSE; 17360 int limit = 100; 17361 17362 p = vim_strsave(p); 17363 17364 if (p[0] == '.' && (vim_ispathsep(p[1]) 17365 || (p[1] == '.' && (vim_ispathsep(p[2]))))) 17366 is_relative_to_current = TRUE; 17367 17368 len = STRLEN(p); 17369 if (len > 0 && after_pathsep(p, p + len)) 17370 { 17371 has_trailing_pathsep = TRUE; 17372 p[len - 1] = NUL; /* the trailing slash breaks readlink() */ 17373 } 17374 17375 q = getnextcomp(p); 17376 if (*q != NUL) 17377 { 17378 /* Separate the first path component in "p", and keep the 17379 * remainder (beginning with the path separator). */ 17380 remain = vim_strsave(q - 1); 17381 q[-1] = NUL; 17382 } 17383 17384 buf = alloc(MAXPATHL + 1); 17385 if (buf == NULL) 17386 goto fail; 17387 17388 for (;;) 17389 { 17390 for (;;) 17391 { 17392 len = readlink((char *)p, (char *)buf, MAXPATHL); 17393 if (len <= 0) 17394 break; 17395 buf[len] = NUL; 17396 17397 if (limit-- == 0) 17398 { 17399 vim_free(p); 17400 vim_free(remain); 17401 EMSG(_("E655: Too many symbolic links (cycle?)")); 17402 rettv->vval.v_string = NULL; 17403 goto fail; 17404 } 17405 17406 /* Ensure that the result will have a trailing path separator 17407 * if the argument has one. */ 17408 if (remain == NULL && has_trailing_pathsep) 17409 add_pathsep(buf); 17410 17411 /* Separate the first path component in the link value and 17412 * concatenate the remainders. */ 17413 q = getnextcomp(vim_ispathsep(*buf) ? buf + 1 : buf); 17414 if (*q != NUL) 17415 { 17416 if (remain == NULL) 17417 remain = vim_strsave(q - 1); 17418 else 17419 { 17420 cpy = concat_str(q - 1, remain); 17421 if (cpy != NULL) 17422 { 17423 vim_free(remain); 17424 remain = cpy; 17425 } 17426 } 17427 q[-1] = NUL; 17428 } 17429 17430 q = gettail(p); 17431 if (q > p && *q == NUL) 17432 { 17433 /* Ignore trailing path separator. */ 17434 q[-1] = NUL; 17435 q = gettail(p); 17436 } 17437 if (q > p && !mch_isFullName(buf)) 17438 { 17439 /* symlink is relative to directory of argument */ 17440 cpy = alloc((unsigned)(STRLEN(p) + STRLEN(buf) + 1)); 17441 if (cpy != NULL) 17442 { 17443 STRCPY(cpy, p); 17444 STRCPY(gettail(cpy), buf); 17445 vim_free(p); 17446 p = cpy; 17447 } 17448 } 17449 else 17450 { 17451 vim_free(p); 17452 p = vim_strsave(buf); 17453 } 17454 } 17455 17456 if (remain == NULL) 17457 break; 17458 17459 /* Append the first path component of "remain" to "p". */ 17460 q = getnextcomp(remain + 1); 17461 len = q - remain - (*q != NUL); 17462 cpy = vim_strnsave(p, STRLEN(p) + len); 17463 if (cpy != NULL) 17464 { 17465 STRNCAT(cpy, remain, len); 17466 vim_free(p); 17467 p = cpy; 17468 } 17469 /* Shorten "remain". */ 17470 if (*q != NUL) 17471 STRMOVE(remain, q - 1); 17472 else 17473 { 17474 vim_free(remain); 17475 remain = NULL; 17476 } 17477 } 17478 17479 /* If the result is a relative path name, make it explicitly relative to 17480 * the current directory if and only if the argument had this form. */ 17481 if (!vim_ispathsep(*p)) 17482 { 17483 if (is_relative_to_current 17484 && *p != NUL 17485 && !(p[0] == '.' 17486 && (p[1] == NUL 17487 || vim_ispathsep(p[1]) 17488 || (p[1] == '.' 17489 && (p[2] == NUL 17490 || vim_ispathsep(p[2])))))) 17491 { 17492 /* Prepend "./". */ 17493 cpy = concat_str((char_u *)"./", p); 17494 if (cpy != NULL) 17495 { 17496 vim_free(p); 17497 p = cpy; 17498 } 17499 } 17500 else if (!is_relative_to_current) 17501 { 17502 /* Strip leading "./". */ 17503 q = p; 17504 while (q[0] == '.' && vim_ispathsep(q[1])) 17505 q += 2; 17506 if (q > p) 17507 STRMOVE(p, p + 2); 17508 } 17509 } 17510 17511 /* Ensure that the result will have no trailing path separator 17512 * if the argument had none. But keep "/" or "//". */ 17513 if (!has_trailing_pathsep) 17514 { 17515 q = p + STRLEN(p); 17516 if (after_pathsep(p, q)) 17517 *gettail_sep(p) = NUL; 17518 } 17519 17520 rettv->vval.v_string = p; 17521 } 17522 # else 17523 rettv->vval.v_string = vim_strsave(p); 17524 # endif 17525 #endif 17526 17527 simplify_filename(rettv->vval.v_string); 17528 17529 #ifdef HAVE_READLINK 17530 fail: 17531 vim_free(buf); 17532 #endif 17533 rettv->v_type = VAR_STRING; 17534 } 17535 17536 /* 17537 * "reverse({list})" function 17538 */ 17539 static void 17540 f_reverse(typval_T *argvars, typval_T *rettv) 17541 { 17542 list_T *l; 17543 listitem_T *li, *ni; 17544 17545 if (argvars[0].v_type != VAR_LIST) 17546 EMSG2(_(e_listarg), "reverse()"); 17547 else if ((l = argvars[0].vval.v_list) != NULL 17548 && !tv_check_lock(l->lv_lock, 17549 (char_u *)N_("reverse() argument"), TRUE)) 17550 { 17551 li = l->lv_last; 17552 l->lv_first = l->lv_last = NULL; 17553 l->lv_len = 0; 17554 while (li != NULL) 17555 { 17556 ni = li->li_prev; 17557 list_append(l, li); 17558 li = ni; 17559 } 17560 rettv->vval.v_list = l; 17561 rettv->v_type = VAR_LIST; 17562 ++l->lv_refcount; 17563 l->lv_idx = l->lv_len - l->lv_idx - 1; 17564 } 17565 } 17566 17567 #define SP_NOMOVE 0x01 /* don't move cursor */ 17568 #define SP_REPEAT 0x02 /* repeat to find outer pair */ 17569 #define SP_RETCOUNT 0x04 /* return matchcount */ 17570 #define SP_SETPCMARK 0x08 /* set previous context mark */ 17571 #define SP_START 0x10 /* accept match at start position */ 17572 #define SP_SUBPAT 0x20 /* return nr of matching sub-pattern */ 17573 #define SP_END 0x40 /* leave cursor at end of match */ 17574 #define SP_COLUMN 0x80 /* start at cursor column */ 17575 17576 static int get_search_arg(typval_T *varp, int *flagsp); 17577 17578 /* 17579 * Get flags for a search function. 17580 * Possibly sets "p_ws". 17581 * Returns BACKWARD, FORWARD or zero (for an error). 17582 */ 17583 static int 17584 get_search_arg(typval_T *varp, int *flagsp) 17585 { 17586 int dir = FORWARD; 17587 char_u *flags; 17588 char_u nbuf[NUMBUFLEN]; 17589 int mask; 17590 17591 if (varp->v_type != VAR_UNKNOWN) 17592 { 17593 flags = get_tv_string_buf_chk(varp, nbuf); 17594 if (flags == NULL) 17595 return 0; /* type error; errmsg already given */ 17596 while (*flags != NUL) 17597 { 17598 switch (*flags) 17599 { 17600 case 'b': dir = BACKWARD; break; 17601 case 'w': p_ws = TRUE; break; 17602 case 'W': p_ws = FALSE; break; 17603 default: mask = 0; 17604 if (flagsp != NULL) 17605 switch (*flags) 17606 { 17607 case 'c': mask = SP_START; break; 17608 case 'e': mask = SP_END; break; 17609 case 'm': mask = SP_RETCOUNT; break; 17610 case 'n': mask = SP_NOMOVE; break; 17611 case 'p': mask = SP_SUBPAT; break; 17612 case 'r': mask = SP_REPEAT; break; 17613 case 's': mask = SP_SETPCMARK; break; 17614 case 'z': mask = SP_COLUMN; break; 17615 } 17616 if (mask == 0) 17617 { 17618 EMSG2(_(e_invarg2), flags); 17619 dir = 0; 17620 } 17621 else 17622 *flagsp |= mask; 17623 } 17624 if (dir == 0) 17625 break; 17626 ++flags; 17627 } 17628 } 17629 return dir; 17630 } 17631 17632 /* 17633 * Shared by search() and searchpos() functions. 17634 */ 17635 static int 17636 search_cmn(typval_T *argvars, pos_T *match_pos, int *flagsp) 17637 { 17638 int flags; 17639 char_u *pat; 17640 pos_T pos; 17641 pos_T save_cursor; 17642 int save_p_ws = p_ws; 17643 int dir; 17644 int retval = 0; /* default: FAIL */ 17645 long lnum_stop = 0; 17646 proftime_T tm; 17647 #ifdef FEAT_RELTIME 17648 long time_limit = 0; 17649 #endif 17650 int options = SEARCH_KEEP; 17651 int subpatnum; 17652 17653 pat = get_tv_string(&argvars[0]); 17654 dir = get_search_arg(&argvars[1], flagsp); /* may set p_ws */ 17655 if (dir == 0) 17656 goto theend; 17657 flags = *flagsp; 17658 if (flags & SP_START) 17659 options |= SEARCH_START; 17660 if (flags & SP_END) 17661 options |= SEARCH_END; 17662 if (flags & SP_COLUMN) 17663 options |= SEARCH_COL; 17664 17665 /* Optional arguments: line number to stop searching and timeout. */ 17666 if (argvars[1].v_type != VAR_UNKNOWN && argvars[2].v_type != VAR_UNKNOWN) 17667 { 17668 lnum_stop = get_tv_number_chk(&argvars[2], NULL); 17669 if (lnum_stop < 0) 17670 goto theend; 17671 #ifdef FEAT_RELTIME 17672 if (argvars[3].v_type != VAR_UNKNOWN) 17673 { 17674 time_limit = get_tv_number_chk(&argvars[3], NULL); 17675 if (time_limit < 0) 17676 goto theend; 17677 } 17678 #endif 17679 } 17680 17681 #ifdef FEAT_RELTIME 17682 /* Set the time limit, if there is one. */ 17683 profile_setlimit(time_limit, &tm); 17684 #endif 17685 17686 /* 17687 * This function does not accept SP_REPEAT and SP_RETCOUNT flags. 17688 * Check to make sure only those flags are set. 17689 * Also, Only the SP_NOMOVE or the SP_SETPCMARK flag can be set. Both 17690 * flags cannot be set. Check for that condition also. 17691 */ 17692 if (((flags & (SP_REPEAT | SP_RETCOUNT)) != 0) 17693 || ((flags & SP_NOMOVE) && (flags & SP_SETPCMARK))) 17694 { 17695 EMSG2(_(e_invarg2), get_tv_string(&argvars[1])); 17696 goto theend; 17697 } 17698 17699 pos = save_cursor = curwin->w_cursor; 17700 subpatnum = searchit(curwin, curbuf, &pos, dir, pat, 1L, 17701 options, RE_SEARCH, (linenr_T)lnum_stop, &tm); 17702 if (subpatnum != FAIL) 17703 { 17704 if (flags & SP_SUBPAT) 17705 retval = subpatnum; 17706 else 17707 retval = pos.lnum; 17708 if (flags & SP_SETPCMARK) 17709 setpcmark(); 17710 curwin->w_cursor = pos; 17711 if (match_pos != NULL) 17712 { 17713 /* Store the match cursor position */ 17714 match_pos->lnum = pos.lnum; 17715 match_pos->col = pos.col + 1; 17716 } 17717 /* "/$" will put the cursor after the end of the line, may need to 17718 * correct that here */ 17719 check_cursor(); 17720 } 17721 17722 /* If 'n' flag is used: restore cursor position. */ 17723 if (flags & SP_NOMOVE) 17724 curwin->w_cursor = save_cursor; 17725 else 17726 curwin->w_set_curswant = TRUE; 17727 theend: 17728 p_ws = save_p_ws; 17729 17730 return retval; 17731 } 17732 17733 #ifdef FEAT_FLOAT 17734 17735 /* 17736 * round() is not in C90, use ceil() or floor() instead. 17737 */ 17738 float_T 17739 vim_round(float_T f) 17740 { 17741 return f > 0 ? floor(f + 0.5) : ceil(f - 0.5); 17742 } 17743 17744 /* 17745 * "round({float})" function 17746 */ 17747 static void 17748 f_round(typval_T *argvars, typval_T *rettv) 17749 { 17750 float_T f = 0.0; 17751 17752 rettv->v_type = VAR_FLOAT; 17753 if (get_float_arg(argvars, &f) == OK) 17754 rettv->vval.v_float = vim_round(f); 17755 else 17756 rettv->vval.v_float = 0.0; 17757 } 17758 #endif 17759 17760 /* 17761 * "screenattr()" function 17762 */ 17763 static void 17764 f_screenattr(typval_T *argvars, typval_T *rettv) 17765 { 17766 int row; 17767 int col; 17768 int c; 17769 17770 row = get_tv_number_chk(&argvars[0], NULL) - 1; 17771 col = get_tv_number_chk(&argvars[1], NULL) - 1; 17772 if (row < 0 || row >= screen_Rows 17773 || col < 0 || col >= screen_Columns) 17774 c = -1; 17775 else 17776 c = ScreenAttrs[LineOffset[row] + col]; 17777 rettv->vval.v_number = c; 17778 } 17779 17780 /* 17781 * "screenchar()" function 17782 */ 17783 static void 17784 f_screenchar(typval_T *argvars, typval_T *rettv) 17785 { 17786 int row; 17787 int col; 17788 int off; 17789 int c; 17790 17791 row = get_tv_number_chk(&argvars[0], NULL) - 1; 17792 col = get_tv_number_chk(&argvars[1], NULL) - 1; 17793 if (row < 0 || row >= screen_Rows 17794 || col < 0 || col >= screen_Columns) 17795 c = -1; 17796 else 17797 { 17798 off = LineOffset[row] + col; 17799 #ifdef FEAT_MBYTE 17800 if (enc_utf8 && ScreenLinesUC[off] != 0) 17801 c = ScreenLinesUC[off]; 17802 else 17803 #endif 17804 c = ScreenLines[off]; 17805 } 17806 rettv->vval.v_number = c; 17807 } 17808 17809 /* 17810 * "screencol()" function 17811 * 17812 * First column is 1 to be consistent with virtcol(). 17813 */ 17814 static void 17815 f_screencol(typval_T *argvars UNUSED, typval_T *rettv) 17816 { 17817 rettv->vval.v_number = screen_screencol() + 1; 17818 } 17819 17820 /* 17821 * "screenrow()" function 17822 */ 17823 static void 17824 f_screenrow(typval_T *argvars UNUSED, typval_T *rettv) 17825 { 17826 rettv->vval.v_number = screen_screenrow() + 1; 17827 } 17828 17829 /* 17830 * "search()" function 17831 */ 17832 static void 17833 f_search(typval_T *argvars, typval_T *rettv) 17834 { 17835 int flags = 0; 17836 17837 rettv->vval.v_number = search_cmn(argvars, NULL, &flags); 17838 } 17839 17840 /* 17841 * "searchdecl()" function 17842 */ 17843 static void 17844 f_searchdecl(typval_T *argvars, typval_T *rettv) 17845 { 17846 int locally = 1; 17847 int thisblock = 0; 17848 int error = FALSE; 17849 char_u *name; 17850 17851 rettv->vval.v_number = 1; /* default: FAIL */ 17852 17853 name = get_tv_string_chk(&argvars[0]); 17854 if (argvars[1].v_type != VAR_UNKNOWN) 17855 { 17856 locally = get_tv_number_chk(&argvars[1], &error) == 0; 17857 if (!error && argvars[2].v_type != VAR_UNKNOWN) 17858 thisblock = get_tv_number_chk(&argvars[2], &error) != 0; 17859 } 17860 if (!error && name != NULL) 17861 rettv->vval.v_number = find_decl(name, (int)STRLEN(name), 17862 locally, thisblock, SEARCH_KEEP) == FAIL; 17863 } 17864 17865 /* 17866 * Used by searchpair() and searchpairpos() 17867 */ 17868 static int 17869 searchpair_cmn(typval_T *argvars, pos_T *match_pos) 17870 { 17871 char_u *spat, *mpat, *epat; 17872 char_u *skip; 17873 int save_p_ws = p_ws; 17874 int dir; 17875 int flags = 0; 17876 char_u nbuf1[NUMBUFLEN]; 17877 char_u nbuf2[NUMBUFLEN]; 17878 char_u nbuf3[NUMBUFLEN]; 17879 int retval = 0; /* default: FAIL */ 17880 long lnum_stop = 0; 17881 long time_limit = 0; 17882 17883 /* Get the three pattern arguments: start, middle, end. */ 17884 spat = get_tv_string_chk(&argvars[0]); 17885 mpat = get_tv_string_buf_chk(&argvars[1], nbuf1); 17886 epat = get_tv_string_buf_chk(&argvars[2], nbuf2); 17887 if (spat == NULL || mpat == NULL || epat == NULL) 17888 goto theend; /* type error */ 17889 17890 /* Handle the optional fourth argument: flags */ 17891 dir = get_search_arg(&argvars[3], &flags); /* may set p_ws */ 17892 if (dir == 0) 17893 goto theend; 17894 17895 /* Don't accept SP_END or SP_SUBPAT. 17896 * Only one of the SP_NOMOVE or SP_SETPCMARK flags can be set. 17897 */ 17898 if ((flags & (SP_END | SP_SUBPAT)) != 0 17899 || ((flags & SP_NOMOVE) && (flags & SP_SETPCMARK))) 17900 { 17901 EMSG2(_(e_invarg2), get_tv_string(&argvars[3])); 17902 goto theend; 17903 } 17904 17905 /* Using 'r' implies 'W', otherwise it doesn't work. */ 17906 if (flags & SP_REPEAT) 17907 p_ws = FALSE; 17908 17909 /* Optional fifth argument: skip expression */ 17910 if (argvars[3].v_type == VAR_UNKNOWN 17911 || argvars[4].v_type == VAR_UNKNOWN) 17912 skip = (char_u *)""; 17913 else 17914 { 17915 skip = get_tv_string_buf_chk(&argvars[4], nbuf3); 17916 if (argvars[5].v_type != VAR_UNKNOWN) 17917 { 17918 lnum_stop = get_tv_number_chk(&argvars[5], NULL); 17919 if (lnum_stop < 0) 17920 goto theend; 17921 #ifdef FEAT_RELTIME 17922 if (argvars[6].v_type != VAR_UNKNOWN) 17923 { 17924 time_limit = get_tv_number_chk(&argvars[6], NULL); 17925 if (time_limit < 0) 17926 goto theend; 17927 } 17928 #endif 17929 } 17930 } 17931 if (skip == NULL) 17932 goto theend; /* type error */ 17933 17934 retval = do_searchpair(spat, mpat, epat, dir, skip, flags, 17935 match_pos, lnum_stop, time_limit); 17936 17937 theend: 17938 p_ws = save_p_ws; 17939 17940 return retval; 17941 } 17942 17943 /* 17944 * "searchpair()" function 17945 */ 17946 static void 17947 f_searchpair(typval_T *argvars, typval_T *rettv) 17948 { 17949 rettv->vval.v_number = searchpair_cmn(argvars, NULL); 17950 } 17951 17952 /* 17953 * "searchpairpos()" function 17954 */ 17955 static void 17956 f_searchpairpos(typval_T *argvars, typval_T *rettv) 17957 { 17958 pos_T match_pos; 17959 int lnum = 0; 17960 int col = 0; 17961 17962 if (rettv_list_alloc(rettv) == FAIL) 17963 return; 17964 17965 if (searchpair_cmn(argvars, &match_pos) > 0) 17966 { 17967 lnum = match_pos.lnum; 17968 col = match_pos.col; 17969 } 17970 17971 list_append_number(rettv->vval.v_list, (varnumber_T)lnum); 17972 list_append_number(rettv->vval.v_list, (varnumber_T)col); 17973 } 17974 17975 /* 17976 * Search for a start/middle/end thing. 17977 * Used by searchpair(), see its documentation for the details. 17978 * Returns 0 or -1 for no match, 17979 */ 17980 long 17981 do_searchpair( 17982 char_u *spat, /* start pattern */ 17983 char_u *mpat, /* middle pattern */ 17984 char_u *epat, /* end pattern */ 17985 int dir, /* BACKWARD or FORWARD */ 17986 char_u *skip, /* skip expression */ 17987 int flags, /* SP_SETPCMARK and other SP_ values */ 17988 pos_T *match_pos, 17989 linenr_T lnum_stop, /* stop at this line if not zero */ 17990 long time_limit UNUSED) /* stop after this many msec */ 17991 { 17992 char_u *save_cpo; 17993 char_u *pat, *pat2 = NULL, *pat3 = NULL; 17994 long retval = 0; 17995 pos_T pos; 17996 pos_T firstpos; 17997 pos_T foundpos; 17998 pos_T save_cursor; 17999 pos_T save_pos; 18000 int n; 18001 int r; 18002 int nest = 1; 18003 int err; 18004 int options = SEARCH_KEEP; 18005 proftime_T tm; 18006 18007 /* Make 'cpoptions' empty, the 'l' flag should not be used here. */ 18008 save_cpo = p_cpo; 18009 p_cpo = empty_option; 18010 18011 #ifdef FEAT_RELTIME 18012 /* Set the time limit, if there is one. */ 18013 profile_setlimit(time_limit, &tm); 18014 #endif 18015 18016 /* Make two search patterns: start/end (pat2, for in nested pairs) and 18017 * start/middle/end (pat3, for the top pair). */ 18018 pat2 = alloc((unsigned)(STRLEN(spat) + STRLEN(epat) + 15)); 18019 pat3 = alloc((unsigned)(STRLEN(spat) + STRLEN(mpat) + STRLEN(epat) + 23)); 18020 if (pat2 == NULL || pat3 == NULL) 18021 goto theend; 18022 sprintf((char *)pat2, "\\(%s\\m\\)\\|\\(%s\\m\\)", spat, epat); 18023 if (*mpat == NUL) 18024 STRCPY(pat3, pat2); 18025 else 18026 sprintf((char *)pat3, "\\(%s\\m\\)\\|\\(%s\\m\\)\\|\\(%s\\m\\)", 18027 spat, epat, mpat); 18028 if (flags & SP_START) 18029 options |= SEARCH_START; 18030 18031 save_cursor = curwin->w_cursor; 18032 pos = curwin->w_cursor; 18033 clearpos(&firstpos); 18034 clearpos(&foundpos); 18035 pat = pat3; 18036 for (;;) 18037 { 18038 n = searchit(curwin, curbuf, &pos, dir, pat, 1L, 18039 options, RE_SEARCH, lnum_stop, &tm); 18040 if (n == FAIL || (firstpos.lnum != 0 && equalpos(pos, firstpos))) 18041 /* didn't find it or found the first match again: FAIL */ 18042 break; 18043 18044 if (firstpos.lnum == 0) 18045 firstpos = pos; 18046 if (equalpos(pos, foundpos)) 18047 { 18048 /* Found the same position again. Can happen with a pattern that 18049 * has "\zs" at the end and searching backwards. Advance one 18050 * character and try again. */ 18051 if (dir == BACKWARD) 18052 decl(&pos); 18053 else 18054 incl(&pos); 18055 } 18056 foundpos = pos; 18057 18058 /* clear the start flag to avoid getting stuck here */ 18059 options &= ~SEARCH_START; 18060 18061 /* If the skip pattern matches, ignore this match. */ 18062 if (*skip != NUL) 18063 { 18064 save_pos = curwin->w_cursor; 18065 curwin->w_cursor = pos; 18066 r = eval_to_bool(skip, &err, NULL, FALSE); 18067 curwin->w_cursor = save_pos; 18068 if (err) 18069 { 18070 /* Evaluating {skip} caused an error, break here. */ 18071 curwin->w_cursor = save_cursor; 18072 retval = -1; 18073 break; 18074 } 18075 if (r) 18076 continue; 18077 } 18078 18079 if ((dir == BACKWARD && n == 3) || (dir == FORWARD && n == 2)) 18080 { 18081 /* Found end when searching backwards or start when searching 18082 * forward: nested pair. */ 18083 ++nest; 18084 pat = pat2; /* nested, don't search for middle */ 18085 } 18086 else 18087 { 18088 /* Found end when searching forward or start when searching 18089 * backward: end of (nested) pair; or found middle in outer pair. */ 18090 if (--nest == 1) 18091 pat = pat3; /* outer level, search for middle */ 18092 } 18093 18094 if (nest == 0) 18095 { 18096 /* Found the match: return matchcount or line number. */ 18097 if (flags & SP_RETCOUNT) 18098 ++retval; 18099 else 18100 retval = pos.lnum; 18101 if (flags & SP_SETPCMARK) 18102 setpcmark(); 18103 curwin->w_cursor = pos; 18104 if (!(flags & SP_REPEAT)) 18105 break; 18106 nest = 1; /* search for next unmatched */ 18107 } 18108 } 18109 18110 if (match_pos != NULL) 18111 { 18112 /* Store the match cursor position */ 18113 match_pos->lnum = curwin->w_cursor.lnum; 18114 match_pos->col = curwin->w_cursor.col + 1; 18115 } 18116 18117 /* If 'n' flag is used or search failed: restore cursor position. */ 18118 if ((flags & SP_NOMOVE) || retval == 0) 18119 curwin->w_cursor = save_cursor; 18120 18121 theend: 18122 vim_free(pat2); 18123 vim_free(pat3); 18124 if (p_cpo == empty_option) 18125 p_cpo = save_cpo; 18126 else 18127 /* Darn, evaluating the {skip} expression changed the value. */ 18128 free_string_option(save_cpo); 18129 18130 return retval; 18131 } 18132 18133 /* 18134 * "searchpos()" function 18135 */ 18136 static void 18137 f_searchpos(typval_T *argvars, typval_T *rettv) 18138 { 18139 pos_T match_pos; 18140 int lnum = 0; 18141 int col = 0; 18142 int n; 18143 int flags = 0; 18144 18145 if (rettv_list_alloc(rettv) == FAIL) 18146 return; 18147 18148 n = search_cmn(argvars, &match_pos, &flags); 18149 if (n > 0) 18150 { 18151 lnum = match_pos.lnum; 18152 col = match_pos.col; 18153 } 18154 18155 list_append_number(rettv->vval.v_list, (varnumber_T)lnum); 18156 list_append_number(rettv->vval.v_list, (varnumber_T)col); 18157 if (flags & SP_SUBPAT) 18158 list_append_number(rettv->vval.v_list, (varnumber_T)n); 18159 } 18160 18161 static void 18162 f_server2client(typval_T *argvars UNUSED, typval_T *rettv) 18163 { 18164 #ifdef FEAT_CLIENTSERVER 18165 char_u buf[NUMBUFLEN]; 18166 char_u *server = get_tv_string_chk(&argvars[0]); 18167 char_u *reply = get_tv_string_buf_chk(&argvars[1], buf); 18168 18169 rettv->vval.v_number = -1; 18170 if (server == NULL || reply == NULL) 18171 return; 18172 if (check_restricted() || check_secure()) 18173 return; 18174 # ifdef FEAT_X11 18175 if (check_connection() == FAIL) 18176 return; 18177 # endif 18178 18179 if (serverSendReply(server, reply) < 0) 18180 { 18181 EMSG(_("E258: Unable to send to client")); 18182 return; 18183 } 18184 rettv->vval.v_number = 0; 18185 #else 18186 rettv->vval.v_number = -1; 18187 #endif 18188 } 18189 18190 static void 18191 f_serverlist(typval_T *argvars UNUSED, typval_T *rettv) 18192 { 18193 char_u *r = NULL; 18194 18195 #ifdef FEAT_CLIENTSERVER 18196 # ifdef WIN32 18197 r = serverGetVimNames(); 18198 # else 18199 make_connection(); 18200 if (X_DISPLAY != NULL) 18201 r = serverGetVimNames(X_DISPLAY); 18202 # endif 18203 #endif 18204 rettv->v_type = VAR_STRING; 18205 rettv->vval.v_string = r; 18206 } 18207 18208 /* 18209 * "setbufvar()" function 18210 */ 18211 static void 18212 f_setbufvar(typval_T *argvars, typval_T *rettv UNUSED) 18213 { 18214 buf_T *buf; 18215 aco_save_T aco; 18216 char_u *varname, *bufvarname; 18217 typval_T *varp; 18218 char_u nbuf[NUMBUFLEN]; 18219 18220 if (check_restricted() || check_secure()) 18221 return; 18222 (void)get_tv_number(&argvars[0]); /* issue errmsg if type error */ 18223 varname = get_tv_string_chk(&argvars[1]); 18224 buf = get_buf_tv(&argvars[0], FALSE); 18225 varp = &argvars[2]; 18226 18227 if (buf != NULL && varname != NULL && varp != NULL) 18228 { 18229 /* set curbuf to be our buf, temporarily */ 18230 aucmd_prepbuf(&aco, buf); 18231 18232 if (*varname == '&') 18233 { 18234 long numval; 18235 char_u *strval; 18236 int error = FALSE; 18237 18238 ++varname; 18239 numval = get_tv_number_chk(varp, &error); 18240 strval = get_tv_string_buf_chk(varp, nbuf); 18241 if (!error && strval != NULL) 18242 set_option_value(varname, numval, strval, OPT_LOCAL); 18243 } 18244 else 18245 { 18246 bufvarname = alloc((unsigned)STRLEN(varname) + 3); 18247 if (bufvarname != NULL) 18248 { 18249 STRCPY(bufvarname, "b:"); 18250 STRCPY(bufvarname + 2, varname); 18251 set_var(bufvarname, varp, TRUE); 18252 vim_free(bufvarname); 18253 } 18254 } 18255 18256 /* reset notion of buffer */ 18257 aucmd_restbuf(&aco); 18258 } 18259 } 18260 18261 static void 18262 f_setcharsearch(typval_T *argvars, typval_T *rettv UNUSED) 18263 { 18264 dict_T *d; 18265 dictitem_T *di; 18266 char_u *csearch; 18267 18268 if (argvars[0].v_type != VAR_DICT) 18269 { 18270 EMSG(_(e_dictreq)); 18271 return; 18272 } 18273 18274 if ((d = argvars[0].vval.v_dict) != NULL) 18275 { 18276 csearch = get_dict_string(d, (char_u *)"char", FALSE); 18277 if (csearch != NULL) 18278 { 18279 #ifdef FEAT_MBYTE 18280 if (enc_utf8) 18281 { 18282 int pcc[MAX_MCO]; 18283 int c = utfc_ptr2char(csearch, pcc); 18284 18285 set_last_csearch(c, csearch, utfc_ptr2len(csearch)); 18286 } 18287 else 18288 #endif 18289 set_last_csearch(PTR2CHAR(csearch), 18290 csearch, MB_PTR2LEN(csearch)); 18291 } 18292 18293 di = dict_find(d, (char_u *)"forward", -1); 18294 if (di != NULL) 18295 set_csearch_direction(get_tv_number(&di->di_tv) 18296 ? FORWARD : BACKWARD); 18297 18298 di = dict_find(d, (char_u *)"until", -1); 18299 if (di != NULL) 18300 set_csearch_until(!!get_tv_number(&di->di_tv)); 18301 } 18302 } 18303 18304 /* 18305 * "setcmdpos()" function 18306 */ 18307 static void 18308 f_setcmdpos(typval_T *argvars, typval_T *rettv) 18309 { 18310 int pos = (int)get_tv_number(&argvars[0]) - 1; 18311 18312 if (pos >= 0) 18313 rettv->vval.v_number = set_cmdline_pos(pos); 18314 } 18315 18316 /* 18317 * "setfperm({fname}, {mode})" function 18318 */ 18319 static void 18320 f_setfperm(typval_T *argvars, typval_T *rettv) 18321 { 18322 char_u *fname; 18323 char_u modebuf[NUMBUFLEN]; 18324 char_u *mode_str; 18325 int i; 18326 int mask; 18327 int mode = 0; 18328 18329 rettv->vval.v_number = 0; 18330 fname = get_tv_string_chk(&argvars[0]); 18331 if (fname == NULL) 18332 return; 18333 mode_str = get_tv_string_buf_chk(&argvars[1], modebuf); 18334 if (mode_str == NULL) 18335 return; 18336 if (STRLEN(mode_str) != 9) 18337 { 18338 EMSG2(_(e_invarg2), mode_str); 18339 return; 18340 } 18341 18342 mask = 1; 18343 for (i = 8; i >= 0; --i) 18344 { 18345 if (mode_str[i] != '-') 18346 mode |= mask; 18347 mask = mask << 1; 18348 } 18349 rettv->vval.v_number = mch_setperm(fname, mode) == OK; 18350 } 18351 18352 /* 18353 * "setline()" function 18354 */ 18355 static void 18356 f_setline(typval_T *argvars, typval_T *rettv) 18357 { 18358 linenr_T lnum; 18359 char_u *line = NULL; 18360 list_T *l = NULL; 18361 listitem_T *li = NULL; 18362 long added = 0; 18363 linenr_T lcount = curbuf->b_ml.ml_line_count; 18364 18365 lnum = get_tv_lnum(&argvars[0]); 18366 if (argvars[1].v_type == VAR_LIST) 18367 { 18368 l = argvars[1].vval.v_list; 18369 li = l->lv_first; 18370 } 18371 else 18372 line = get_tv_string_chk(&argvars[1]); 18373 18374 /* default result is zero == OK */ 18375 for (;;) 18376 { 18377 if (l != NULL) 18378 { 18379 /* list argument, get next string */ 18380 if (li == NULL) 18381 break; 18382 line = get_tv_string_chk(&li->li_tv); 18383 li = li->li_next; 18384 } 18385 18386 rettv->vval.v_number = 1; /* FAIL */ 18387 if (line == NULL || lnum < 1 || lnum > curbuf->b_ml.ml_line_count + 1) 18388 break; 18389 18390 /* When coming here from Insert mode, sync undo, so that this can be 18391 * undone separately from what was previously inserted. */ 18392 if (u_sync_once == 2) 18393 { 18394 u_sync_once = 1; /* notify that u_sync() was called */ 18395 u_sync(TRUE); 18396 } 18397 18398 if (lnum <= curbuf->b_ml.ml_line_count) 18399 { 18400 /* existing line, replace it */ 18401 if (u_savesub(lnum) == OK && ml_replace(lnum, line, TRUE) == OK) 18402 { 18403 changed_bytes(lnum, 0); 18404 if (lnum == curwin->w_cursor.lnum) 18405 check_cursor_col(); 18406 rettv->vval.v_number = 0; /* OK */ 18407 } 18408 } 18409 else if (added > 0 || u_save(lnum - 1, lnum) == OK) 18410 { 18411 /* lnum is one past the last line, append the line */ 18412 ++added; 18413 if (ml_append(lnum - 1, line, (colnr_T)0, FALSE) == OK) 18414 rettv->vval.v_number = 0; /* OK */ 18415 } 18416 18417 if (l == NULL) /* only one string argument */ 18418 break; 18419 ++lnum; 18420 } 18421 18422 if (added > 0) 18423 appended_lines_mark(lcount, added); 18424 } 18425 18426 static void set_qf_ll_list(win_T *wp, typval_T *list_arg, typval_T *action_arg, typval_T *rettv); 18427 18428 /* 18429 * Used by "setqflist()" and "setloclist()" functions 18430 */ 18431 static void 18432 set_qf_ll_list( 18433 win_T *wp UNUSED, 18434 typval_T *list_arg UNUSED, 18435 typval_T *action_arg UNUSED, 18436 typval_T *rettv) 18437 { 18438 #ifdef FEAT_QUICKFIX 18439 static char *e_invact = N_("E927: Invalid action: '%s'"); 18440 char_u *act; 18441 int action = 0; 18442 #endif 18443 18444 rettv->vval.v_number = -1; 18445 18446 #ifdef FEAT_QUICKFIX 18447 if (list_arg->v_type != VAR_LIST) 18448 EMSG(_(e_listreq)); 18449 else 18450 { 18451 list_T *l = list_arg->vval.v_list; 18452 18453 if (action_arg->v_type == VAR_STRING) 18454 { 18455 act = get_tv_string_chk(action_arg); 18456 if (act == NULL) 18457 return; /* type error; errmsg already given */ 18458 if ((*act == 'a' || *act == 'r' || *act == ' ') && act[1] == NUL) 18459 action = *act; 18460 else 18461 EMSG2(_(e_invact), act); 18462 } 18463 else if (action_arg->v_type == VAR_UNKNOWN) 18464 action = ' '; 18465 else 18466 EMSG(_(e_stringreq)); 18467 18468 if (l != NULL && action && set_errorlist(wp, l, action, 18469 (char_u *)(wp == NULL ? "setqflist()" : "setloclist()")) == OK) 18470 rettv->vval.v_number = 0; 18471 } 18472 #endif 18473 } 18474 18475 /* 18476 * "setloclist()" function 18477 */ 18478 static void 18479 f_setloclist(typval_T *argvars, typval_T *rettv) 18480 { 18481 win_T *win; 18482 18483 rettv->vval.v_number = -1; 18484 18485 win = find_win_by_nr(&argvars[0], NULL); 18486 if (win != NULL) 18487 set_qf_ll_list(win, &argvars[1], &argvars[2], rettv); 18488 } 18489 18490 /* 18491 * "setmatches()" function 18492 */ 18493 static void 18494 f_setmatches(typval_T *argvars UNUSED, typval_T *rettv UNUSED) 18495 { 18496 #ifdef FEAT_SEARCH_EXTRA 18497 list_T *l; 18498 listitem_T *li; 18499 dict_T *d; 18500 list_T *s = NULL; 18501 18502 rettv->vval.v_number = -1; 18503 if (argvars[0].v_type != VAR_LIST) 18504 { 18505 EMSG(_(e_listreq)); 18506 return; 18507 } 18508 if ((l = argvars[0].vval.v_list) != NULL) 18509 { 18510 18511 /* To some extent make sure that we are dealing with a list from 18512 * "getmatches()". */ 18513 li = l->lv_first; 18514 while (li != NULL) 18515 { 18516 if (li->li_tv.v_type != VAR_DICT 18517 || (d = li->li_tv.vval.v_dict) == NULL) 18518 { 18519 EMSG(_(e_invarg)); 18520 return; 18521 } 18522 if (!(dict_find(d, (char_u *)"group", -1) != NULL 18523 && (dict_find(d, (char_u *)"pattern", -1) != NULL 18524 || dict_find(d, (char_u *)"pos1", -1) != NULL) 18525 && dict_find(d, (char_u *)"priority", -1) != NULL 18526 && dict_find(d, (char_u *)"id", -1) != NULL)) 18527 { 18528 EMSG(_(e_invarg)); 18529 return; 18530 } 18531 li = li->li_next; 18532 } 18533 18534 clear_matches(curwin); 18535 li = l->lv_first; 18536 while (li != NULL) 18537 { 18538 int i = 0; 18539 char_u buf[5]; 18540 dictitem_T *di; 18541 char_u *group; 18542 int priority; 18543 int id; 18544 char_u *conceal; 18545 18546 d = li->li_tv.vval.v_dict; 18547 if (dict_find(d, (char_u *)"pattern", -1) == NULL) 18548 { 18549 if (s == NULL) 18550 { 18551 s = list_alloc(); 18552 if (s == NULL) 18553 return; 18554 } 18555 18556 /* match from matchaddpos() */ 18557 for (i = 1; i < 9; i++) 18558 { 18559 sprintf((char *)buf, (char *)"pos%d", i); 18560 if ((di = dict_find(d, (char_u *)buf, -1)) != NULL) 18561 { 18562 if (di->di_tv.v_type != VAR_LIST) 18563 return; 18564 18565 list_append_tv(s, &di->di_tv); 18566 s->lv_refcount++; 18567 } 18568 else 18569 break; 18570 } 18571 } 18572 18573 group = get_dict_string(d, (char_u *)"group", FALSE); 18574 priority = (int)get_dict_number(d, (char_u *)"priority"); 18575 id = (int)get_dict_number(d, (char_u *)"id"); 18576 conceal = dict_find(d, (char_u *)"conceal", -1) != NULL 18577 ? get_dict_string(d, (char_u *)"conceal", FALSE) 18578 : NULL; 18579 if (i == 0) 18580 { 18581 match_add(curwin, group, 18582 get_dict_string(d, (char_u *)"pattern", FALSE), 18583 priority, id, NULL, conceal); 18584 } 18585 else 18586 { 18587 match_add(curwin, group, NULL, priority, id, s, conceal); 18588 list_unref(s); 18589 s = NULL; 18590 } 18591 18592 li = li->li_next; 18593 } 18594 rettv->vval.v_number = 0; 18595 } 18596 #endif 18597 } 18598 18599 /* 18600 * "setpos()" function 18601 */ 18602 static void 18603 f_setpos(typval_T *argvars, typval_T *rettv) 18604 { 18605 pos_T pos; 18606 int fnum; 18607 char_u *name; 18608 colnr_T curswant = -1; 18609 18610 rettv->vval.v_number = -1; 18611 name = get_tv_string_chk(argvars); 18612 if (name != NULL) 18613 { 18614 if (list2fpos(&argvars[1], &pos, &fnum, &curswant) == OK) 18615 { 18616 if (--pos.col < 0) 18617 pos.col = 0; 18618 if (name[0] == '.' && name[1] == NUL) 18619 { 18620 /* set cursor */ 18621 if (fnum == curbuf->b_fnum) 18622 { 18623 curwin->w_cursor = pos; 18624 if (curswant >= 0) 18625 { 18626 curwin->w_curswant = curswant - 1; 18627 curwin->w_set_curswant = FALSE; 18628 } 18629 check_cursor(); 18630 rettv->vval.v_number = 0; 18631 } 18632 else 18633 EMSG(_(e_invarg)); 18634 } 18635 else if (name[0] == '\'' && name[1] != NUL && name[2] == NUL) 18636 { 18637 /* set mark */ 18638 if (setmark_pos(name[1], &pos, fnum) == OK) 18639 rettv->vval.v_number = 0; 18640 } 18641 else 18642 EMSG(_(e_invarg)); 18643 } 18644 } 18645 } 18646 18647 /* 18648 * "setqflist()" function 18649 */ 18650 static void 18651 f_setqflist(typval_T *argvars, typval_T *rettv) 18652 { 18653 set_qf_ll_list(NULL, &argvars[0], &argvars[1], rettv); 18654 } 18655 18656 /* 18657 * "setreg()" function 18658 */ 18659 static void 18660 f_setreg(typval_T *argvars, typval_T *rettv) 18661 { 18662 int regname; 18663 char_u *strregname; 18664 char_u *stropt; 18665 char_u *strval; 18666 int append; 18667 char_u yank_type; 18668 long block_len; 18669 18670 block_len = -1; 18671 yank_type = MAUTO; 18672 append = FALSE; 18673 18674 strregname = get_tv_string_chk(argvars); 18675 rettv->vval.v_number = 1; /* FAIL is default */ 18676 18677 if (strregname == NULL) 18678 return; /* type error; errmsg already given */ 18679 regname = *strregname; 18680 if (regname == 0 || regname == '@') 18681 regname = '"'; 18682 18683 if (argvars[2].v_type != VAR_UNKNOWN) 18684 { 18685 stropt = get_tv_string_chk(&argvars[2]); 18686 if (stropt == NULL) 18687 return; /* type error */ 18688 for (; *stropt != NUL; ++stropt) 18689 switch (*stropt) 18690 { 18691 case 'a': case 'A': /* append */ 18692 append = TRUE; 18693 break; 18694 case 'v': case 'c': /* character-wise selection */ 18695 yank_type = MCHAR; 18696 break; 18697 case 'V': case 'l': /* line-wise selection */ 18698 yank_type = MLINE; 18699 break; 18700 case 'b': case Ctrl_V: /* block-wise selection */ 18701 yank_type = MBLOCK; 18702 if (VIM_ISDIGIT(stropt[1])) 18703 { 18704 ++stropt; 18705 block_len = getdigits(&stropt) - 1; 18706 --stropt; 18707 } 18708 break; 18709 } 18710 } 18711 18712 if (argvars[1].v_type == VAR_LIST) 18713 { 18714 char_u **lstval; 18715 char_u **allocval; 18716 char_u buf[NUMBUFLEN]; 18717 char_u **curval; 18718 char_u **curallocval; 18719 list_T *ll = argvars[1].vval.v_list; 18720 listitem_T *li; 18721 int len; 18722 18723 /* If the list is NULL handle like an empty list. */ 18724 len = ll == NULL ? 0 : ll->lv_len; 18725 18726 /* First half: use for pointers to result lines; second half: use for 18727 * pointers to allocated copies. */ 18728 lstval = (char_u **)alloc(sizeof(char_u *) * ((len + 1) * 2)); 18729 if (lstval == NULL) 18730 return; 18731 curval = lstval; 18732 allocval = lstval + len + 2; 18733 curallocval = allocval; 18734 18735 for (li = ll == NULL ? NULL : ll->lv_first; li != NULL; 18736 li = li->li_next) 18737 { 18738 strval = get_tv_string_buf_chk(&li->li_tv, buf); 18739 if (strval == NULL) 18740 goto free_lstval; 18741 if (strval == buf) 18742 { 18743 /* Need to make a copy, next get_tv_string_buf_chk() will 18744 * overwrite the string. */ 18745 strval = vim_strsave(buf); 18746 if (strval == NULL) 18747 goto free_lstval; 18748 *curallocval++ = strval; 18749 } 18750 *curval++ = strval; 18751 } 18752 *curval++ = NULL; 18753 18754 write_reg_contents_lst(regname, lstval, -1, 18755 append, yank_type, block_len); 18756 free_lstval: 18757 while (curallocval > allocval) 18758 vim_free(*--curallocval); 18759 vim_free(lstval); 18760 } 18761 else 18762 { 18763 strval = get_tv_string_chk(&argvars[1]); 18764 if (strval == NULL) 18765 return; 18766 write_reg_contents_ex(regname, strval, -1, 18767 append, yank_type, block_len); 18768 } 18769 rettv->vval.v_number = 0; 18770 } 18771 18772 /* 18773 * "settabvar()" function 18774 */ 18775 static void 18776 f_settabvar(typval_T *argvars, typval_T *rettv) 18777 { 18778 #ifdef FEAT_WINDOWS 18779 tabpage_T *save_curtab; 18780 tabpage_T *tp; 18781 #endif 18782 char_u *varname, *tabvarname; 18783 typval_T *varp; 18784 18785 rettv->vval.v_number = 0; 18786 18787 if (check_restricted() || check_secure()) 18788 return; 18789 18790 #ifdef FEAT_WINDOWS 18791 tp = find_tabpage((int)get_tv_number_chk(&argvars[0], NULL)); 18792 #endif 18793 varname = get_tv_string_chk(&argvars[1]); 18794 varp = &argvars[2]; 18795 18796 if (varname != NULL && varp != NULL 18797 #ifdef FEAT_WINDOWS 18798 && tp != NULL 18799 #endif 18800 ) 18801 { 18802 #ifdef FEAT_WINDOWS 18803 save_curtab = curtab; 18804 goto_tabpage_tp(tp, FALSE, FALSE); 18805 #endif 18806 18807 tabvarname = alloc((unsigned)STRLEN(varname) + 3); 18808 if (tabvarname != NULL) 18809 { 18810 STRCPY(tabvarname, "t:"); 18811 STRCPY(tabvarname + 2, varname); 18812 set_var(tabvarname, varp, TRUE); 18813 vim_free(tabvarname); 18814 } 18815 18816 #ifdef FEAT_WINDOWS 18817 /* Restore current tabpage */ 18818 if (valid_tabpage(save_curtab)) 18819 goto_tabpage_tp(save_curtab, FALSE, FALSE); 18820 #endif 18821 } 18822 } 18823 18824 /* 18825 * "settabwinvar()" function 18826 */ 18827 static void 18828 f_settabwinvar(typval_T *argvars, typval_T *rettv) 18829 { 18830 setwinvar(argvars, rettv, 1); 18831 } 18832 18833 /* 18834 * "setwinvar()" function 18835 */ 18836 static void 18837 f_setwinvar(typval_T *argvars, typval_T *rettv) 18838 { 18839 setwinvar(argvars, rettv, 0); 18840 } 18841 18842 /* 18843 * "setwinvar()" and "settabwinvar()" functions 18844 */ 18845 18846 static void 18847 setwinvar(typval_T *argvars, typval_T *rettv UNUSED, int off) 18848 { 18849 win_T *win; 18850 #ifdef FEAT_WINDOWS 18851 win_T *save_curwin; 18852 tabpage_T *save_curtab; 18853 int need_switch_win; 18854 #endif 18855 char_u *varname, *winvarname; 18856 typval_T *varp; 18857 char_u nbuf[NUMBUFLEN]; 18858 tabpage_T *tp = NULL; 18859 18860 if (check_restricted() || check_secure()) 18861 return; 18862 18863 #ifdef FEAT_WINDOWS 18864 if (off == 1) 18865 tp = find_tabpage((int)get_tv_number_chk(&argvars[0], NULL)); 18866 else 18867 tp = curtab; 18868 #endif 18869 win = find_win_by_nr(&argvars[off], tp); 18870 varname = get_tv_string_chk(&argvars[off + 1]); 18871 varp = &argvars[off + 2]; 18872 18873 if (win != NULL && varname != NULL && varp != NULL) 18874 { 18875 #ifdef FEAT_WINDOWS 18876 need_switch_win = !(tp == curtab && win == curwin); 18877 if (!need_switch_win 18878 || switch_win(&save_curwin, &save_curtab, win, tp, TRUE) == OK) 18879 #endif 18880 { 18881 if (*varname == '&') 18882 { 18883 long numval; 18884 char_u *strval; 18885 int error = FALSE; 18886 18887 ++varname; 18888 numval = get_tv_number_chk(varp, &error); 18889 strval = get_tv_string_buf_chk(varp, nbuf); 18890 if (!error && strval != NULL) 18891 set_option_value(varname, numval, strval, OPT_LOCAL); 18892 } 18893 else 18894 { 18895 winvarname = alloc((unsigned)STRLEN(varname) + 3); 18896 if (winvarname != NULL) 18897 { 18898 STRCPY(winvarname, "w:"); 18899 STRCPY(winvarname + 2, varname); 18900 set_var(winvarname, varp, TRUE); 18901 vim_free(winvarname); 18902 } 18903 } 18904 } 18905 #ifdef FEAT_WINDOWS 18906 if (need_switch_win) 18907 restore_win(save_curwin, save_curtab, TRUE); 18908 #endif 18909 } 18910 } 18911 18912 #ifdef FEAT_CRYPT 18913 /* 18914 * "sha256({string})" function 18915 */ 18916 static void 18917 f_sha256(typval_T *argvars, typval_T *rettv) 18918 { 18919 char_u *p; 18920 18921 p = get_tv_string(&argvars[0]); 18922 rettv->vval.v_string = vim_strsave( 18923 sha256_bytes(p, (int)STRLEN(p), NULL, 0)); 18924 rettv->v_type = VAR_STRING; 18925 } 18926 #endif /* FEAT_CRYPT */ 18927 18928 /* 18929 * "shellescape({string})" function 18930 */ 18931 static void 18932 f_shellescape(typval_T *argvars, typval_T *rettv) 18933 { 18934 rettv->vval.v_string = vim_strsave_shellescape( 18935 get_tv_string(&argvars[0]), non_zero_arg(&argvars[1]), TRUE); 18936 rettv->v_type = VAR_STRING; 18937 } 18938 18939 /* 18940 * shiftwidth() function 18941 */ 18942 static void 18943 f_shiftwidth(typval_T *argvars UNUSED, typval_T *rettv) 18944 { 18945 rettv->vval.v_number = get_sw_value(curbuf); 18946 } 18947 18948 /* 18949 * "simplify()" function 18950 */ 18951 static void 18952 f_simplify(typval_T *argvars, typval_T *rettv) 18953 { 18954 char_u *p; 18955 18956 p = get_tv_string(&argvars[0]); 18957 rettv->vval.v_string = vim_strsave(p); 18958 simplify_filename(rettv->vval.v_string); /* simplify in place */ 18959 rettv->v_type = VAR_STRING; 18960 } 18961 18962 #ifdef FEAT_FLOAT 18963 /* 18964 * "sin()" function 18965 */ 18966 static void 18967 f_sin(typval_T *argvars, typval_T *rettv) 18968 { 18969 float_T f = 0.0; 18970 18971 rettv->v_type = VAR_FLOAT; 18972 if (get_float_arg(argvars, &f) == OK) 18973 rettv->vval.v_float = sin(f); 18974 else 18975 rettv->vval.v_float = 0.0; 18976 } 18977 18978 /* 18979 * "sinh()" function 18980 */ 18981 static void 18982 f_sinh(typval_T *argvars, typval_T *rettv) 18983 { 18984 float_T f = 0.0; 18985 18986 rettv->v_type = VAR_FLOAT; 18987 if (get_float_arg(argvars, &f) == OK) 18988 rettv->vval.v_float = sinh(f); 18989 else 18990 rettv->vval.v_float = 0.0; 18991 } 18992 #endif 18993 18994 static int 18995 #ifdef __BORLANDC__ 18996 _RTLENTRYF 18997 #endif 18998 item_compare(const void *s1, const void *s2); 18999 static int 19000 #ifdef __BORLANDC__ 19001 _RTLENTRYF 19002 #endif 19003 item_compare2(const void *s1, const void *s2); 19004 19005 /* struct used in the array that's given to qsort() */ 19006 typedef struct 19007 { 19008 listitem_T *item; 19009 int idx; 19010 } sortItem_T; 19011 19012 /* struct storing information about current sort */ 19013 typedef struct 19014 { 19015 int item_compare_ic; 19016 int item_compare_numeric; 19017 int item_compare_numbers; 19018 #ifdef FEAT_FLOAT 19019 int item_compare_float; 19020 #endif 19021 char_u *item_compare_func; 19022 partial_T *item_compare_partial; 19023 dict_T *item_compare_selfdict; 19024 int item_compare_func_err; 19025 int item_compare_keep_zero; 19026 } sortinfo_T; 19027 static sortinfo_T *sortinfo = NULL; 19028 static void do_sort_uniq(typval_T *argvars, typval_T *rettv, int sort); 19029 #define ITEM_COMPARE_FAIL 999 19030 19031 /* 19032 * Compare functions for f_sort() and f_uniq() below. 19033 */ 19034 static int 19035 #ifdef __BORLANDC__ 19036 _RTLENTRYF 19037 #endif 19038 item_compare(const void *s1, const void *s2) 19039 { 19040 sortItem_T *si1, *si2; 19041 typval_T *tv1, *tv2; 19042 char_u *p1, *p2; 19043 char_u *tofree1 = NULL, *tofree2 = NULL; 19044 int res; 19045 char_u numbuf1[NUMBUFLEN]; 19046 char_u numbuf2[NUMBUFLEN]; 19047 19048 si1 = (sortItem_T *)s1; 19049 si2 = (sortItem_T *)s2; 19050 tv1 = &si1->item->li_tv; 19051 tv2 = &si2->item->li_tv; 19052 19053 if (sortinfo->item_compare_numbers) 19054 { 19055 long v1 = get_tv_number(tv1); 19056 long v2 = get_tv_number(tv2); 19057 19058 return v1 == v2 ? 0 : v1 > v2 ? 1 : -1; 19059 } 19060 19061 #ifdef FEAT_FLOAT 19062 if (sortinfo->item_compare_float) 19063 { 19064 float_T v1 = get_tv_float(tv1); 19065 float_T v2 = get_tv_float(tv2); 19066 19067 return v1 == v2 ? 0 : v1 > v2 ? 1 : -1; 19068 } 19069 #endif 19070 19071 /* tv2string() puts quotes around a string and allocates memory. Don't do 19072 * that for string variables. Use a single quote when comparing with a 19073 * non-string to do what the docs promise. */ 19074 if (tv1->v_type == VAR_STRING) 19075 { 19076 if (tv2->v_type != VAR_STRING || sortinfo->item_compare_numeric) 19077 p1 = (char_u *)"'"; 19078 else 19079 p1 = tv1->vval.v_string; 19080 } 19081 else 19082 p1 = tv2string(tv1, &tofree1, numbuf1, 0); 19083 if (tv2->v_type == VAR_STRING) 19084 { 19085 if (tv1->v_type != VAR_STRING || sortinfo->item_compare_numeric) 19086 p2 = (char_u *)"'"; 19087 else 19088 p2 = tv2->vval.v_string; 19089 } 19090 else 19091 p2 = tv2string(tv2, &tofree2, numbuf2, 0); 19092 if (p1 == NULL) 19093 p1 = (char_u *)""; 19094 if (p2 == NULL) 19095 p2 = (char_u *)""; 19096 if (!sortinfo->item_compare_numeric) 19097 { 19098 if (sortinfo->item_compare_ic) 19099 res = STRICMP(p1, p2); 19100 else 19101 res = STRCMP(p1, p2); 19102 } 19103 else 19104 { 19105 double n1, n2; 19106 n1 = strtod((char *)p1, (char **)&p1); 19107 n2 = strtod((char *)p2, (char **)&p2); 19108 res = n1 == n2 ? 0 : n1 > n2 ? 1 : -1; 19109 } 19110 19111 /* When the result would be zero, compare the item indexes. Makes the 19112 * sort stable. */ 19113 if (res == 0 && !sortinfo->item_compare_keep_zero) 19114 res = si1->idx > si2->idx ? 1 : -1; 19115 19116 vim_free(tofree1); 19117 vim_free(tofree2); 19118 return res; 19119 } 19120 19121 static int 19122 #ifdef __BORLANDC__ 19123 _RTLENTRYF 19124 #endif 19125 item_compare2(const void *s1, const void *s2) 19126 { 19127 sortItem_T *si1, *si2; 19128 int res; 19129 typval_T rettv; 19130 typval_T argv[3]; 19131 int dummy; 19132 char_u *func_name; 19133 partial_T *partial = sortinfo->item_compare_partial; 19134 19135 /* shortcut after failure in previous call; compare all items equal */ 19136 if (sortinfo->item_compare_func_err) 19137 return 0; 19138 19139 si1 = (sortItem_T *)s1; 19140 si2 = (sortItem_T *)s2; 19141 19142 if (partial == NULL) 19143 func_name = sortinfo->item_compare_func; 19144 else 19145 func_name = partial->pt_name; 19146 19147 /* Copy the values. This is needed to be able to set v_lock to VAR_FIXED 19148 * in the copy without changing the original list items. */ 19149 copy_tv(&si1->item->li_tv, &argv[0]); 19150 copy_tv(&si2->item->li_tv, &argv[1]); 19151 19152 rettv.v_type = VAR_UNKNOWN; /* clear_tv() uses this */ 19153 res = call_func(func_name, (int)STRLEN(func_name), 19154 &rettv, 2, argv, 0L, 0L, &dummy, TRUE, 19155 partial, sortinfo->item_compare_selfdict); 19156 clear_tv(&argv[0]); 19157 clear_tv(&argv[1]); 19158 19159 if (res == FAIL) 19160 res = ITEM_COMPARE_FAIL; 19161 else 19162 res = get_tv_number_chk(&rettv, &sortinfo->item_compare_func_err); 19163 if (sortinfo->item_compare_func_err) 19164 res = ITEM_COMPARE_FAIL; /* return value has wrong type */ 19165 clear_tv(&rettv); 19166 19167 /* When the result would be zero, compare the pointers themselves. Makes 19168 * the sort stable. */ 19169 if (res == 0 && !sortinfo->item_compare_keep_zero) 19170 res = si1->idx > si2->idx ? 1 : -1; 19171 19172 return res; 19173 } 19174 19175 /* 19176 * "sort({list})" function 19177 */ 19178 static void 19179 do_sort_uniq(typval_T *argvars, typval_T *rettv, int sort) 19180 { 19181 list_T *l; 19182 listitem_T *li; 19183 sortItem_T *ptrs; 19184 sortinfo_T *old_sortinfo; 19185 sortinfo_T info; 19186 long len; 19187 long i; 19188 19189 /* Pointer to current info struct used in compare function. Save and 19190 * restore the current one for nested calls. */ 19191 old_sortinfo = sortinfo; 19192 sortinfo = &info; 19193 19194 if (argvars[0].v_type != VAR_LIST) 19195 EMSG2(_(e_listarg), sort ? "sort()" : "uniq()"); 19196 else 19197 { 19198 l = argvars[0].vval.v_list; 19199 if (l == NULL || tv_check_lock(l->lv_lock, 19200 (char_u *)(sort ? N_("sort() argument") : N_("uniq() argument")), 19201 TRUE)) 19202 goto theend; 19203 rettv->vval.v_list = l; 19204 rettv->v_type = VAR_LIST; 19205 ++l->lv_refcount; 19206 19207 len = list_len(l); 19208 if (len <= 1) 19209 goto theend; /* short list sorts pretty quickly */ 19210 19211 info.item_compare_ic = FALSE; 19212 info.item_compare_numeric = FALSE; 19213 info.item_compare_numbers = FALSE; 19214 #ifdef FEAT_FLOAT 19215 info.item_compare_float = FALSE; 19216 #endif 19217 info.item_compare_func = NULL; 19218 info.item_compare_partial = NULL; 19219 info.item_compare_selfdict = NULL; 19220 if (argvars[1].v_type != VAR_UNKNOWN) 19221 { 19222 /* optional second argument: {func} */ 19223 if (argvars[1].v_type == VAR_FUNC) 19224 info.item_compare_func = argvars[1].vval.v_string; 19225 else if (argvars[1].v_type == VAR_PARTIAL) 19226 info.item_compare_partial = argvars[1].vval.v_partial; 19227 else 19228 { 19229 int error = FALSE; 19230 19231 i = get_tv_number_chk(&argvars[1], &error); 19232 if (error) 19233 goto theend; /* type error; errmsg already given */ 19234 if (i == 1) 19235 info.item_compare_ic = TRUE; 19236 else if (argvars[1].v_type != VAR_NUMBER) 19237 info.item_compare_func = get_tv_string(&argvars[1]); 19238 else if (i != 0) 19239 { 19240 EMSG(_(e_invarg)); 19241 goto theend; 19242 } 19243 if (info.item_compare_func != NULL) 19244 { 19245 if (*info.item_compare_func == NUL) 19246 { 19247 /* empty string means default sort */ 19248 info.item_compare_func = NULL; 19249 } 19250 else if (STRCMP(info.item_compare_func, "n") == 0) 19251 { 19252 info.item_compare_func = NULL; 19253 info.item_compare_numeric = TRUE; 19254 } 19255 else if (STRCMP(info.item_compare_func, "N") == 0) 19256 { 19257 info.item_compare_func = NULL; 19258 info.item_compare_numbers = TRUE; 19259 } 19260 #ifdef FEAT_FLOAT 19261 else if (STRCMP(info.item_compare_func, "f") == 0) 19262 { 19263 info.item_compare_func = NULL; 19264 info.item_compare_float = TRUE; 19265 } 19266 #endif 19267 else if (STRCMP(info.item_compare_func, "i") == 0) 19268 { 19269 info.item_compare_func = NULL; 19270 info.item_compare_ic = TRUE; 19271 } 19272 } 19273 } 19274 19275 if (argvars[2].v_type != VAR_UNKNOWN) 19276 { 19277 /* optional third argument: {dict} */ 19278 if (argvars[2].v_type != VAR_DICT) 19279 { 19280 EMSG(_(e_dictreq)); 19281 goto theend; 19282 } 19283 info.item_compare_selfdict = argvars[2].vval.v_dict; 19284 } 19285 } 19286 19287 /* Make an array with each entry pointing to an item in the List. */ 19288 ptrs = (sortItem_T *)alloc((int)(len * sizeof(sortItem_T))); 19289 if (ptrs == NULL) 19290 goto theend; 19291 19292 i = 0; 19293 if (sort) 19294 { 19295 /* sort(): ptrs will be the list to sort */ 19296 for (li = l->lv_first; li != NULL; li = li->li_next) 19297 { 19298 ptrs[i].item = li; 19299 ptrs[i].idx = i; 19300 ++i; 19301 } 19302 19303 info.item_compare_func_err = FALSE; 19304 info.item_compare_keep_zero = FALSE; 19305 /* test the compare function */ 19306 if ((info.item_compare_func != NULL 19307 || info.item_compare_partial != NULL) 19308 && item_compare2((void *)&ptrs[0], (void *)&ptrs[1]) 19309 == ITEM_COMPARE_FAIL) 19310 EMSG(_("E702: Sort compare function failed")); 19311 else 19312 { 19313 /* Sort the array with item pointers. */ 19314 qsort((void *)ptrs, (size_t)len, sizeof(sortItem_T), 19315 info.item_compare_func == NULL 19316 && info.item_compare_partial == NULL 19317 ? item_compare : item_compare2); 19318 19319 if (!info.item_compare_func_err) 19320 { 19321 /* Clear the List and append the items in sorted order. */ 19322 l->lv_first = l->lv_last = l->lv_idx_item = NULL; 19323 l->lv_len = 0; 19324 for (i = 0; i < len; ++i) 19325 list_append(l, ptrs[i].item); 19326 } 19327 } 19328 } 19329 else 19330 { 19331 int (*item_compare_func_ptr)(const void *, const void *); 19332 19333 /* f_uniq(): ptrs will be a stack of items to remove */ 19334 info.item_compare_func_err = FALSE; 19335 info.item_compare_keep_zero = TRUE; 19336 item_compare_func_ptr = info.item_compare_func != NULL 19337 || info.item_compare_partial != NULL 19338 ? item_compare2 : item_compare; 19339 19340 for (li = l->lv_first; li != NULL && li->li_next != NULL; 19341 li = li->li_next) 19342 { 19343 if (item_compare_func_ptr((void *)&li, (void *)&li->li_next) 19344 == 0) 19345 ptrs[i++].item = li; 19346 if (info.item_compare_func_err) 19347 { 19348 EMSG(_("E882: Uniq compare function failed")); 19349 break; 19350 } 19351 } 19352 19353 if (!info.item_compare_func_err) 19354 { 19355 while (--i >= 0) 19356 { 19357 li = ptrs[i].item->li_next; 19358 ptrs[i].item->li_next = li->li_next; 19359 if (li->li_next != NULL) 19360 li->li_next->li_prev = ptrs[i].item; 19361 else 19362 l->lv_last = ptrs[i].item; 19363 list_fix_watch(l, li); 19364 listitem_free(li); 19365 l->lv_len--; 19366 } 19367 } 19368 } 19369 19370 vim_free(ptrs); 19371 } 19372 theend: 19373 sortinfo = old_sortinfo; 19374 } 19375 19376 /* 19377 * "sort({list})" function 19378 */ 19379 static void 19380 f_sort(typval_T *argvars, typval_T *rettv) 19381 { 19382 do_sort_uniq(argvars, rettv, TRUE); 19383 } 19384 19385 /* 19386 * "uniq({list})" function 19387 */ 19388 static void 19389 f_uniq(typval_T *argvars, typval_T *rettv) 19390 { 19391 do_sort_uniq(argvars, rettv, FALSE); 19392 } 19393 19394 /* 19395 * "soundfold({word})" function 19396 */ 19397 static void 19398 f_soundfold(typval_T *argvars, typval_T *rettv) 19399 { 19400 char_u *s; 19401 19402 rettv->v_type = VAR_STRING; 19403 s = get_tv_string(&argvars[0]); 19404 #ifdef FEAT_SPELL 19405 rettv->vval.v_string = eval_soundfold(s); 19406 #else 19407 rettv->vval.v_string = vim_strsave(s); 19408 #endif 19409 } 19410 19411 /* 19412 * "spellbadword()" function 19413 */ 19414 static void 19415 f_spellbadword(typval_T *argvars UNUSED, typval_T *rettv) 19416 { 19417 char_u *word = (char_u *)""; 19418 hlf_T attr = HLF_COUNT; 19419 int len = 0; 19420 19421 if (rettv_list_alloc(rettv) == FAIL) 19422 return; 19423 19424 #ifdef FEAT_SPELL 19425 if (argvars[0].v_type == VAR_UNKNOWN) 19426 { 19427 /* Find the start and length of the badly spelled word. */ 19428 len = spell_move_to(curwin, FORWARD, TRUE, TRUE, &attr); 19429 if (len != 0) 19430 word = ml_get_cursor(); 19431 } 19432 else if (curwin->w_p_spell && *curbuf->b_s.b_p_spl != NUL) 19433 { 19434 char_u *str = get_tv_string_chk(&argvars[0]); 19435 int capcol = -1; 19436 19437 if (str != NULL) 19438 { 19439 /* Check the argument for spelling. */ 19440 while (*str != NUL) 19441 { 19442 len = spell_check(curwin, str, &attr, &capcol, FALSE); 19443 if (attr != HLF_COUNT) 19444 { 19445 word = str; 19446 break; 19447 } 19448 str += len; 19449 } 19450 } 19451 } 19452 #endif 19453 19454 list_append_string(rettv->vval.v_list, word, len); 19455 list_append_string(rettv->vval.v_list, (char_u *)( 19456 attr == HLF_SPB ? "bad" : 19457 attr == HLF_SPR ? "rare" : 19458 attr == HLF_SPL ? "local" : 19459 attr == HLF_SPC ? "caps" : 19460 ""), -1); 19461 } 19462 19463 /* 19464 * "spellsuggest()" function 19465 */ 19466 static void 19467 f_spellsuggest(typval_T *argvars UNUSED, typval_T *rettv) 19468 { 19469 #ifdef FEAT_SPELL 19470 char_u *str; 19471 int typeerr = FALSE; 19472 int maxcount; 19473 garray_T ga; 19474 int i; 19475 listitem_T *li; 19476 int need_capital = FALSE; 19477 #endif 19478 19479 if (rettv_list_alloc(rettv) == FAIL) 19480 return; 19481 19482 #ifdef FEAT_SPELL 19483 if (curwin->w_p_spell && *curwin->w_s->b_p_spl != NUL) 19484 { 19485 str = get_tv_string(&argvars[0]); 19486 if (argvars[1].v_type != VAR_UNKNOWN) 19487 { 19488 maxcount = get_tv_number_chk(&argvars[1], &typeerr); 19489 if (maxcount <= 0) 19490 return; 19491 if (argvars[2].v_type != VAR_UNKNOWN) 19492 { 19493 need_capital = get_tv_number_chk(&argvars[2], &typeerr); 19494 if (typeerr) 19495 return; 19496 } 19497 } 19498 else 19499 maxcount = 25; 19500 19501 spell_suggest_list(&ga, str, maxcount, need_capital, FALSE); 19502 19503 for (i = 0; i < ga.ga_len; ++i) 19504 { 19505 str = ((char_u **)ga.ga_data)[i]; 19506 19507 li = listitem_alloc(); 19508 if (li == NULL) 19509 vim_free(str); 19510 else 19511 { 19512 li->li_tv.v_type = VAR_STRING; 19513 li->li_tv.v_lock = 0; 19514 li->li_tv.vval.v_string = str; 19515 list_append(rettv->vval.v_list, li); 19516 } 19517 } 19518 ga_clear(&ga); 19519 } 19520 #endif 19521 } 19522 19523 static void 19524 f_split(typval_T *argvars, typval_T *rettv) 19525 { 19526 char_u *str; 19527 char_u *end; 19528 char_u *pat = NULL; 19529 regmatch_T regmatch; 19530 char_u patbuf[NUMBUFLEN]; 19531 char_u *save_cpo; 19532 int match; 19533 colnr_T col = 0; 19534 int keepempty = FALSE; 19535 int typeerr = FALSE; 19536 19537 /* Make 'cpoptions' empty, the 'l' flag should not be used here. */ 19538 save_cpo = p_cpo; 19539 p_cpo = (char_u *)""; 19540 19541 str = get_tv_string(&argvars[0]); 19542 if (argvars[1].v_type != VAR_UNKNOWN) 19543 { 19544 pat = get_tv_string_buf_chk(&argvars[1], patbuf); 19545 if (pat == NULL) 19546 typeerr = TRUE; 19547 if (argvars[2].v_type != VAR_UNKNOWN) 19548 keepempty = get_tv_number_chk(&argvars[2], &typeerr); 19549 } 19550 if (pat == NULL || *pat == NUL) 19551 pat = (char_u *)"[\\x01- ]\\+"; 19552 19553 if (rettv_list_alloc(rettv) == FAIL) 19554 return; 19555 if (typeerr) 19556 return; 19557 19558 regmatch.regprog = vim_regcomp(pat, RE_MAGIC + RE_STRING); 19559 if (regmatch.regprog != NULL) 19560 { 19561 regmatch.rm_ic = FALSE; 19562 while (*str != NUL || keepempty) 19563 { 19564 if (*str == NUL) 19565 match = FALSE; /* empty item at the end */ 19566 else 19567 match = vim_regexec_nl(®match, str, col); 19568 if (match) 19569 end = regmatch.startp[0]; 19570 else 19571 end = str + STRLEN(str); 19572 if (keepempty || end > str || (rettv->vval.v_list->lv_len > 0 19573 && *str != NUL && match && end < regmatch.endp[0])) 19574 { 19575 if (list_append_string(rettv->vval.v_list, str, 19576 (int)(end - str)) == FAIL) 19577 break; 19578 } 19579 if (!match) 19580 break; 19581 /* Advance to just after the match. */ 19582 if (regmatch.endp[0] > str) 19583 col = 0; 19584 else 19585 { 19586 /* Don't get stuck at the same match. */ 19587 #ifdef FEAT_MBYTE 19588 col = (*mb_ptr2len)(regmatch.endp[0]); 19589 #else 19590 col = 1; 19591 #endif 19592 } 19593 str = regmatch.endp[0]; 19594 } 19595 19596 vim_regfree(regmatch.regprog); 19597 } 19598 19599 p_cpo = save_cpo; 19600 } 19601 19602 #ifdef FEAT_FLOAT 19603 /* 19604 * "sqrt()" function 19605 */ 19606 static void 19607 f_sqrt(typval_T *argvars, typval_T *rettv) 19608 { 19609 float_T f = 0.0; 19610 19611 rettv->v_type = VAR_FLOAT; 19612 if (get_float_arg(argvars, &f) == OK) 19613 rettv->vval.v_float = sqrt(f); 19614 else 19615 rettv->vval.v_float = 0.0; 19616 } 19617 19618 /* 19619 * "str2float()" function 19620 */ 19621 static void 19622 f_str2float(typval_T *argvars, typval_T *rettv) 19623 { 19624 char_u *p = skipwhite(get_tv_string(&argvars[0])); 19625 19626 if (*p == '+') 19627 p = skipwhite(p + 1); 19628 (void)string2float(p, &rettv->vval.v_float); 19629 rettv->v_type = VAR_FLOAT; 19630 } 19631 #endif 19632 19633 /* 19634 * "str2nr()" function 19635 */ 19636 static void 19637 f_str2nr(typval_T *argvars, typval_T *rettv) 19638 { 19639 int base = 10; 19640 char_u *p; 19641 long n; 19642 int what; 19643 19644 if (argvars[1].v_type != VAR_UNKNOWN) 19645 { 19646 base = get_tv_number(&argvars[1]); 19647 if (base != 2 && base != 8 && base != 10 && base != 16) 19648 { 19649 EMSG(_(e_invarg)); 19650 return; 19651 } 19652 } 19653 19654 p = skipwhite(get_tv_string(&argvars[0])); 19655 if (*p == '+') 19656 p = skipwhite(p + 1); 19657 switch (base) 19658 { 19659 case 2: what = STR2NR_BIN + STR2NR_FORCE; break; 19660 case 8: what = STR2NR_OCT + STR2NR_FORCE; break; 19661 case 16: what = STR2NR_HEX + STR2NR_FORCE; break; 19662 default: what = 0; 19663 } 19664 vim_str2nr(p, NULL, NULL, what, &n, NULL, 0); 19665 rettv->vval.v_number = n; 19666 } 19667 19668 #ifdef HAVE_STRFTIME 19669 /* 19670 * "strftime({format}[, {time}])" function 19671 */ 19672 static void 19673 f_strftime(typval_T *argvars, typval_T *rettv) 19674 { 19675 char_u result_buf[256]; 19676 struct tm *curtime; 19677 time_t seconds; 19678 char_u *p; 19679 19680 rettv->v_type = VAR_STRING; 19681 19682 p = get_tv_string(&argvars[0]); 19683 if (argvars[1].v_type == VAR_UNKNOWN) 19684 seconds = time(NULL); 19685 else 19686 seconds = (time_t)get_tv_number(&argvars[1]); 19687 curtime = localtime(&seconds); 19688 /* MSVC returns NULL for an invalid value of seconds. */ 19689 if (curtime == NULL) 19690 rettv->vval.v_string = vim_strsave((char_u *)_("(Invalid)")); 19691 else 19692 { 19693 # ifdef FEAT_MBYTE 19694 vimconv_T conv; 19695 char_u *enc; 19696 19697 conv.vc_type = CONV_NONE; 19698 enc = enc_locale(); 19699 convert_setup(&conv, p_enc, enc); 19700 if (conv.vc_type != CONV_NONE) 19701 p = string_convert(&conv, p, NULL); 19702 # endif 19703 if (p != NULL) 19704 (void)strftime((char *)result_buf, sizeof(result_buf), 19705 (char *)p, curtime); 19706 else 19707 result_buf[0] = NUL; 19708 19709 # ifdef FEAT_MBYTE 19710 if (conv.vc_type != CONV_NONE) 19711 vim_free(p); 19712 convert_setup(&conv, enc, p_enc); 19713 if (conv.vc_type != CONV_NONE) 19714 rettv->vval.v_string = string_convert(&conv, result_buf, NULL); 19715 else 19716 # endif 19717 rettv->vval.v_string = vim_strsave(result_buf); 19718 19719 # ifdef FEAT_MBYTE 19720 /* Release conversion descriptors */ 19721 convert_setup(&conv, NULL, NULL); 19722 vim_free(enc); 19723 # endif 19724 } 19725 } 19726 #endif 19727 19728 /* 19729 * "strgetchar()" function 19730 */ 19731 static void 19732 f_strgetchar(typval_T *argvars, typval_T *rettv) 19733 { 19734 char_u *str; 19735 int len; 19736 int error = FALSE; 19737 int charidx; 19738 19739 rettv->vval.v_number = -1; 19740 str = get_tv_string_chk(&argvars[0]); 19741 if (str == NULL) 19742 return; 19743 len = (int)STRLEN(str); 19744 charidx = get_tv_number_chk(&argvars[1], &error); 19745 if (error) 19746 return; 19747 #ifdef FEAT_MBYTE 19748 { 19749 int byteidx = 0; 19750 19751 while (charidx >= 0 && byteidx < len) 19752 { 19753 if (charidx == 0) 19754 { 19755 rettv->vval.v_number = mb_ptr2char(str + byteidx); 19756 break; 19757 } 19758 --charidx; 19759 byteidx += mb_cptr2len(str + byteidx); 19760 } 19761 } 19762 #else 19763 if (charidx < len) 19764 rettv->vval.v_number = str[charidx]; 19765 #endif 19766 } 19767 19768 /* 19769 * "stridx()" function 19770 */ 19771 static void 19772 f_stridx(typval_T *argvars, typval_T *rettv) 19773 { 19774 char_u buf[NUMBUFLEN]; 19775 char_u *needle; 19776 char_u *haystack; 19777 char_u *save_haystack; 19778 char_u *pos; 19779 int start_idx; 19780 19781 needle = get_tv_string_chk(&argvars[1]); 19782 save_haystack = haystack = get_tv_string_buf_chk(&argvars[0], buf); 19783 rettv->vval.v_number = -1; 19784 if (needle == NULL || haystack == NULL) 19785 return; /* type error; errmsg already given */ 19786 19787 if (argvars[2].v_type != VAR_UNKNOWN) 19788 { 19789 int error = FALSE; 19790 19791 start_idx = get_tv_number_chk(&argvars[2], &error); 19792 if (error || start_idx >= (int)STRLEN(haystack)) 19793 return; 19794 if (start_idx >= 0) 19795 haystack += start_idx; 19796 } 19797 19798 pos = (char_u *)strstr((char *)haystack, (char *)needle); 19799 if (pos != NULL) 19800 rettv->vval.v_number = (varnumber_T)(pos - save_haystack); 19801 } 19802 19803 /* 19804 * "string()" function 19805 */ 19806 static void 19807 f_string(typval_T *argvars, typval_T *rettv) 19808 { 19809 char_u *tofree; 19810 char_u numbuf[NUMBUFLEN]; 19811 19812 rettv->v_type = VAR_STRING; 19813 rettv->vval.v_string = tv2string(&argvars[0], &tofree, numbuf, 19814 get_copyID()); 19815 /* Make a copy if we have a value but it's not in allocated memory. */ 19816 if (rettv->vval.v_string != NULL && tofree == NULL) 19817 rettv->vval.v_string = vim_strsave(rettv->vval.v_string); 19818 } 19819 19820 /* 19821 * "strlen()" function 19822 */ 19823 static void 19824 f_strlen(typval_T *argvars, typval_T *rettv) 19825 { 19826 rettv->vval.v_number = (varnumber_T)(STRLEN( 19827 get_tv_string(&argvars[0]))); 19828 } 19829 19830 /* 19831 * "strchars()" function 19832 */ 19833 static void 19834 f_strchars(typval_T *argvars, typval_T *rettv) 19835 { 19836 char_u *s = get_tv_string(&argvars[0]); 19837 int skipcc = 0; 19838 #ifdef FEAT_MBYTE 19839 varnumber_T len = 0; 19840 int (*func_mb_ptr2char_adv)(char_u **pp); 19841 #endif 19842 19843 if (argvars[1].v_type != VAR_UNKNOWN) 19844 skipcc = get_tv_number_chk(&argvars[1], NULL); 19845 if (skipcc < 0 || skipcc > 1) 19846 EMSG(_(e_invarg)); 19847 else 19848 { 19849 #ifdef FEAT_MBYTE 19850 func_mb_ptr2char_adv = skipcc ? mb_ptr2char_adv : mb_cptr2char_adv; 19851 while (*s != NUL) 19852 { 19853 func_mb_ptr2char_adv(&s); 19854 ++len; 19855 } 19856 rettv->vval.v_number = len; 19857 #else 19858 rettv->vval.v_number = (varnumber_T)(STRLEN(s)); 19859 #endif 19860 } 19861 } 19862 19863 /* 19864 * "strdisplaywidth()" function 19865 */ 19866 static void 19867 f_strdisplaywidth(typval_T *argvars, typval_T *rettv) 19868 { 19869 char_u *s = get_tv_string(&argvars[0]); 19870 int col = 0; 19871 19872 if (argvars[1].v_type != VAR_UNKNOWN) 19873 col = get_tv_number(&argvars[1]); 19874 19875 rettv->vval.v_number = (varnumber_T)(linetabsize_col(col, s) - col); 19876 } 19877 19878 /* 19879 * "strwidth()" function 19880 */ 19881 static void 19882 f_strwidth(typval_T *argvars, typval_T *rettv) 19883 { 19884 char_u *s = get_tv_string(&argvars[0]); 19885 19886 rettv->vval.v_number = (varnumber_T)( 19887 #ifdef FEAT_MBYTE 19888 mb_string2cells(s, -1) 19889 #else 19890 STRLEN(s) 19891 #endif 19892 ); 19893 } 19894 19895 /* 19896 * "strcharpart()" function 19897 */ 19898 static void 19899 f_strcharpart(typval_T *argvars, typval_T *rettv) 19900 { 19901 #ifdef FEAT_MBYTE 19902 char_u *p; 19903 int nchar; 19904 int nbyte = 0; 19905 int charlen; 19906 int len = 0; 19907 int slen; 19908 int error = FALSE; 19909 19910 p = get_tv_string(&argvars[0]); 19911 slen = (int)STRLEN(p); 19912 19913 nchar = get_tv_number_chk(&argvars[1], &error); 19914 if (!error) 19915 { 19916 if (nchar > 0) 19917 while (nchar > 0 && nbyte < slen) 19918 { 19919 nbyte += mb_cptr2len(p + nbyte); 19920 --nchar; 19921 } 19922 else 19923 nbyte = nchar; 19924 if (argvars[2].v_type != VAR_UNKNOWN) 19925 { 19926 charlen = get_tv_number(&argvars[2]); 19927 while (charlen > 0 && nbyte + len < slen) 19928 { 19929 int off = nbyte + len; 19930 19931 if (off < 0) 19932 len += 1; 19933 else 19934 len += mb_cptr2len(p + off); 19935 --charlen; 19936 } 19937 } 19938 else 19939 len = slen - nbyte; /* default: all bytes that are available. */ 19940 } 19941 19942 /* 19943 * Only return the overlap between the specified part and the actual 19944 * string. 19945 */ 19946 if (nbyte < 0) 19947 { 19948 len += nbyte; 19949 nbyte = 0; 19950 } 19951 else if (nbyte > slen) 19952 nbyte = slen; 19953 if (len < 0) 19954 len = 0; 19955 else if (nbyte + len > slen) 19956 len = slen - nbyte; 19957 19958 rettv->v_type = VAR_STRING; 19959 rettv->vval.v_string = vim_strnsave(p + nbyte, len); 19960 #else 19961 f_strpart(argvars, rettv); 19962 #endif 19963 } 19964 19965 /* 19966 * "strpart()" function 19967 */ 19968 static void 19969 f_strpart(typval_T *argvars, typval_T *rettv) 19970 { 19971 char_u *p; 19972 int n; 19973 int len; 19974 int slen; 19975 int error = FALSE; 19976 19977 p = get_tv_string(&argvars[0]); 19978 slen = (int)STRLEN(p); 19979 19980 n = get_tv_number_chk(&argvars[1], &error); 19981 if (error) 19982 len = 0; 19983 else if (argvars[2].v_type != VAR_UNKNOWN) 19984 len = get_tv_number(&argvars[2]); 19985 else 19986 len = slen - n; /* default len: all bytes that are available. */ 19987 19988 /* 19989 * Only return the overlap between the specified part and the actual 19990 * string. 19991 */ 19992 if (n < 0) 19993 { 19994 len += n; 19995 n = 0; 19996 } 19997 else if (n > slen) 19998 n = slen; 19999 if (len < 0) 20000 len = 0; 20001 else if (n + len > slen) 20002 len = slen - n; 20003 20004 rettv->v_type = VAR_STRING; 20005 rettv->vval.v_string = vim_strnsave(p + n, len); 20006 } 20007 20008 /* 20009 * "strridx()" function 20010 */ 20011 static void 20012 f_strridx(typval_T *argvars, typval_T *rettv) 20013 { 20014 char_u buf[NUMBUFLEN]; 20015 char_u *needle; 20016 char_u *haystack; 20017 char_u *rest; 20018 char_u *lastmatch = NULL; 20019 int haystack_len, end_idx; 20020 20021 needle = get_tv_string_chk(&argvars[1]); 20022 haystack = get_tv_string_buf_chk(&argvars[0], buf); 20023 20024 rettv->vval.v_number = -1; 20025 if (needle == NULL || haystack == NULL) 20026 return; /* type error; errmsg already given */ 20027 20028 haystack_len = (int)STRLEN(haystack); 20029 if (argvars[2].v_type != VAR_UNKNOWN) 20030 { 20031 /* Third argument: upper limit for index */ 20032 end_idx = get_tv_number_chk(&argvars[2], NULL); 20033 if (end_idx < 0) 20034 return; /* can never find a match */ 20035 } 20036 else 20037 end_idx = haystack_len; 20038 20039 if (*needle == NUL) 20040 { 20041 /* Empty string matches past the end. */ 20042 lastmatch = haystack + end_idx; 20043 } 20044 else 20045 { 20046 for (rest = haystack; *rest != '\0'; ++rest) 20047 { 20048 rest = (char_u *)strstr((char *)rest, (char *)needle); 20049 if (rest == NULL || rest > haystack + end_idx) 20050 break; 20051 lastmatch = rest; 20052 } 20053 } 20054 20055 if (lastmatch == NULL) 20056 rettv->vval.v_number = -1; 20057 else 20058 rettv->vval.v_number = (varnumber_T)(lastmatch - haystack); 20059 } 20060 20061 /* 20062 * "strtrans()" function 20063 */ 20064 static void 20065 f_strtrans(typval_T *argvars, typval_T *rettv) 20066 { 20067 rettv->v_type = VAR_STRING; 20068 rettv->vval.v_string = transstr(get_tv_string(&argvars[0])); 20069 } 20070 20071 /* 20072 * "submatch()" function 20073 */ 20074 static void 20075 f_submatch(typval_T *argvars, typval_T *rettv) 20076 { 20077 int error = FALSE; 20078 int no; 20079 int retList = 0; 20080 20081 no = (int)get_tv_number_chk(&argvars[0], &error); 20082 if (error) 20083 return; 20084 error = FALSE; 20085 if (argvars[1].v_type != VAR_UNKNOWN) 20086 retList = get_tv_number_chk(&argvars[1], &error); 20087 if (error) 20088 return; 20089 20090 if (retList == 0) 20091 { 20092 rettv->v_type = VAR_STRING; 20093 rettv->vval.v_string = reg_submatch(no); 20094 } 20095 else 20096 { 20097 rettv->v_type = VAR_LIST; 20098 rettv->vval.v_list = reg_submatch_list(no); 20099 } 20100 } 20101 20102 /* 20103 * "substitute()" function 20104 */ 20105 static void 20106 f_substitute(typval_T *argvars, typval_T *rettv) 20107 { 20108 char_u patbuf[NUMBUFLEN]; 20109 char_u subbuf[NUMBUFLEN]; 20110 char_u flagsbuf[NUMBUFLEN]; 20111 20112 char_u *str = get_tv_string_chk(&argvars[0]); 20113 char_u *pat = get_tv_string_buf_chk(&argvars[1], patbuf); 20114 char_u *sub = get_tv_string_buf_chk(&argvars[2], subbuf); 20115 char_u *flg = get_tv_string_buf_chk(&argvars[3], flagsbuf); 20116 20117 rettv->v_type = VAR_STRING; 20118 if (str == NULL || pat == NULL || sub == NULL || flg == NULL) 20119 rettv->vval.v_string = NULL; 20120 else 20121 rettv->vval.v_string = do_string_sub(str, pat, sub, flg); 20122 } 20123 20124 /* 20125 * "synID(lnum, col, trans)" function 20126 */ 20127 static void 20128 f_synID(typval_T *argvars UNUSED, typval_T *rettv) 20129 { 20130 int id = 0; 20131 #ifdef FEAT_SYN_HL 20132 long lnum; 20133 long col; 20134 int trans; 20135 int transerr = FALSE; 20136 20137 lnum = get_tv_lnum(argvars); /* -1 on type error */ 20138 col = get_tv_number(&argvars[1]) - 1; /* -1 on type error */ 20139 trans = get_tv_number_chk(&argvars[2], &transerr); 20140 20141 if (!transerr && lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count 20142 && col >= 0 && col < (long)STRLEN(ml_get(lnum))) 20143 id = syn_get_id(curwin, lnum, (colnr_T)col, trans, NULL, FALSE); 20144 #endif 20145 20146 rettv->vval.v_number = id; 20147 } 20148 20149 /* 20150 * "synIDattr(id, what [, mode])" function 20151 */ 20152 static void 20153 f_synIDattr(typval_T *argvars UNUSED, typval_T *rettv) 20154 { 20155 char_u *p = NULL; 20156 #ifdef FEAT_SYN_HL 20157 int id; 20158 char_u *what; 20159 char_u *mode; 20160 char_u modebuf[NUMBUFLEN]; 20161 int modec; 20162 20163 id = get_tv_number(&argvars[0]); 20164 what = get_tv_string(&argvars[1]); 20165 if (argvars[2].v_type != VAR_UNKNOWN) 20166 { 20167 mode = get_tv_string_buf(&argvars[2], modebuf); 20168 modec = TOLOWER_ASC(mode[0]); 20169 if (modec != 't' && modec != 'c' && modec != 'g') 20170 modec = 0; /* replace invalid with current */ 20171 } 20172 else 20173 { 20174 #if defined(FEAT_GUI) || defined(FEAT_TERMGUICOLORS) 20175 if (USE_24BIT) 20176 modec = 'g'; 20177 else 20178 #endif 20179 if (t_colors > 1) 20180 modec = 'c'; 20181 else 20182 modec = 't'; 20183 } 20184 20185 20186 switch (TOLOWER_ASC(what[0])) 20187 { 20188 case 'b': 20189 if (TOLOWER_ASC(what[1]) == 'g') /* bg[#] */ 20190 p = highlight_color(id, what, modec); 20191 else /* bold */ 20192 p = highlight_has_attr(id, HL_BOLD, modec); 20193 break; 20194 20195 case 'f': /* fg[#] or font */ 20196 p = highlight_color(id, what, modec); 20197 break; 20198 20199 case 'i': 20200 if (TOLOWER_ASC(what[1]) == 'n') /* inverse */ 20201 p = highlight_has_attr(id, HL_INVERSE, modec); 20202 else /* italic */ 20203 p = highlight_has_attr(id, HL_ITALIC, modec); 20204 break; 20205 20206 case 'n': /* name */ 20207 p = get_highlight_name(NULL, id - 1); 20208 break; 20209 20210 case 'r': /* reverse */ 20211 p = highlight_has_attr(id, HL_INVERSE, modec); 20212 break; 20213 20214 case 's': 20215 if (TOLOWER_ASC(what[1]) == 'p') /* sp[#] */ 20216 p = highlight_color(id, what, modec); 20217 else /* standout */ 20218 p = highlight_has_attr(id, HL_STANDOUT, modec); 20219 break; 20220 20221 case 'u': 20222 if (STRLEN(what) <= 5 || TOLOWER_ASC(what[5]) != 'c') 20223 /* underline */ 20224 p = highlight_has_attr(id, HL_UNDERLINE, modec); 20225 else 20226 /* undercurl */ 20227 p = highlight_has_attr(id, HL_UNDERCURL, modec); 20228 break; 20229 } 20230 20231 if (p != NULL) 20232 p = vim_strsave(p); 20233 #endif 20234 rettv->v_type = VAR_STRING; 20235 rettv->vval.v_string = p; 20236 } 20237 20238 /* 20239 * "synIDtrans(id)" function 20240 */ 20241 static void 20242 f_synIDtrans(typval_T *argvars UNUSED, typval_T *rettv) 20243 { 20244 int id; 20245 20246 #ifdef FEAT_SYN_HL 20247 id = get_tv_number(&argvars[0]); 20248 20249 if (id > 0) 20250 id = syn_get_final_id(id); 20251 else 20252 #endif 20253 id = 0; 20254 20255 rettv->vval.v_number = id; 20256 } 20257 20258 /* 20259 * "synconcealed(lnum, col)" function 20260 */ 20261 static void 20262 f_synconcealed(typval_T *argvars UNUSED, typval_T *rettv) 20263 { 20264 #if defined(FEAT_SYN_HL) && defined(FEAT_CONCEAL) 20265 long lnum; 20266 long col; 20267 int syntax_flags = 0; 20268 int cchar; 20269 int matchid = 0; 20270 char_u str[NUMBUFLEN]; 20271 #endif 20272 20273 rettv->v_type = VAR_LIST; 20274 rettv->vval.v_list = NULL; 20275 20276 #if defined(FEAT_SYN_HL) && defined(FEAT_CONCEAL) 20277 lnum = get_tv_lnum(argvars); /* -1 on type error */ 20278 col = get_tv_number(&argvars[1]) - 1; /* -1 on type error */ 20279 20280 vim_memset(str, NUL, sizeof(str)); 20281 20282 if (rettv_list_alloc(rettv) != FAIL) 20283 { 20284 if (lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count 20285 && col >= 0 && col <= (long)STRLEN(ml_get(lnum)) 20286 && curwin->w_p_cole > 0) 20287 { 20288 (void)syn_get_id(curwin, lnum, col, FALSE, NULL, FALSE); 20289 syntax_flags = get_syntax_info(&matchid); 20290 20291 /* get the conceal character */ 20292 if ((syntax_flags & HL_CONCEAL) && curwin->w_p_cole < 3) 20293 { 20294 cchar = syn_get_sub_char(); 20295 if (cchar == NUL && curwin->w_p_cole == 1 && lcs_conceal != NUL) 20296 cchar = lcs_conceal; 20297 if (cchar != NUL) 20298 { 20299 # ifdef FEAT_MBYTE 20300 if (has_mbyte) 20301 (*mb_char2bytes)(cchar, str); 20302 else 20303 # endif 20304 str[0] = cchar; 20305 } 20306 } 20307 } 20308 20309 list_append_number(rettv->vval.v_list, 20310 (syntax_flags & HL_CONCEAL) != 0); 20311 /* -1 to auto-determine strlen */ 20312 list_append_string(rettv->vval.v_list, str, -1); 20313 list_append_number(rettv->vval.v_list, matchid); 20314 } 20315 #endif 20316 } 20317 20318 /* 20319 * "synstack(lnum, col)" function 20320 */ 20321 static void 20322 f_synstack(typval_T *argvars UNUSED, typval_T *rettv) 20323 { 20324 #ifdef FEAT_SYN_HL 20325 long lnum; 20326 long col; 20327 int i; 20328 int id; 20329 #endif 20330 20331 rettv->v_type = VAR_LIST; 20332 rettv->vval.v_list = NULL; 20333 20334 #ifdef FEAT_SYN_HL 20335 lnum = get_tv_lnum(argvars); /* -1 on type error */ 20336 col = get_tv_number(&argvars[1]) - 1; /* -1 on type error */ 20337 20338 if (lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count 20339 && col >= 0 && col <= (long)STRLEN(ml_get(lnum)) 20340 && rettv_list_alloc(rettv) != FAIL) 20341 { 20342 (void)syn_get_id(curwin, lnum, (colnr_T)col, FALSE, NULL, TRUE); 20343 for (i = 0; ; ++i) 20344 { 20345 id = syn_get_stack_item(i); 20346 if (id < 0) 20347 break; 20348 if (list_append_number(rettv->vval.v_list, id) == FAIL) 20349 break; 20350 } 20351 } 20352 #endif 20353 } 20354 20355 static void 20356 get_cmd_output_as_rettv( 20357 typval_T *argvars, 20358 typval_T *rettv, 20359 int retlist) 20360 { 20361 char_u *res = NULL; 20362 char_u *p; 20363 char_u *infile = NULL; 20364 char_u buf[NUMBUFLEN]; 20365 int err = FALSE; 20366 FILE *fd; 20367 list_T *list = NULL; 20368 int flags = SHELL_SILENT; 20369 20370 rettv->v_type = VAR_STRING; 20371 rettv->vval.v_string = NULL; 20372 if (check_restricted() || check_secure()) 20373 goto errret; 20374 20375 if (argvars[1].v_type != VAR_UNKNOWN) 20376 { 20377 /* 20378 * Write the string to a temp file, to be used for input of the shell 20379 * command. 20380 */ 20381 if ((infile = vim_tempname('i', TRUE)) == NULL) 20382 { 20383 EMSG(_(e_notmp)); 20384 goto errret; 20385 } 20386 20387 fd = mch_fopen((char *)infile, WRITEBIN); 20388 if (fd == NULL) 20389 { 20390 EMSG2(_(e_notopen), infile); 20391 goto errret; 20392 } 20393 if (argvars[1].v_type == VAR_LIST) 20394 { 20395 if (write_list(fd, argvars[1].vval.v_list, TRUE) == FAIL) 20396 err = TRUE; 20397 } 20398 else 20399 { 20400 size_t len; 20401 20402 p = get_tv_string_buf_chk(&argvars[1], buf); 20403 if (p == NULL) 20404 { 20405 fclose(fd); 20406 goto errret; /* type error; errmsg already given */ 20407 } 20408 len = STRLEN(p); 20409 if (len > 0 && fwrite(p, len, 1, fd) != 1) 20410 err = TRUE; 20411 } 20412 if (fclose(fd) != 0) 20413 err = TRUE; 20414 if (err) 20415 { 20416 EMSG(_("E677: Error writing temp file")); 20417 goto errret; 20418 } 20419 } 20420 20421 /* Omit SHELL_COOKED when invoked with ":silent". Avoids that the shell 20422 * echoes typeahead, that messes up the display. */ 20423 if (!msg_silent) 20424 flags += SHELL_COOKED; 20425 20426 if (retlist) 20427 { 20428 int len; 20429 listitem_T *li; 20430 char_u *s = NULL; 20431 char_u *start; 20432 char_u *end; 20433 int i; 20434 20435 res = get_cmd_output(get_tv_string(&argvars[0]), infile, flags, &len); 20436 if (res == NULL) 20437 goto errret; 20438 20439 list = list_alloc(); 20440 if (list == NULL) 20441 goto errret; 20442 20443 for (i = 0; i < len; ++i) 20444 { 20445 start = res + i; 20446 while (i < len && res[i] != NL) 20447 ++i; 20448 end = res + i; 20449 20450 s = alloc((unsigned)(end - start + 1)); 20451 if (s == NULL) 20452 goto errret; 20453 20454 for (p = s; start < end; ++p, ++start) 20455 *p = *start == NUL ? NL : *start; 20456 *p = NUL; 20457 20458 li = listitem_alloc(); 20459 if (li == NULL) 20460 { 20461 vim_free(s); 20462 goto errret; 20463 } 20464 li->li_tv.v_type = VAR_STRING; 20465 li->li_tv.v_lock = 0; 20466 li->li_tv.vval.v_string = s; 20467 list_append(list, li); 20468 } 20469 20470 ++list->lv_refcount; 20471 rettv->v_type = VAR_LIST; 20472 rettv->vval.v_list = list; 20473 list = NULL; 20474 } 20475 else 20476 { 20477 res = get_cmd_output(get_tv_string(&argvars[0]), infile, flags, NULL); 20478 #ifdef USE_CR 20479 /* translate <CR> into <NL> */ 20480 if (res != NULL) 20481 { 20482 char_u *s; 20483 20484 for (s = res; *s; ++s) 20485 { 20486 if (*s == CAR) 20487 *s = NL; 20488 } 20489 } 20490 #else 20491 # ifdef USE_CRNL 20492 /* translate <CR><NL> into <NL> */ 20493 if (res != NULL) 20494 { 20495 char_u *s, *d; 20496 20497 d = res; 20498 for (s = res; *s; ++s) 20499 { 20500 if (s[0] == CAR && s[1] == NL) 20501 ++s; 20502 *d++ = *s; 20503 } 20504 *d = NUL; 20505 } 20506 # endif 20507 #endif 20508 rettv->vval.v_string = res; 20509 res = NULL; 20510 } 20511 20512 errret: 20513 if (infile != NULL) 20514 { 20515 mch_remove(infile); 20516 vim_free(infile); 20517 } 20518 if (res != NULL) 20519 vim_free(res); 20520 if (list != NULL) 20521 list_free(list); 20522 } 20523 20524 /* 20525 * "system()" function 20526 */ 20527 static void 20528 f_system(typval_T *argvars, typval_T *rettv) 20529 { 20530 get_cmd_output_as_rettv(argvars, rettv, FALSE); 20531 } 20532 20533 /* 20534 * "systemlist()" function 20535 */ 20536 static void 20537 f_systemlist(typval_T *argvars, typval_T *rettv) 20538 { 20539 get_cmd_output_as_rettv(argvars, rettv, TRUE); 20540 } 20541 20542 /* 20543 * "tabpagebuflist()" function 20544 */ 20545 static void 20546 f_tabpagebuflist(typval_T *argvars UNUSED, typval_T *rettv UNUSED) 20547 { 20548 #ifdef FEAT_WINDOWS 20549 tabpage_T *tp; 20550 win_T *wp = NULL; 20551 20552 if (argvars[0].v_type == VAR_UNKNOWN) 20553 wp = firstwin; 20554 else 20555 { 20556 tp = find_tabpage((int)get_tv_number(&argvars[0])); 20557 if (tp != NULL) 20558 wp = (tp == curtab) ? firstwin : tp->tp_firstwin; 20559 } 20560 if (wp != NULL && rettv_list_alloc(rettv) != FAIL) 20561 { 20562 for (; wp != NULL; wp = wp->w_next) 20563 if (list_append_number(rettv->vval.v_list, 20564 wp->w_buffer->b_fnum) == FAIL) 20565 break; 20566 } 20567 #endif 20568 } 20569 20570 20571 /* 20572 * "tabpagenr()" function 20573 */ 20574 static void 20575 f_tabpagenr(typval_T *argvars UNUSED, typval_T *rettv) 20576 { 20577 int nr = 1; 20578 #ifdef FEAT_WINDOWS 20579 char_u *arg; 20580 20581 if (argvars[0].v_type != VAR_UNKNOWN) 20582 { 20583 arg = get_tv_string_chk(&argvars[0]); 20584 nr = 0; 20585 if (arg != NULL) 20586 { 20587 if (STRCMP(arg, "$") == 0) 20588 nr = tabpage_index(NULL) - 1; 20589 else 20590 EMSG2(_(e_invexpr2), arg); 20591 } 20592 } 20593 else 20594 nr = tabpage_index(curtab); 20595 #endif 20596 rettv->vval.v_number = nr; 20597 } 20598 20599 20600 #ifdef FEAT_WINDOWS 20601 static int get_winnr(tabpage_T *tp, typval_T *argvar); 20602 20603 /* 20604 * Common code for tabpagewinnr() and winnr(). 20605 */ 20606 static int 20607 get_winnr(tabpage_T *tp, typval_T *argvar) 20608 { 20609 win_T *twin; 20610 int nr = 1; 20611 win_T *wp; 20612 char_u *arg; 20613 20614 twin = (tp == curtab) ? curwin : tp->tp_curwin; 20615 if (argvar->v_type != VAR_UNKNOWN) 20616 { 20617 arg = get_tv_string_chk(argvar); 20618 if (arg == NULL) 20619 nr = 0; /* type error; errmsg already given */ 20620 else if (STRCMP(arg, "$") == 0) 20621 twin = (tp == curtab) ? lastwin : tp->tp_lastwin; 20622 else if (STRCMP(arg, "#") == 0) 20623 { 20624 twin = (tp == curtab) ? prevwin : tp->tp_prevwin; 20625 if (twin == NULL) 20626 nr = 0; 20627 } 20628 else 20629 { 20630 EMSG2(_(e_invexpr2), arg); 20631 nr = 0; 20632 } 20633 } 20634 20635 if (nr > 0) 20636 for (wp = (tp == curtab) ? firstwin : tp->tp_firstwin; 20637 wp != twin; wp = wp->w_next) 20638 { 20639 if (wp == NULL) 20640 { 20641 /* didn't find it in this tabpage */ 20642 nr = 0; 20643 break; 20644 } 20645 ++nr; 20646 } 20647 return nr; 20648 } 20649 #endif 20650 20651 /* 20652 * "tabpagewinnr()" function 20653 */ 20654 static void 20655 f_tabpagewinnr(typval_T *argvars UNUSED, typval_T *rettv) 20656 { 20657 int nr = 1; 20658 #ifdef FEAT_WINDOWS 20659 tabpage_T *tp; 20660 20661 tp = find_tabpage((int)get_tv_number(&argvars[0])); 20662 if (tp == NULL) 20663 nr = 0; 20664 else 20665 nr = get_winnr(tp, &argvars[1]); 20666 #endif 20667 rettv->vval.v_number = nr; 20668 } 20669 20670 20671 /* 20672 * "tagfiles()" function 20673 */ 20674 static void 20675 f_tagfiles(typval_T *argvars UNUSED, typval_T *rettv) 20676 { 20677 char_u *fname; 20678 tagname_T tn; 20679 int first; 20680 20681 if (rettv_list_alloc(rettv) == FAIL) 20682 return; 20683 fname = alloc(MAXPATHL); 20684 if (fname == NULL) 20685 return; 20686 20687 for (first = TRUE; ; first = FALSE) 20688 if (get_tagfname(&tn, first, fname) == FAIL 20689 || list_append_string(rettv->vval.v_list, fname, -1) == FAIL) 20690 break; 20691 tagname_free(&tn); 20692 vim_free(fname); 20693 } 20694 20695 /* 20696 * "taglist()" function 20697 */ 20698 static void 20699 f_taglist(typval_T *argvars, typval_T *rettv) 20700 { 20701 char_u *tag_pattern; 20702 20703 tag_pattern = get_tv_string(&argvars[0]); 20704 20705 rettv->vval.v_number = FALSE; 20706 if (*tag_pattern == NUL) 20707 return; 20708 20709 if (rettv_list_alloc(rettv) == OK) 20710 (void)get_tags(rettv->vval.v_list, tag_pattern); 20711 } 20712 20713 /* 20714 * "tempname()" function 20715 */ 20716 static void 20717 f_tempname(typval_T *argvars UNUSED, typval_T *rettv) 20718 { 20719 static int x = 'A'; 20720 20721 rettv->v_type = VAR_STRING; 20722 rettv->vval.v_string = vim_tempname(x, FALSE); 20723 20724 /* Advance 'x' to use A-Z and 0-9, so that there are at least 34 different 20725 * names. Skip 'I' and 'O', they are used for shell redirection. */ 20726 do 20727 { 20728 if (x == 'Z') 20729 x = '0'; 20730 else if (x == '9') 20731 x = 'A'; 20732 else 20733 { 20734 #ifdef EBCDIC 20735 if (x == 'I') 20736 x = 'J'; 20737 else if (x == 'R') 20738 x = 'S'; 20739 else 20740 #endif 20741 ++x; 20742 } 20743 } while (x == 'I' || x == 'O'); 20744 } 20745 20746 #ifdef FEAT_FLOAT 20747 /* 20748 * "tan()" function 20749 */ 20750 static void 20751 f_tan(typval_T *argvars, typval_T *rettv) 20752 { 20753 float_T f = 0.0; 20754 20755 rettv->v_type = VAR_FLOAT; 20756 if (get_float_arg(argvars, &f) == OK) 20757 rettv->vval.v_float = tan(f); 20758 else 20759 rettv->vval.v_float = 0.0; 20760 } 20761 20762 /* 20763 * "tanh()" function 20764 */ 20765 static void 20766 f_tanh(typval_T *argvars, typval_T *rettv) 20767 { 20768 float_T f = 0.0; 20769 20770 rettv->v_type = VAR_FLOAT; 20771 if (get_float_arg(argvars, &f) == OK) 20772 rettv->vval.v_float = tanh(f); 20773 else 20774 rettv->vval.v_float = 0.0; 20775 } 20776 #endif 20777 20778 /* 20779 * "test_alloc_fail(id, countdown, repeat)" function 20780 */ 20781 static void 20782 f_test_alloc_fail(typval_T *argvars, typval_T *rettv UNUSED) 20783 { 20784 if (argvars[0].v_type != VAR_NUMBER 20785 || argvars[0].vval.v_number <= 0 20786 || argvars[1].v_type != VAR_NUMBER 20787 || argvars[1].vval.v_number < 0 20788 || argvars[2].v_type != VAR_NUMBER) 20789 EMSG(_(e_invarg)); 20790 else 20791 { 20792 alloc_fail_id = argvars[0].vval.v_number; 20793 if (alloc_fail_id >= aid_last) 20794 EMSG(_(e_invarg)); 20795 alloc_fail_countdown = argvars[1].vval.v_number; 20796 alloc_fail_repeat = argvars[2].vval.v_number; 20797 did_outofmem_msg = FALSE; 20798 } 20799 } 20800 20801 /* 20802 * "test_disable_char_avail({expr})" function 20803 */ 20804 static void 20805 f_test_disable_char_avail(typval_T *argvars, typval_T *rettv UNUSED) 20806 { 20807 disable_char_avail_for_testing = get_tv_number(&argvars[0]); 20808 } 20809 20810 /* 20811 * "test_garbagecollect_now()" function 20812 */ 20813 static void 20814 f_test_garbagecollect_now(typval_T *argvars UNUSED, typval_T *rettv UNUSED) 20815 { 20816 /* This is dangerous, any Lists and Dicts used internally may be freed 20817 * while still in use. */ 20818 garbage_collect(TRUE); 20819 } 20820 20821 #ifdef FEAT_JOB_CHANNEL 20822 static void 20823 f_test_null_channel(typval_T *argvars UNUSED, typval_T *rettv UNUSED) 20824 { 20825 rettv->v_type = VAR_CHANNEL; 20826 rettv->vval.v_channel = NULL; 20827 } 20828 #endif 20829 20830 static void 20831 f_test_null_dict(typval_T *argvars UNUSED, typval_T *rettv UNUSED) 20832 { 20833 rettv->v_type = VAR_DICT; 20834 rettv->vval.v_dict = NULL; 20835 } 20836 20837 #ifdef FEAT_JOB_CHANNEL 20838 static void 20839 f_test_null_job(typval_T *argvars UNUSED, typval_T *rettv UNUSED) 20840 { 20841 rettv->v_type = VAR_JOB; 20842 rettv->vval.v_job = NULL; 20843 } 20844 #endif 20845 20846 static void 20847 f_test_null_list(typval_T *argvars UNUSED, typval_T *rettv UNUSED) 20848 { 20849 rettv->v_type = VAR_LIST; 20850 rettv->vval.v_list = NULL; 20851 } 20852 20853 static void 20854 f_test_null_partial(typval_T *argvars UNUSED, typval_T *rettv UNUSED) 20855 { 20856 rettv->v_type = VAR_PARTIAL; 20857 rettv->vval.v_partial = NULL; 20858 } 20859 20860 static void 20861 f_test_null_string(typval_T *argvars UNUSED, typval_T *rettv UNUSED) 20862 { 20863 rettv->v_type = VAR_STRING; 20864 rettv->vval.v_string = NULL; 20865 } 20866 20867 #if defined(FEAT_JOB_CHANNEL) || defined(FEAT_TIMERS) || defined(PROTO) 20868 /* 20869 * Get a callback from "arg". It can be a Funcref or a function name. 20870 * When "arg" is zero return an empty string. 20871 * Return NULL for an invalid argument. 20872 */ 20873 char_u * 20874 get_callback(typval_T *arg, partial_T **pp) 20875 { 20876 if (arg->v_type == VAR_PARTIAL && arg->vval.v_partial != NULL) 20877 { 20878 *pp = arg->vval.v_partial; 20879 ++(*pp)->pt_refcount; 20880 return (*pp)->pt_name; 20881 } 20882 *pp = NULL; 20883 if (arg->v_type == VAR_FUNC || arg->v_type == VAR_STRING) 20884 return arg->vval.v_string; 20885 if (arg->v_type == VAR_NUMBER && arg->vval.v_number == 0) 20886 return (char_u *)""; 20887 EMSG(_("E921: Invalid callback argument")); 20888 return NULL; 20889 } 20890 #endif 20891 20892 #ifdef FEAT_TIMERS 20893 /* 20894 * "timer_start(time, callback [, options])" function 20895 */ 20896 static void 20897 f_timer_start(typval_T *argvars, typval_T *rettv) 20898 { 20899 long msec = get_tv_number(&argvars[0]); 20900 timer_T *timer; 20901 int repeat = 0; 20902 char_u *callback; 20903 dict_T *dict; 20904 20905 if (check_secure()) 20906 return; 20907 if (argvars[2].v_type != VAR_UNKNOWN) 20908 { 20909 if (argvars[2].v_type != VAR_DICT 20910 || (dict = argvars[2].vval.v_dict) == NULL) 20911 { 20912 EMSG2(_(e_invarg2), get_tv_string(&argvars[2])); 20913 return; 20914 } 20915 if (dict_find(dict, (char_u *)"repeat", -1) != NULL) 20916 repeat = get_dict_number(dict, (char_u *)"repeat"); 20917 } 20918 20919 timer = create_timer(msec, repeat); 20920 callback = get_callback(&argvars[1], &timer->tr_partial); 20921 if (callback == NULL) 20922 { 20923 stop_timer(timer); 20924 rettv->vval.v_number = -1; 20925 } 20926 else 20927 { 20928 timer->tr_callback = vim_strsave(callback); 20929 rettv->vval.v_number = timer->tr_id; 20930 } 20931 } 20932 20933 /* 20934 * "timer_stop(timer)" function 20935 */ 20936 static void 20937 f_timer_stop(typval_T *argvars, typval_T *rettv UNUSED) 20938 { 20939 timer_T *timer; 20940 20941 if (argvars[0].v_type != VAR_NUMBER) 20942 { 20943 EMSG(_(e_number_exp)); 20944 return; 20945 } 20946 timer = find_timer(get_tv_number(&argvars[0])); 20947 if (timer != NULL) 20948 stop_timer(timer); 20949 } 20950 #endif 20951 20952 /* 20953 * "tolower(string)" function 20954 */ 20955 static void 20956 f_tolower(typval_T *argvars, typval_T *rettv) 20957 { 20958 char_u *p; 20959 20960 p = vim_strsave(get_tv_string(&argvars[0])); 20961 rettv->v_type = VAR_STRING; 20962 rettv->vval.v_string = p; 20963 20964 if (p != NULL) 20965 while (*p != NUL) 20966 { 20967 #ifdef FEAT_MBYTE 20968 int l; 20969 20970 if (enc_utf8) 20971 { 20972 int c, lc; 20973 20974 c = utf_ptr2char(p); 20975 lc = utf_tolower(c); 20976 l = utf_ptr2len(p); 20977 /* TODO: reallocate string when byte count changes. */ 20978 if (utf_char2len(lc) == l) 20979 utf_char2bytes(lc, p); 20980 p += l; 20981 } 20982 else if (has_mbyte && (l = (*mb_ptr2len)(p)) > 1) 20983 p += l; /* skip multi-byte character */ 20984 else 20985 #endif 20986 { 20987 *p = TOLOWER_LOC(*p); /* note that tolower() can be a macro */ 20988 ++p; 20989 } 20990 } 20991 } 20992 20993 /* 20994 * "toupper(string)" function 20995 */ 20996 static void 20997 f_toupper(typval_T *argvars, typval_T *rettv) 20998 { 20999 rettv->v_type = VAR_STRING; 21000 rettv->vval.v_string = strup_save(get_tv_string(&argvars[0])); 21001 } 21002 21003 /* 21004 * "tr(string, fromstr, tostr)" function 21005 */ 21006 static void 21007 f_tr(typval_T *argvars, typval_T *rettv) 21008 { 21009 char_u *in_str; 21010 char_u *fromstr; 21011 char_u *tostr; 21012 char_u *p; 21013 #ifdef FEAT_MBYTE 21014 int inlen; 21015 int fromlen; 21016 int tolen; 21017 int idx; 21018 char_u *cpstr; 21019 int cplen; 21020 int first = TRUE; 21021 #endif 21022 char_u buf[NUMBUFLEN]; 21023 char_u buf2[NUMBUFLEN]; 21024 garray_T ga; 21025 21026 in_str = get_tv_string(&argvars[0]); 21027 fromstr = get_tv_string_buf_chk(&argvars[1], buf); 21028 tostr = get_tv_string_buf_chk(&argvars[2], buf2); 21029 21030 /* Default return value: empty string. */ 21031 rettv->v_type = VAR_STRING; 21032 rettv->vval.v_string = NULL; 21033 if (fromstr == NULL || tostr == NULL) 21034 return; /* type error; errmsg already given */ 21035 ga_init2(&ga, (int)sizeof(char), 80); 21036 21037 #ifdef FEAT_MBYTE 21038 if (!has_mbyte) 21039 #endif 21040 /* not multi-byte: fromstr and tostr must be the same length */ 21041 if (STRLEN(fromstr) != STRLEN(tostr)) 21042 { 21043 #ifdef FEAT_MBYTE 21044 error: 21045 #endif 21046 EMSG2(_(e_invarg2), fromstr); 21047 ga_clear(&ga); 21048 return; 21049 } 21050 21051 /* fromstr and tostr have to contain the same number of chars */ 21052 while (*in_str != NUL) 21053 { 21054 #ifdef FEAT_MBYTE 21055 if (has_mbyte) 21056 { 21057 inlen = (*mb_ptr2len)(in_str); 21058 cpstr = in_str; 21059 cplen = inlen; 21060 idx = 0; 21061 for (p = fromstr; *p != NUL; p += fromlen) 21062 { 21063 fromlen = (*mb_ptr2len)(p); 21064 if (fromlen == inlen && STRNCMP(in_str, p, inlen) == 0) 21065 { 21066 for (p = tostr; *p != NUL; p += tolen) 21067 { 21068 tolen = (*mb_ptr2len)(p); 21069 if (idx-- == 0) 21070 { 21071 cplen = tolen; 21072 cpstr = p; 21073 break; 21074 } 21075 } 21076 if (*p == NUL) /* tostr is shorter than fromstr */ 21077 goto error; 21078 break; 21079 } 21080 ++idx; 21081 } 21082 21083 if (first && cpstr == in_str) 21084 { 21085 /* Check that fromstr and tostr have the same number of 21086 * (multi-byte) characters. Done only once when a character 21087 * of in_str doesn't appear in fromstr. */ 21088 first = FALSE; 21089 for (p = tostr; *p != NUL; p += tolen) 21090 { 21091 tolen = (*mb_ptr2len)(p); 21092 --idx; 21093 } 21094 if (idx != 0) 21095 goto error; 21096 } 21097 21098 (void)ga_grow(&ga, cplen); 21099 mch_memmove((char *)ga.ga_data + ga.ga_len, cpstr, (size_t)cplen); 21100 ga.ga_len += cplen; 21101 21102 in_str += inlen; 21103 } 21104 else 21105 #endif 21106 { 21107 /* When not using multi-byte chars we can do it faster. */ 21108 p = vim_strchr(fromstr, *in_str); 21109 if (p != NULL) 21110 ga_append(&ga, tostr[p - fromstr]); 21111 else 21112 ga_append(&ga, *in_str); 21113 ++in_str; 21114 } 21115 } 21116 21117 /* add a terminating NUL */ 21118 (void)ga_grow(&ga, 1); 21119 ga_append(&ga, NUL); 21120 21121 rettv->vval.v_string = ga.ga_data; 21122 } 21123 21124 #ifdef FEAT_FLOAT 21125 /* 21126 * "trunc({float})" function 21127 */ 21128 static void 21129 f_trunc(typval_T *argvars, typval_T *rettv) 21130 { 21131 float_T f = 0.0; 21132 21133 rettv->v_type = VAR_FLOAT; 21134 if (get_float_arg(argvars, &f) == OK) 21135 /* trunc() is not in C90, use floor() or ceil() instead. */ 21136 rettv->vval.v_float = f > 0 ? floor(f) : ceil(f); 21137 else 21138 rettv->vval.v_float = 0.0; 21139 } 21140 #endif 21141 21142 /* 21143 * "type(expr)" function 21144 */ 21145 static void 21146 f_type(typval_T *argvars, typval_T *rettv) 21147 { 21148 int n = -1; 21149 21150 switch (argvars[0].v_type) 21151 { 21152 case VAR_NUMBER: n = 0; break; 21153 case VAR_STRING: n = 1; break; 21154 case VAR_PARTIAL: 21155 case VAR_FUNC: n = 2; break; 21156 case VAR_LIST: n = 3; break; 21157 case VAR_DICT: n = 4; break; 21158 case VAR_FLOAT: n = 5; break; 21159 case VAR_SPECIAL: 21160 if (argvars[0].vval.v_number == VVAL_FALSE 21161 || argvars[0].vval.v_number == VVAL_TRUE) 21162 n = 6; 21163 else 21164 n = 7; 21165 break; 21166 case VAR_JOB: n = 8; break; 21167 case VAR_CHANNEL: n = 9; break; 21168 case VAR_UNKNOWN: 21169 EMSG2(_(e_intern2), "f_type(UNKNOWN)"); 21170 n = -1; 21171 break; 21172 } 21173 rettv->vval.v_number = n; 21174 } 21175 21176 /* 21177 * "undofile(name)" function 21178 */ 21179 static void 21180 f_undofile(typval_T *argvars UNUSED, typval_T *rettv) 21181 { 21182 rettv->v_type = VAR_STRING; 21183 #ifdef FEAT_PERSISTENT_UNDO 21184 { 21185 char_u *fname = get_tv_string(&argvars[0]); 21186 21187 if (*fname == NUL) 21188 { 21189 /* If there is no file name there will be no undo file. */ 21190 rettv->vval.v_string = NULL; 21191 } 21192 else 21193 { 21194 char_u *ffname = FullName_save(fname, FALSE); 21195 21196 if (ffname != NULL) 21197 rettv->vval.v_string = u_get_undo_file_name(ffname, FALSE); 21198 vim_free(ffname); 21199 } 21200 } 21201 #else 21202 rettv->vval.v_string = NULL; 21203 #endif 21204 } 21205 21206 /* 21207 * "undotree()" function 21208 */ 21209 static void 21210 f_undotree(typval_T *argvars UNUSED, typval_T *rettv) 21211 { 21212 if (rettv_dict_alloc(rettv) == OK) 21213 { 21214 dict_T *dict = rettv->vval.v_dict; 21215 list_T *list; 21216 21217 dict_add_nr_str(dict, "synced", (long)curbuf->b_u_synced, NULL); 21218 dict_add_nr_str(dict, "seq_last", curbuf->b_u_seq_last, NULL); 21219 dict_add_nr_str(dict, "save_last", 21220 (long)curbuf->b_u_save_nr_last, NULL); 21221 dict_add_nr_str(dict, "seq_cur", curbuf->b_u_seq_cur, NULL); 21222 dict_add_nr_str(dict, "time_cur", (long)curbuf->b_u_time_cur, NULL); 21223 dict_add_nr_str(dict, "save_cur", (long)curbuf->b_u_save_nr_cur, NULL); 21224 21225 list = list_alloc(); 21226 if (list != NULL) 21227 { 21228 u_eval_tree(curbuf->b_u_oldhead, list); 21229 dict_add_list(dict, "entries", list); 21230 } 21231 } 21232 } 21233 21234 /* 21235 * "values(dict)" function 21236 */ 21237 static void 21238 f_values(typval_T *argvars, typval_T *rettv) 21239 { 21240 dict_list(argvars, rettv, 1); 21241 } 21242 21243 /* 21244 * "virtcol(string)" function 21245 */ 21246 static void 21247 f_virtcol(typval_T *argvars, typval_T *rettv) 21248 { 21249 colnr_T vcol = 0; 21250 pos_T *fp; 21251 int fnum = curbuf->b_fnum; 21252 21253 fp = var2fpos(&argvars[0], FALSE, &fnum); 21254 if (fp != NULL && fp->lnum <= curbuf->b_ml.ml_line_count 21255 && fnum == curbuf->b_fnum) 21256 { 21257 getvvcol(curwin, fp, NULL, NULL, &vcol); 21258 ++vcol; 21259 } 21260 21261 rettv->vval.v_number = vcol; 21262 } 21263 21264 /* 21265 * "visualmode()" function 21266 */ 21267 static void 21268 f_visualmode(typval_T *argvars, typval_T *rettv) 21269 { 21270 char_u str[2]; 21271 21272 rettv->v_type = VAR_STRING; 21273 str[0] = curbuf->b_visual_mode_eval; 21274 str[1] = NUL; 21275 rettv->vval.v_string = vim_strsave(str); 21276 21277 /* A non-zero number or non-empty string argument: reset mode. */ 21278 if (non_zero_arg(&argvars[0])) 21279 curbuf->b_visual_mode_eval = NUL; 21280 } 21281 21282 /* 21283 * "wildmenumode()" function 21284 */ 21285 static void 21286 f_wildmenumode(typval_T *argvars UNUSED, typval_T *rettv UNUSED) 21287 { 21288 #ifdef FEAT_WILDMENU 21289 if (wild_menu_showing) 21290 rettv->vval.v_number = 1; 21291 #endif 21292 } 21293 21294 /* 21295 * "winbufnr(nr)" function 21296 */ 21297 static void 21298 f_winbufnr(typval_T *argvars, typval_T *rettv) 21299 { 21300 win_T *wp; 21301 21302 wp = find_win_by_nr(&argvars[0], NULL); 21303 if (wp == NULL) 21304 rettv->vval.v_number = -1; 21305 else 21306 rettv->vval.v_number = wp->w_buffer->b_fnum; 21307 } 21308 21309 /* 21310 * "wincol()" function 21311 */ 21312 static void 21313 f_wincol(typval_T *argvars UNUSED, typval_T *rettv) 21314 { 21315 validate_cursor(); 21316 rettv->vval.v_number = curwin->w_wcol + 1; 21317 } 21318 21319 /* 21320 * "winheight(nr)" function 21321 */ 21322 static void 21323 f_winheight(typval_T *argvars, typval_T *rettv) 21324 { 21325 win_T *wp; 21326 21327 wp = find_win_by_nr(&argvars[0], NULL); 21328 if (wp == NULL) 21329 rettv->vval.v_number = -1; 21330 else 21331 rettv->vval.v_number = wp->w_height; 21332 } 21333 21334 /* 21335 * "winline()" function 21336 */ 21337 static void 21338 f_winline(typval_T *argvars UNUSED, typval_T *rettv) 21339 { 21340 validate_cursor(); 21341 rettv->vval.v_number = curwin->w_wrow + 1; 21342 } 21343 21344 /* 21345 * "winnr()" function 21346 */ 21347 static void 21348 f_winnr(typval_T *argvars UNUSED, typval_T *rettv) 21349 { 21350 int nr = 1; 21351 21352 #ifdef FEAT_WINDOWS 21353 nr = get_winnr(curtab, &argvars[0]); 21354 #endif 21355 rettv->vval.v_number = nr; 21356 } 21357 21358 /* 21359 * "winrestcmd()" function 21360 */ 21361 static void 21362 f_winrestcmd(typval_T *argvars UNUSED, typval_T *rettv) 21363 { 21364 #ifdef FEAT_WINDOWS 21365 win_T *wp; 21366 int winnr = 1; 21367 garray_T ga; 21368 char_u buf[50]; 21369 21370 ga_init2(&ga, (int)sizeof(char), 70); 21371 for (wp = firstwin; wp != NULL; wp = wp->w_next) 21372 { 21373 sprintf((char *)buf, "%dresize %d|", winnr, wp->w_height); 21374 ga_concat(&ga, buf); 21375 sprintf((char *)buf, "vert %dresize %d|", winnr, wp->w_width); 21376 ga_concat(&ga, buf); 21377 ++winnr; 21378 } 21379 ga_append(&ga, NUL); 21380 21381 rettv->vval.v_string = ga.ga_data; 21382 #else 21383 rettv->vval.v_string = NULL; 21384 #endif 21385 rettv->v_type = VAR_STRING; 21386 } 21387 21388 /* 21389 * "winrestview()" function 21390 */ 21391 static void 21392 f_winrestview(typval_T *argvars, typval_T *rettv UNUSED) 21393 { 21394 dict_T *dict; 21395 21396 if (argvars[0].v_type != VAR_DICT 21397 || (dict = argvars[0].vval.v_dict) == NULL) 21398 EMSG(_(e_invarg)); 21399 else 21400 { 21401 if (dict_find(dict, (char_u *)"lnum", -1) != NULL) 21402 curwin->w_cursor.lnum = get_dict_number(dict, (char_u *)"lnum"); 21403 if (dict_find(dict, (char_u *)"col", -1) != NULL) 21404 curwin->w_cursor.col = get_dict_number(dict, (char_u *)"col"); 21405 #ifdef FEAT_VIRTUALEDIT 21406 if (dict_find(dict, (char_u *)"coladd", -1) != NULL) 21407 curwin->w_cursor.coladd = get_dict_number(dict, (char_u *)"coladd"); 21408 #endif 21409 if (dict_find(dict, (char_u *)"curswant", -1) != NULL) 21410 { 21411 curwin->w_curswant = get_dict_number(dict, (char_u *)"curswant"); 21412 curwin->w_set_curswant = FALSE; 21413 } 21414 21415 if (dict_find(dict, (char_u *)"topline", -1) != NULL) 21416 set_topline(curwin, get_dict_number(dict, (char_u *)"topline")); 21417 #ifdef FEAT_DIFF 21418 if (dict_find(dict, (char_u *)"topfill", -1) != NULL) 21419 curwin->w_topfill = get_dict_number(dict, (char_u *)"topfill"); 21420 #endif 21421 if (dict_find(dict, (char_u *)"leftcol", -1) != NULL) 21422 curwin->w_leftcol = get_dict_number(dict, (char_u *)"leftcol"); 21423 if (dict_find(dict, (char_u *)"skipcol", -1) != NULL) 21424 curwin->w_skipcol = get_dict_number(dict, (char_u *)"skipcol"); 21425 21426 check_cursor(); 21427 win_new_height(curwin, curwin->w_height); 21428 # ifdef FEAT_WINDOWS 21429 win_new_width(curwin, W_WIDTH(curwin)); 21430 # endif 21431 changed_window_setting(); 21432 21433 if (curwin->w_topline <= 0) 21434 curwin->w_topline = 1; 21435 if (curwin->w_topline > curbuf->b_ml.ml_line_count) 21436 curwin->w_topline = curbuf->b_ml.ml_line_count; 21437 #ifdef FEAT_DIFF 21438 check_topfill(curwin, TRUE); 21439 #endif 21440 } 21441 } 21442 21443 /* 21444 * "winsaveview()" function 21445 */ 21446 static void 21447 f_winsaveview(typval_T *argvars UNUSED, typval_T *rettv) 21448 { 21449 dict_T *dict; 21450 21451 if (rettv_dict_alloc(rettv) == FAIL) 21452 return; 21453 dict = rettv->vval.v_dict; 21454 21455 dict_add_nr_str(dict, "lnum", (long)curwin->w_cursor.lnum, NULL); 21456 dict_add_nr_str(dict, "col", (long)curwin->w_cursor.col, NULL); 21457 #ifdef FEAT_VIRTUALEDIT 21458 dict_add_nr_str(dict, "coladd", (long)curwin->w_cursor.coladd, NULL); 21459 #endif 21460 update_curswant(); 21461 dict_add_nr_str(dict, "curswant", (long)curwin->w_curswant, NULL); 21462 21463 dict_add_nr_str(dict, "topline", (long)curwin->w_topline, NULL); 21464 #ifdef FEAT_DIFF 21465 dict_add_nr_str(dict, "topfill", (long)curwin->w_topfill, NULL); 21466 #endif 21467 dict_add_nr_str(dict, "leftcol", (long)curwin->w_leftcol, NULL); 21468 dict_add_nr_str(dict, "skipcol", (long)curwin->w_skipcol, NULL); 21469 } 21470 21471 /* 21472 * "winwidth(nr)" function 21473 */ 21474 static void 21475 f_winwidth(typval_T *argvars, typval_T *rettv) 21476 { 21477 win_T *wp; 21478 21479 wp = find_win_by_nr(&argvars[0], NULL); 21480 if (wp == NULL) 21481 rettv->vval.v_number = -1; 21482 else 21483 #ifdef FEAT_WINDOWS 21484 rettv->vval.v_number = wp->w_width; 21485 #else 21486 rettv->vval.v_number = Columns; 21487 #endif 21488 } 21489 21490 /* 21491 * "wordcount()" function 21492 */ 21493 static void 21494 f_wordcount(typval_T *argvars UNUSED, typval_T *rettv) 21495 { 21496 if (rettv_dict_alloc(rettv) == FAIL) 21497 return; 21498 cursor_pos_info(rettv->vval.v_dict); 21499 } 21500 21501 /* 21502 * Write list of strings to file 21503 */ 21504 static int 21505 write_list(FILE *fd, list_T *list, int binary) 21506 { 21507 listitem_T *li; 21508 int c; 21509 int ret = OK; 21510 char_u *s; 21511 21512 for (li = list->lv_first; li != NULL; li = li->li_next) 21513 { 21514 for (s = get_tv_string(&li->li_tv); *s != NUL; ++s) 21515 { 21516 if (*s == '\n') 21517 c = putc(NUL, fd); 21518 else 21519 c = putc(*s, fd); 21520 if (c == EOF) 21521 { 21522 ret = FAIL; 21523 break; 21524 } 21525 } 21526 if (!binary || li->li_next != NULL) 21527 if (putc('\n', fd) == EOF) 21528 { 21529 ret = FAIL; 21530 break; 21531 } 21532 if (ret == FAIL) 21533 { 21534 EMSG(_(e_write)); 21535 break; 21536 } 21537 } 21538 return ret; 21539 } 21540 21541 /* 21542 * "writefile()" function 21543 */ 21544 static void 21545 f_writefile(typval_T *argvars, typval_T *rettv) 21546 { 21547 int binary = FALSE; 21548 int append = FALSE; 21549 char_u *fname; 21550 FILE *fd; 21551 int ret = 0; 21552 21553 if (check_restricted() || check_secure()) 21554 return; 21555 21556 if (argvars[0].v_type != VAR_LIST) 21557 { 21558 EMSG2(_(e_listarg), "writefile()"); 21559 return; 21560 } 21561 if (argvars[0].vval.v_list == NULL) 21562 return; 21563 21564 if (argvars[2].v_type != VAR_UNKNOWN) 21565 { 21566 if (vim_strchr(get_tv_string(&argvars[2]), 'b') != NULL) 21567 binary = TRUE; 21568 if (vim_strchr(get_tv_string(&argvars[2]), 'a') != NULL) 21569 append = TRUE; 21570 } 21571 21572 /* Always open the file in binary mode, library functions have a mind of 21573 * their own about CR-LF conversion. */ 21574 fname = get_tv_string(&argvars[1]); 21575 if (*fname == NUL || (fd = mch_fopen((char *)fname, 21576 append ? APPENDBIN : WRITEBIN)) == NULL) 21577 { 21578 EMSG2(_(e_notcreate), *fname == NUL ? (char_u *)_("<empty>") : fname); 21579 ret = -1; 21580 } 21581 else 21582 { 21583 if (write_list(fd, argvars[0].vval.v_list, binary) == FAIL) 21584 ret = -1; 21585 fclose(fd); 21586 } 21587 21588 rettv->vval.v_number = ret; 21589 } 21590 21591 /* 21592 * "xor(expr, expr)" function 21593 */ 21594 static void 21595 f_xor(typval_T *argvars, typval_T *rettv) 21596 { 21597 rettv->vval.v_number = get_tv_number_chk(&argvars[0], NULL) 21598 ^ get_tv_number_chk(&argvars[1], NULL); 21599 } 21600 21601 21602 /* 21603 * Translate a String variable into a position. 21604 * Returns NULL when there is an error. 21605 */ 21606 static pos_T * 21607 var2fpos( 21608 typval_T *varp, 21609 int dollar_lnum, /* TRUE when $ is last line */ 21610 int *fnum) /* set to fnum for '0, 'A, etc. */ 21611 { 21612 char_u *name; 21613 static pos_T pos; 21614 pos_T *pp; 21615 21616 /* Argument can be [lnum, col, coladd]. */ 21617 if (varp->v_type == VAR_LIST) 21618 { 21619 list_T *l; 21620 int len; 21621 int error = FALSE; 21622 listitem_T *li; 21623 21624 l = varp->vval.v_list; 21625 if (l == NULL) 21626 return NULL; 21627 21628 /* Get the line number */ 21629 pos.lnum = list_find_nr(l, 0L, &error); 21630 if (error || pos.lnum <= 0 || pos.lnum > curbuf->b_ml.ml_line_count) 21631 return NULL; /* invalid line number */ 21632 21633 /* Get the column number */ 21634 pos.col = list_find_nr(l, 1L, &error); 21635 if (error) 21636 return NULL; 21637 len = (long)STRLEN(ml_get(pos.lnum)); 21638 21639 /* We accept "$" for the column number: last column. */ 21640 li = list_find(l, 1L); 21641 if (li != NULL && li->li_tv.v_type == VAR_STRING 21642 && li->li_tv.vval.v_string != NULL 21643 && STRCMP(li->li_tv.vval.v_string, "$") == 0) 21644 pos.col = len + 1; 21645 21646 /* Accept a position up to the NUL after the line. */ 21647 if (pos.col == 0 || (int)pos.col > len + 1) 21648 return NULL; /* invalid column number */ 21649 --pos.col; 21650 21651 #ifdef FEAT_VIRTUALEDIT 21652 /* Get the virtual offset. Defaults to zero. */ 21653 pos.coladd = list_find_nr(l, 2L, &error); 21654 if (error) 21655 pos.coladd = 0; 21656 #endif 21657 21658 return &pos; 21659 } 21660 21661 name = get_tv_string_chk(varp); 21662 if (name == NULL) 21663 return NULL; 21664 if (name[0] == '.') /* cursor */ 21665 return &curwin->w_cursor; 21666 if (name[0] == 'v' && name[1] == NUL) /* Visual start */ 21667 { 21668 if (VIsual_active) 21669 return &VIsual; 21670 return &curwin->w_cursor; 21671 } 21672 if (name[0] == '\'') /* mark */ 21673 { 21674 pp = getmark_buf_fnum(curbuf, name[1], FALSE, fnum); 21675 if (pp == NULL || pp == (pos_T *)-1 || pp->lnum <= 0) 21676 return NULL; 21677 return pp; 21678 } 21679 21680 #ifdef FEAT_VIRTUALEDIT 21681 pos.coladd = 0; 21682 #endif 21683 21684 if (name[0] == 'w' && dollar_lnum) 21685 { 21686 pos.col = 0; 21687 if (name[1] == '0') /* "w0": first visible line */ 21688 { 21689 update_topline(); 21690 pos.lnum = curwin->w_topline; 21691 return &pos; 21692 } 21693 else if (name[1] == '$') /* "w$": last visible line */ 21694 { 21695 validate_botline(); 21696 pos.lnum = curwin->w_botline - 1; 21697 return &pos; 21698 } 21699 } 21700 else if (name[0] == '$') /* last column or line */ 21701 { 21702 if (dollar_lnum) 21703 { 21704 pos.lnum = curbuf->b_ml.ml_line_count; 21705 pos.col = 0; 21706 } 21707 else 21708 { 21709 pos.lnum = curwin->w_cursor.lnum; 21710 pos.col = (colnr_T)STRLEN(ml_get_curline()); 21711 } 21712 return &pos; 21713 } 21714 return NULL; 21715 } 21716 21717 /* 21718 * Convert list in "arg" into a position and optional file number. 21719 * When "fnump" is NULL there is no file number, only 3 items. 21720 * Note that the column is passed on as-is, the caller may want to decrement 21721 * it to use 1 for the first column. 21722 * Return FAIL when conversion is not possible, doesn't check the position for 21723 * validity. 21724 */ 21725 static int 21726 list2fpos( 21727 typval_T *arg, 21728 pos_T *posp, 21729 int *fnump, 21730 colnr_T *curswantp) 21731 { 21732 list_T *l = arg->vval.v_list; 21733 long i = 0; 21734 long n; 21735 21736 /* List must be: [fnum, lnum, col, coladd, curswant], where "fnum" is only 21737 * there when "fnump" isn't NULL; "coladd" and "curswant" are optional. */ 21738 if (arg->v_type != VAR_LIST 21739 || l == NULL 21740 || l->lv_len < (fnump == NULL ? 2 : 3) 21741 || l->lv_len > (fnump == NULL ? 4 : 5)) 21742 return FAIL; 21743 21744 if (fnump != NULL) 21745 { 21746 n = list_find_nr(l, i++, NULL); /* fnum */ 21747 if (n < 0) 21748 return FAIL; 21749 if (n == 0) 21750 n = curbuf->b_fnum; /* current buffer */ 21751 *fnump = n; 21752 } 21753 21754 n = list_find_nr(l, i++, NULL); /* lnum */ 21755 if (n < 0) 21756 return FAIL; 21757 posp->lnum = n; 21758 21759 n = list_find_nr(l, i++, NULL); /* col */ 21760 if (n < 0) 21761 return FAIL; 21762 posp->col = n; 21763 21764 #ifdef FEAT_VIRTUALEDIT 21765 n = list_find_nr(l, i, NULL); /* off */ 21766 if (n < 0) 21767 posp->coladd = 0; 21768 else 21769 posp->coladd = n; 21770 #endif 21771 21772 if (curswantp != NULL) 21773 *curswantp = list_find_nr(l, i + 1, NULL); /* curswant */ 21774 21775 return OK; 21776 } 21777 21778 /* 21779 * Get the length of an environment variable name. 21780 * Advance "arg" to the first character after the name. 21781 * Return 0 for error. 21782 */ 21783 static int 21784 get_env_len(char_u **arg) 21785 { 21786 char_u *p; 21787 int len; 21788 21789 for (p = *arg; vim_isIDc(*p); ++p) 21790 ; 21791 if (p == *arg) /* no name found */ 21792 return 0; 21793 21794 len = (int)(p - *arg); 21795 *arg = p; 21796 return len; 21797 } 21798 21799 /* 21800 * Get the length of the name of a function or internal variable. 21801 * "arg" is advanced to the first non-white character after the name. 21802 * Return 0 if something is wrong. 21803 */ 21804 static int 21805 get_id_len(char_u **arg) 21806 { 21807 char_u *p; 21808 int len; 21809 21810 /* Find the end of the name. */ 21811 for (p = *arg; eval_isnamec(*p); ++p) 21812 { 21813 if (*p == ':') 21814 { 21815 /* "s:" is start of "s:var", but "n:" is not and can be used in 21816 * slice "[n:]". Also "xx:" is not a namespace. */ 21817 len = (int)(p - *arg); 21818 if ((len == 1 && vim_strchr(NAMESPACE_CHAR, **arg) == NULL) 21819 || len > 1) 21820 break; 21821 } 21822 } 21823 if (p == *arg) /* no name found */ 21824 return 0; 21825 21826 len = (int)(p - *arg); 21827 *arg = skipwhite(p); 21828 21829 return len; 21830 } 21831 21832 /* 21833 * Get the length of the name of a variable or function. 21834 * Only the name is recognized, does not handle ".key" or "[idx]". 21835 * "arg" is advanced to the first non-white character after the name. 21836 * Return -1 if curly braces expansion failed. 21837 * Return 0 if something else is wrong. 21838 * If the name contains 'magic' {}'s, expand them and return the 21839 * expanded name in an allocated string via 'alias' - caller must free. 21840 */ 21841 static int 21842 get_name_len( 21843 char_u **arg, 21844 char_u **alias, 21845 int evaluate, 21846 int verbose) 21847 { 21848 int len; 21849 char_u *p; 21850 char_u *expr_start; 21851 char_u *expr_end; 21852 21853 *alias = NULL; /* default to no alias */ 21854 21855 if ((*arg)[0] == K_SPECIAL && (*arg)[1] == KS_EXTRA 21856 && (*arg)[2] == (int)KE_SNR) 21857 { 21858 /* hard coded <SNR>, already translated */ 21859 *arg += 3; 21860 return get_id_len(arg) + 3; 21861 } 21862 len = eval_fname_script(*arg); 21863 if (len > 0) 21864 { 21865 /* literal "<SID>", "s:" or "<SNR>" */ 21866 *arg += len; 21867 } 21868 21869 /* 21870 * Find the end of the name; check for {} construction. 21871 */ 21872 p = find_name_end(*arg, &expr_start, &expr_end, 21873 len > 0 ? 0 : FNE_CHECK_START); 21874 if (expr_start != NULL) 21875 { 21876 char_u *temp_string; 21877 21878 if (!evaluate) 21879 { 21880 len += (int)(p - *arg); 21881 *arg = skipwhite(p); 21882 return len; 21883 } 21884 21885 /* 21886 * Include any <SID> etc in the expanded string: 21887 * Thus the -len here. 21888 */ 21889 temp_string = make_expanded_name(*arg - len, expr_start, expr_end, p); 21890 if (temp_string == NULL) 21891 return -1; 21892 *alias = temp_string; 21893 *arg = skipwhite(p); 21894 return (int)STRLEN(temp_string); 21895 } 21896 21897 len += get_id_len(arg); 21898 if (len == 0 && verbose) 21899 EMSG2(_(e_invexpr2), *arg); 21900 21901 return len; 21902 } 21903 21904 /* 21905 * Find the end of a variable or function name, taking care of magic braces. 21906 * If "expr_start" is not NULL then "expr_start" and "expr_end" are set to the 21907 * start and end of the first magic braces item. 21908 * "flags" can have FNE_INCL_BR and FNE_CHECK_START. 21909 * Return a pointer to just after the name. Equal to "arg" if there is no 21910 * valid name. 21911 */ 21912 static char_u * 21913 find_name_end( 21914 char_u *arg, 21915 char_u **expr_start, 21916 char_u **expr_end, 21917 int flags) 21918 { 21919 int mb_nest = 0; 21920 int br_nest = 0; 21921 char_u *p; 21922 int len; 21923 21924 if (expr_start != NULL) 21925 { 21926 *expr_start = NULL; 21927 *expr_end = NULL; 21928 } 21929 21930 /* Quick check for valid starting character. */ 21931 if ((flags & FNE_CHECK_START) && !eval_isnamec1(*arg) && *arg != '{') 21932 return arg; 21933 21934 for (p = arg; *p != NUL 21935 && (eval_isnamec(*p) 21936 || *p == '{' 21937 || ((flags & FNE_INCL_BR) && (*p == '[' || *p == '.')) 21938 || mb_nest != 0 21939 || br_nest != 0); mb_ptr_adv(p)) 21940 { 21941 if (*p == '\'') 21942 { 21943 /* skip over 'string' to avoid counting [ and ] inside it. */ 21944 for (p = p + 1; *p != NUL && *p != '\''; mb_ptr_adv(p)) 21945 ; 21946 if (*p == NUL) 21947 break; 21948 } 21949 else if (*p == '"') 21950 { 21951 /* skip over "str\"ing" to avoid counting [ and ] inside it. */ 21952 for (p = p + 1; *p != NUL && *p != '"'; mb_ptr_adv(p)) 21953 if (*p == '\\' && p[1] != NUL) 21954 ++p; 21955 if (*p == NUL) 21956 break; 21957 } 21958 else if (br_nest == 0 && mb_nest == 0 && *p == ':') 21959 { 21960 /* "s:" is start of "s:var", but "n:" is not and can be used in 21961 * slice "[n:]". Also "xx:" is not a namespace. But {ns}: is. */ 21962 len = (int)(p - arg); 21963 if ((len == 1 && vim_strchr(NAMESPACE_CHAR, *arg) == NULL) 21964 || (len > 1 && p[-1] != '}')) 21965 break; 21966 } 21967 21968 if (mb_nest == 0) 21969 { 21970 if (*p == '[') 21971 ++br_nest; 21972 else if (*p == ']') 21973 --br_nest; 21974 } 21975 21976 if (br_nest == 0) 21977 { 21978 if (*p == '{') 21979 { 21980 mb_nest++; 21981 if (expr_start != NULL && *expr_start == NULL) 21982 *expr_start = p; 21983 } 21984 else if (*p == '}') 21985 { 21986 mb_nest--; 21987 if (expr_start != NULL && mb_nest == 0 && *expr_end == NULL) 21988 *expr_end = p; 21989 } 21990 } 21991 } 21992 21993 return p; 21994 } 21995 21996 /* 21997 * Expands out the 'magic' {}'s in a variable/function name. 21998 * Note that this can call itself recursively, to deal with 21999 * constructs like foo{bar}{baz}{bam} 22000 * The four pointer arguments point to "foo{expre}ss{ion}bar" 22001 * "in_start" ^ 22002 * "expr_start" ^ 22003 * "expr_end" ^ 22004 * "in_end" ^ 22005 * 22006 * Returns a new allocated string, which the caller must free. 22007 * Returns NULL for failure. 22008 */ 22009 static char_u * 22010 make_expanded_name( 22011 char_u *in_start, 22012 char_u *expr_start, 22013 char_u *expr_end, 22014 char_u *in_end) 22015 { 22016 char_u c1; 22017 char_u *retval = NULL; 22018 char_u *temp_result; 22019 char_u *nextcmd = NULL; 22020 22021 if (expr_end == NULL || in_end == NULL) 22022 return NULL; 22023 *expr_start = NUL; 22024 *expr_end = NUL; 22025 c1 = *in_end; 22026 *in_end = NUL; 22027 22028 temp_result = eval_to_string(expr_start + 1, &nextcmd, FALSE); 22029 if (temp_result != NULL && nextcmd == NULL) 22030 { 22031 retval = alloc((unsigned)(STRLEN(temp_result) + (expr_start - in_start) 22032 + (in_end - expr_end) + 1)); 22033 if (retval != NULL) 22034 { 22035 STRCPY(retval, in_start); 22036 STRCAT(retval, temp_result); 22037 STRCAT(retval, expr_end + 1); 22038 } 22039 } 22040 vim_free(temp_result); 22041 22042 *in_end = c1; /* put char back for error messages */ 22043 *expr_start = '{'; 22044 *expr_end = '}'; 22045 22046 if (retval != NULL) 22047 { 22048 temp_result = find_name_end(retval, &expr_start, &expr_end, 0); 22049 if (expr_start != NULL) 22050 { 22051 /* Further expansion! */ 22052 temp_result = make_expanded_name(retval, expr_start, 22053 expr_end, temp_result); 22054 vim_free(retval); 22055 retval = temp_result; 22056 } 22057 } 22058 22059 return retval; 22060 } 22061 22062 /* 22063 * Return TRUE if character "c" can be used in a variable or function name. 22064 * Does not include '{' or '}' for magic braces. 22065 */ 22066 static int 22067 eval_isnamec(int c) 22068 { 22069 return (ASCII_ISALNUM(c) || c == '_' || c == ':' || c == AUTOLOAD_CHAR); 22070 } 22071 22072 /* 22073 * Return TRUE if character "c" can be used as the first character in a 22074 * variable or function name (excluding '{' and '}'). 22075 */ 22076 static int 22077 eval_isnamec1(int c) 22078 { 22079 return (ASCII_ISALPHA(c) || c == '_'); 22080 } 22081 22082 /* 22083 * Set number v: variable to "val". 22084 */ 22085 void 22086 set_vim_var_nr(int idx, long val) 22087 { 22088 vimvars[idx].vv_nr = val; 22089 } 22090 22091 /* 22092 * Get number v: variable value. 22093 */ 22094 long 22095 get_vim_var_nr(int idx) 22096 { 22097 return vimvars[idx].vv_nr; 22098 } 22099 22100 /* 22101 * Get string v: variable value. Uses a static buffer, can only be used once. 22102 */ 22103 char_u * 22104 get_vim_var_str(int idx) 22105 { 22106 return get_tv_string(&vimvars[idx].vv_tv); 22107 } 22108 22109 /* 22110 * Get List v: variable value. Caller must take care of reference count when 22111 * needed. 22112 */ 22113 list_T * 22114 get_vim_var_list(int idx) 22115 { 22116 return vimvars[idx].vv_list; 22117 } 22118 22119 /* 22120 * Set v:char to character "c". 22121 */ 22122 void 22123 set_vim_var_char(int c) 22124 { 22125 char_u buf[MB_MAXBYTES + 1]; 22126 22127 #ifdef FEAT_MBYTE 22128 if (has_mbyte) 22129 buf[(*mb_char2bytes)(c, buf)] = NUL; 22130 else 22131 #endif 22132 { 22133 buf[0] = c; 22134 buf[1] = NUL; 22135 } 22136 set_vim_var_string(VV_CHAR, buf, -1); 22137 } 22138 22139 /* 22140 * Set v:count to "count" and v:count1 to "count1". 22141 * When "set_prevcount" is TRUE first set v:prevcount from v:count. 22142 */ 22143 void 22144 set_vcount( 22145 long count, 22146 long count1, 22147 int set_prevcount) 22148 { 22149 if (set_prevcount) 22150 vimvars[VV_PREVCOUNT].vv_nr = vimvars[VV_COUNT].vv_nr; 22151 vimvars[VV_COUNT].vv_nr = count; 22152 vimvars[VV_COUNT1].vv_nr = count1; 22153 } 22154 22155 /* 22156 * Set string v: variable to a copy of "val". 22157 */ 22158 void 22159 set_vim_var_string( 22160 int idx, 22161 char_u *val, 22162 int len) /* length of "val" to use or -1 (whole string) */ 22163 { 22164 clear_tv(&vimvars[idx].vv_di.di_tv); 22165 vimvars[idx].vv_type = VAR_STRING; 22166 if (val == NULL) 22167 vimvars[idx].vv_str = NULL; 22168 else if (len == -1) 22169 vimvars[idx].vv_str = vim_strsave(val); 22170 else 22171 vimvars[idx].vv_str = vim_strnsave(val, len); 22172 } 22173 22174 /* 22175 * Set List v: variable to "val". 22176 */ 22177 void 22178 set_vim_var_list(int idx, list_T *val) 22179 { 22180 clear_tv(&vimvars[idx].vv_di.di_tv); 22181 vimvars[idx].vv_type = VAR_LIST; 22182 vimvars[idx].vv_list = val; 22183 if (val != NULL) 22184 ++val->lv_refcount; 22185 } 22186 22187 /* 22188 * Set Dictionary v: variable to "val". 22189 */ 22190 void 22191 set_vim_var_dict(int idx, dict_T *val) 22192 { 22193 int todo; 22194 hashitem_T *hi; 22195 22196 clear_tv(&vimvars[idx].vv_di.di_tv); 22197 vimvars[idx].vv_type = VAR_DICT; 22198 vimvars[idx].vv_dict = val; 22199 if (val != NULL) 22200 { 22201 ++val->dv_refcount; 22202 22203 /* Set readonly */ 22204 todo = (int)val->dv_hashtab.ht_used; 22205 for (hi = val->dv_hashtab.ht_array; todo > 0 ; ++hi) 22206 { 22207 if (HASHITEM_EMPTY(hi)) 22208 continue; 22209 --todo; 22210 HI2DI(hi)->di_flags = DI_FLAGS_RO | DI_FLAGS_FIX; 22211 } 22212 } 22213 } 22214 22215 /* 22216 * Set v:register if needed. 22217 */ 22218 void 22219 set_reg_var(int c) 22220 { 22221 char_u regname; 22222 22223 if (c == 0 || c == ' ') 22224 regname = '"'; 22225 else 22226 regname = c; 22227 /* Avoid free/alloc when the value is already right. */ 22228 if (vimvars[VV_REG].vv_str == NULL || vimvars[VV_REG].vv_str[0] != c) 22229 set_vim_var_string(VV_REG, ®name, 1); 22230 } 22231 22232 /* 22233 * Get or set v:exception. If "oldval" == NULL, return the current value. 22234 * Otherwise, restore the value to "oldval" and return NULL. 22235 * Must always be called in pairs to save and restore v:exception! Does not 22236 * take care of memory allocations. 22237 */ 22238 char_u * 22239 v_exception(char_u *oldval) 22240 { 22241 if (oldval == NULL) 22242 return vimvars[VV_EXCEPTION].vv_str; 22243 22244 vimvars[VV_EXCEPTION].vv_str = oldval; 22245 return NULL; 22246 } 22247 22248 /* 22249 * Get or set v:throwpoint. If "oldval" == NULL, return the current value. 22250 * Otherwise, restore the value to "oldval" and return NULL. 22251 * Must always be called in pairs to save and restore v:throwpoint! Does not 22252 * take care of memory allocations. 22253 */ 22254 char_u * 22255 v_throwpoint(char_u *oldval) 22256 { 22257 if (oldval == NULL) 22258 return vimvars[VV_THROWPOINT].vv_str; 22259 22260 vimvars[VV_THROWPOINT].vv_str = oldval; 22261 return NULL; 22262 } 22263 22264 #if defined(FEAT_AUTOCMD) || defined(PROTO) 22265 /* 22266 * Set v:cmdarg. 22267 * If "eap" != NULL, use "eap" to generate the value and return the old value. 22268 * If "oldarg" != NULL, restore the value to "oldarg" and return NULL. 22269 * Must always be called in pairs! 22270 */ 22271 char_u * 22272 set_cmdarg(exarg_T *eap, char_u *oldarg) 22273 { 22274 char_u *oldval; 22275 char_u *newval; 22276 unsigned len; 22277 22278 oldval = vimvars[VV_CMDARG].vv_str; 22279 if (eap == NULL) 22280 { 22281 vim_free(oldval); 22282 vimvars[VV_CMDARG].vv_str = oldarg; 22283 return NULL; 22284 } 22285 22286 if (eap->force_bin == FORCE_BIN) 22287 len = 6; 22288 else if (eap->force_bin == FORCE_NOBIN) 22289 len = 8; 22290 else 22291 len = 0; 22292 22293 if (eap->read_edit) 22294 len += 7; 22295 22296 if (eap->force_ff != 0) 22297 len += (unsigned)STRLEN(eap->cmd + eap->force_ff) + 6; 22298 # ifdef FEAT_MBYTE 22299 if (eap->force_enc != 0) 22300 len += (unsigned)STRLEN(eap->cmd + eap->force_enc) + 7; 22301 if (eap->bad_char != 0) 22302 len += 7 + 4; /* " ++bad=" + "keep" or "drop" */ 22303 # endif 22304 22305 newval = alloc(len + 1); 22306 if (newval == NULL) 22307 return NULL; 22308 22309 if (eap->force_bin == FORCE_BIN) 22310 sprintf((char *)newval, " ++bin"); 22311 else if (eap->force_bin == FORCE_NOBIN) 22312 sprintf((char *)newval, " ++nobin"); 22313 else 22314 *newval = NUL; 22315 22316 if (eap->read_edit) 22317 STRCAT(newval, " ++edit"); 22318 22319 if (eap->force_ff != 0) 22320 sprintf((char *)newval + STRLEN(newval), " ++ff=%s", 22321 eap->cmd + eap->force_ff); 22322 # ifdef FEAT_MBYTE 22323 if (eap->force_enc != 0) 22324 sprintf((char *)newval + STRLEN(newval), " ++enc=%s", 22325 eap->cmd + eap->force_enc); 22326 if (eap->bad_char == BAD_KEEP) 22327 STRCPY(newval + STRLEN(newval), " ++bad=keep"); 22328 else if (eap->bad_char == BAD_DROP) 22329 STRCPY(newval + STRLEN(newval), " ++bad=drop"); 22330 else if (eap->bad_char != 0) 22331 sprintf((char *)newval + STRLEN(newval), " ++bad=%c", eap->bad_char); 22332 # endif 22333 vimvars[VV_CMDARG].vv_str = newval; 22334 return oldval; 22335 } 22336 #endif 22337 22338 /* 22339 * Get the value of internal variable "name". 22340 * Return OK or FAIL. 22341 */ 22342 static int 22343 get_var_tv( 22344 char_u *name, 22345 int len, /* length of "name" */ 22346 typval_T *rettv, /* NULL when only checking existence */ 22347 dictitem_T **dip, /* non-NULL when typval's dict item is needed */ 22348 int verbose, /* may give error message */ 22349 int no_autoload) /* do not use script autoloading */ 22350 { 22351 int ret = OK; 22352 typval_T *tv = NULL; 22353 typval_T atv; 22354 dictitem_T *v; 22355 int cc; 22356 22357 /* truncate the name, so that we can use strcmp() */ 22358 cc = name[len]; 22359 name[len] = NUL; 22360 22361 /* 22362 * Check for "b:changedtick". 22363 */ 22364 if (STRCMP(name, "b:changedtick") == 0) 22365 { 22366 atv.v_type = VAR_NUMBER; 22367 atv.vval.v_number = curbuf->b_changedtick; 22368 tv = &atv; 22369 } 22370 22371 /* 22372 * Check for user-defined variables. 22373 */ 22374 else 22375 { 22376 v = find_var(name, NULL, no_autoload); 22377 if (v != NULL) 22378 { 22379 tv = &v->di_tv; 22380 if (dip != NULL) 22381 *dip = v; 22382 } 22383 } 22384 22385 if (tv == NULL) 22386 { 22387 if (rettv != NULL && verbose) 22388 EMSG2(_(e_undefvar), name); 22389 ret = FAIL; 22390 } 22391 else if (rettv != NULL) 22392 copy_tv(tv, rettv); 22393 22394 name[len] = cc; 22395 22396 return ret; 22397 } 22398 22399 /* 22400 * Handle expr[expr], expr[expr:expr] subscript and .name lookup. 22401 * Also handle function call with Funcref variable: func(expr) 22402 * Can all be combined: dict.func(expr)[idx]['func'](expr) 22403 */ 22404 static int 22405 handle_subscript( 22406 char_u **arg, 22407 typval_T *rettv, 22408 int evaluate, /* do more than finding the end */ 22409 int verbose) /* give error messages */ 22410 { 22411 int ret = OK; 22412 dict_T *selfdict = NULL; 22413 char_u *s; 22414 int len; 22415 typval_T functv; 22416 22417 while (ret == OK 22418 && (**arg == '[' 22419 || (**arg == '.' && rettv->v_type == VAR_DICT) 22420 || (**arg == '(' && (!evaluate || rettv->v_type == VAR_FUNC 22421 || rettv->v_type == VAR_PARTIAL))) 22422 && !vim_iswhite(*(*arg - 1))) 22423 { 22424 if (**arg == '(') 22425 { 22426 partial_T *pt = NULL; 22427 22428 /* need to copy the funcref so that we can clear rettv */ 22429 if (evaluate) 22430 { 22431 functv = *rettv; 22432 rettv->v_type = VAR_UNKNOWN; 22433 22434 /* Invoke the function. Recursive! */ 22435 if (functv.v_type == VAR_PARTIAL) 22436 { 22437 pt = functv.vval.v_partial; 22438 s = pt->pt_name; 22439 } 22440 else 22441 s = functv.vval.v_string; 22442 } 22443 else 22444 s = (char_u *)""; 22445 ret = get_func_tv(s, (int)STRLEN(s), rettv, arg, 22446 curwin->w_cursor.lnum, curwin->w_cursor.lnum, 22447 &len, evaluate, pt, selfdict); 22448 22449 /* Clear the funcref afterwards, so that deleting it while 22450 * evaluating the arguments is possible (see test55). */ 22451 if (evaluate) 22452 clear_tv(&functv); 22453 22454 /* Stop the expression evaluation when immediately aborting on 22455 * error, or when an interrupt occurred or an exception was thrown 22456 * but not caught. */ 22457 if (aborting()) 22458 { 22459 if (ret == OK) 22460 clear_tv(rettv); 22461 ret = FAIL; 22462 } 22463 dict_unref(selfdict); 22464 selfdict = NULL; 22465 } 22466 else /* **arg == '[' || **arg == '.' */ 22467 { 22468 dict_unref(selfdict); 22469 if (rettv->v_type == VAR_DICT) 22470 { 22471 selfdict = rettv->vval.v_dict; 22472 if (selfdict != NULL) 22473 ++selfdict->dv_refcount; 22474 } 22475 else 22476 selfdict = NULL; 22477 if (eval_index(arg, rettv, evaluate, verbose) == FAIL) 22478 { 22479 clear_tv(rettv); 22480 ret = FAIL; 22481 } 22482 } 22483 } 22484 22485 /* Turn "dict.Func" into a partial for "Func" bound to "dict". 22486 * Don't do this when "Func" is already a partial that was bound 22487 * explicitly (pt_auto is FALSE). */ 22488 if (selfdict != NULL 22489 && (rettv->v_type == VAR_FUNC 22490 || (rettv->v_type == VAR_PARTIAL 22491 && (rettv->vval.v_partial->pt_auto 22492 || rettv->vval.v_partial->pt_dict == NULL)))) 22493 { 22494 char_u *fname = rettv->v_type == VAR_FUNC ? rettv->vval.v_string 22495 : rettv->vval.v_partial->pt_name; 22496 char_u *tofree = NULL; 22497 ufunc_T *fp; 22498 char_u fname_buf[FLEN_FIXED + 1]; 22499 int error; 22500 22501 /* Translate "s:func" to the stored function name. */ 22502 fname = fname_trans_sid(fname, fname_buf, &tofree, &error); 22503 fp = find_func(fname); 22504 vim_free(tofree); 22505 22506 if (fp != NULL && (fp->uf_flags & FC_DICT)) 22507 { 22508 partial_T *pt = (partial_T *)alloc_clear(sizeof(partial_T)); 22509 22510 if (pt != NULL) 22511 { 22512 pt->pt_refcount = 1; 22513 pt->pt_dict = selfdict; 22514 pt->pt_auto = TRUE; 22515 selfdict = NULL; 22516 if (rettv->v_type == VAR_FUNC) 22517 { 22518 /* Just a function: Take over the function name and use 22519 * selfdict. */ 22520 pt->pt_name = rettv->vval.v_string; 22521 } 22522 else 22523 { 22524 partial_T *ret_pt = rettv->vval.v_partial; 22525 int i; 22526 22527 /* Partial: copy the function name, use selfdict and copy 22528 * args. Can't take over name or args, the partial might 22529 * be referenced elsewhere. */ 22530 pt->pt_name = vim_strsave(ret_pt->pt_name); 22531 func_ref(pt->pt_name); 22532 if (ret_pt->pt_argc > 0) 22533 { 22534 pt->pt_argv = (typval_T *)alloc( 22535 sizeof(typval_T) * ret_pt->pt_argc); 22536 if (pt->pt_argv == NULL) 22537 /* out of memory: drop the arguments */ 22538 pt->pt_argc = 0; 22539 else 22540 { 22541 pt->pt_argc = ret_pt->pt_argc; 22542 for (i = 0; i < pt->pt_argc; i++) 22543 copy_tv(&ret_pt->pt_argv[i], &pt->pt_argv[i]); 22544 } 22545 } 22546 partial_unref(ret_pt); 22547 } 22548 rettv->v_type = VAR_PARTIAL; 22549 rettv->vval.v_partial = pt; 22550 } 22551 } 22552 } 22553 22554 dict_unref(selfdict); 22555 return ret; 22556 } 22557 22558 /* 22559 * Allocate memory for a variable type-value, and make it empty (0 or NULL 22560 * value). 22561 */ 22562 typval_T * 22563 alloc_tv(void) 22564 { 22565 return (typval_T *)alloc_clear((unsigned)sizeof(typval_T)); 22566 } 22567 22568 /* 22569 * Allocate memory for a variable type-value, and assign a string to it. 22570 * The string "s" must have been allocated, it is consumed. 22571 * Return NULL for out of memory, the variable otherwise. 22572 */ 22573 static typval_T * 22574 alloc_string_tv(char_u *s) 22575 { 22576 typval_T *rettv; 22577 22578 rettv = alloc_tv(); 22579 if (rettv != NULL) 22580 { 22581 rettv->v_type = VAR_STRING; 22582 rettv->vval.v_string = s; 22583 } 22584 else 22585 vim_free(s); 22586 return rettv; 22587 } 22588 22589 /* 22590 * Free the memory for a variable type-value. 22591 */ 22592 void 22593 free_tv(typval_T *varp) 22594 { 22595 if (varp != NULL) 22596 { 22597 switch (varp->v_type) 22598 { 22599 case VAR_FUNC: 22600 func_unref(varp->vval.v_string); 22601 /*FALLTHROUGH*/ 22602 case VAR_STRING: 22603 vim_free(varp->vval.v_string); 22604 break; 22605 case VAR_PARTIAL: 22606 partial_unref(varp->vval.v_partial); 22607 break; 22608 case VAR_LIST: 22609 list_unref(varp->vval.v_list); 22610 break; 22611 case VAR_DICT: 22612 dict_unref(varp->vval.v_dict); 22613 break; 22614 case VAR_JOB: 22615 #ifdef FEAT_JOB_CHANNEL 22616 job_unref(varp->vval.v_job); 22617 break; 22618 #endif 22619 case VAR_CHANNEL: 22620 #ifdef FEAT_JOB_CHANNEL 22621 channel_unref(varp->vval.v_channel); 22622 break; 22623 #endif 22624 case VAR_NUMBER: 22625 case VAR_FLOAT: 22626 case VAR_UNKNOWN: 22627 case VAR_SPECIAL: 22628 break; 22629 } 22630 vim_free(varp); 22631 } 22632 } 22633 22634 /* 22635 * Free the memory for a variable value and set the value to NULL or 0. 22636 */ 22637 void 22638 clear_tv(typval_T *varp) 22639 { 22640 if (varp != NULL) 22641 { 22642 switch (varp->v_type) 22643 { 22644 case VAR_FUNC: 22645 func_unref(varp->vval.v_string); 22646 /*FALLTHROUGH*/ 22647 case VAR_STRING: 22648 vim_free(varp->vval.v_string); 22649 varp->vval.v_string = NULL; 22650 break; 22651 case VAR_PARTIAL: 22652 partial_unref(varp->vval.v_partial); 22653 varp->vval.v_partial = NULL; 22654 break; 22655 case VAR_LIST: 22656 list_unref(varp->vval.v_list); 22657 varp->vval.v_list = NULL; 22658 break; 22659 case VAR_DICT: 22660 dict_unref(varp->vval.v_dict); 22661 varp->vval.v_dict = NULL; 22662 break; 22663 case VAR_NUMBER: 22664 case VAR_SPECIAL: 22665 varp->vval.v_number = 0; 22666 break; 22667 case VAR_FLOAT: 22668 #ifdef FEAT_FLOAT 22669 varp->vval.v_float = 0.0; 22670 break; 22671 #endif 22672 case VAR_JOB: 22673 #ifdef FEAT_JOB_CHANNEL 22674 job_unref(varp->vval.v_job); 22675 varp->vval.v_job = NULL; 22676 #endif 22677 break; 22678 case VAR_CHANNEL: 22679 #ifdef FEAT_JOB_CHANNEL 22680 channel_unref(varp->vval.v_channel); 22681 varp->vval.v_channel = NULL; 22682 #endif 22683 case VAR_UNKNOWN: 22684 break; 22685 } 22686 varp->v_lock = 0; 22687 } 22688 } 22689 22690 /* 22691 * Set the value of a variable to NULL without freeing items. 22692 */ 22693 static void 22694 init_tv(typval_T *varp) 22695 { 22696 if (varp != NULL) 22697 vim_memset(varp, 0, sizeof(typval_T)); 22698 } 22699 22700 /* 22701 * Get the number value of a variable. 22702 * If it is a String variable, uses vim_str2nr(). 22703 * For incompatible types, return 0. 22704 * get_tv_number_chk() is similar to get_tv_number(), but informs the 22705 * caller of incompatible types: it sets *denote to TRUE if "denote" 22706 * is not NULL or returns -1 otherwise. 22707 */ 22708 long 22709 get_tv_number(typval_T *varp) 22710 { 22711 int error = FALSE; 22712 22713 return get_tv_number_chk(varp, &error); /* return 0L on error */ 22714 } 22715 22716 long 22717 get_tv_number_chk(typval_T *varp, int *denote) 22718 { 22719 long n = 0L; 22720 22721 switch (varp->v_type) 22722 { 22723 case VAR_NUMBER: 22724 return (long)(varp->vval.v_number); 22725 case VAR_FLOAT: 22726 #ifdef FEAT_FLOAT 22727 EMSG(_("E805: Using a Float as a Number")); 22728 break; 22729 #endif 22730 case VAR_FUNC: 22731 case VAR_PARTIAL: 22732 EMSG(_("E703: Using a Funcref as a Number")); 22733 break; 22734 case VAR_STRING: 22735 if (varp->vval.v_string != NULL) 22736 vim_str2nr(varp->vval.v_string, NULL, NULL, 22737 STR2NR_ALL, &n, NULL, 0); 22738 return n; 22739 case VAR_LIST: 22740 EMSG(_("E745: Using a List as a Number")); 22741 break; 22742 case VAR_DICT: 22743 EMSG(_("E728: Using a Dictionary as a Number")); 22744 break; 22745 case VAR_SPECIAL: 22746 return varp->vval.v_number == VVAL_TRUE ? 1 : 0; 22747 break; 22748 case VAR_JOB: 22749 #ifdef FEAT_JOB_CHANNEL 22750 EMSG(_("E910: Using a Job as a Number")); 22751 break; 22752 #endif 22753 case VAR_CHANNEL: 22754 #ifdef FEAT_JOB_CHANNEL 22755 EMSG(_("E913: Using a Channel as a Number")); 22756 break; 22757 #endif 22758 case VAR_UNKNOWN: 22759 EMSG2(_(e_intern2), "get_tv_number(UNKNOWN)"); 22760 break; 22761 } 22762 if (denote == NULL) /* useful for values that must be unsigned */ 22763 n = -1; 22764 else 22765 *denote = TRUE; 22766 return n; 22767 } 22768 22769 #ifdef FEAT_FLOAT 22770 static float_T 22771 get_tv_float(typval_T *varp) 22772 { 22773 switch (varp->v_type) 22774 { 22775 case VAR_NUMBER: 22776 return (float_T)(varp->vval.v_number); 22777 case VAR_FLOAT: 22778 return varp->vval.v_float; 22779 case VAR_FUNC: 22780 case VAR_PARTIAL: 22781 EMSG(_("E891: Using a Funcref as a Float")); 22782 break; 22783 case VAR_STRING: 22784 EMSG(_("E892: Using a String as a Float")); 22785 break; 22786 case VAR_LIST: 22787 EMSG(_("E893: Using a List as a Float")); 22788 break; 22789 case VAR_DICT: 22790 EMSG(_("E894: Using a Dictionary as a Float")); 22791 break; 22792 case VAR_SPECIAL: 22793 EMSG(_("E907: Using a special value as a Float")); 22794 break; 22795 case VAR_JOB: 22796 # ifdef FEAT_JOB_CHANNEL 22797 EMSG(_("E911: Using a Job as a Float")); 22798 break; 22799 # endif 22800 case VAR_CHANNEL: 22801 # ifdef FEAT_JOB_CHANNEL 22802 EMSG(_("E914: Using a Channel as a Float")); 22803 break; 22804 # endif 22805 case VAR_UNKNOWN: 22806 EMSG2(_(e_intern2), "get_tv_float(UNKNOWN)"); 22807 break; 22808 } 22809 return 0; 22810 } 22811 #endif 22812 22813 /* 22814 * Get the lnum from the first argument. 22815 * Also accepts ".", "$", etc., but that only works for the current buffer. 22816 * Returns -1 on error. 22817 */ 22818 static linenr_T 22819 get_tv_lnum(typval_T *argvars) 22820 { 22821 typval_T rettv; 22822 linenr_T lnum; 22823 22824 lnum = get_tv_number_chk(&argvars[0], NULL); 22825 if (lnum == 0) /* no valid number, try using line() */ 22826 { 22827 rettv.v_type = VAR_NUMBER; 22828 f_line(argvars, &rettv); 22829 lnum = rettv.vval.v_number; 22830 clear_tv(&rettv); 22831 } 22832 return lnum; 22833 } 22834 22835 /* 22836 * Get the lnum from the first argument. 22837 * Also accepts "$", then "buf" is used. 22838 * Returns 0 on error. 22839 */ 22840 static linenr_T 22841 get_tv_lnum_buf(typval_T *argvars, buf_T *buf) 22842 { 22843 if (argvars[0].v_type == VAR_STRING 22844 && argvars[0].vval.v_string != NULL 22845 && argvars[0].vval.v_string[0] == '$' 22846 && buf != NULL) 22847 return buf->b_ml.ml_line_count; 22848 return get_tv_number_chk(&argvars[0], NULL); 22849 } 22850 22851 /* 22852 * Get the string value of a variable. 22853 * If it is a Number variable, the number is converted into a string. 22854 * get_tv_string() uses a single, static buffer. YOU CAN ONLY USE IT ONCE! 22855 * get_tv_string_buf() uses a given buffer. 22856 * If the String variable has never been set, return an empty string. 22857 * Never returns NULL; 22858 * get_tv_string_chk() and get_tv_string_buf_chk() are similar, but return 22859 * NULL on error. 22860 */ 22861 char_u * 22862 get_tv_string(typval_T *varp) 22863 { 22864 static char_u mybuf[NUMBUFLEN]; 22865 22866 return get_tv_string_buf(varp, mybuf); 22867 } 22868 22869 char_u * 22870 get_tv_string_buf(typval_T *varp, char_u *buf) 22871 { 22872 char_u *res = get_tv_string_buf_chk(varp, buf); 22873 22874 return res != NULL ? res : (char_u *)""; 22875 } 22876 22877 /* 22878 * Careful: This uses a single, static buffer. YOU CAN ONLY USE IT ONCE! 22879 */ 22880 char_u * 22881 get_tv_string_chk(typval_T *varp) 22882 { 22883 static char_u mybuf[NUMBUFLEN]; 22884 22885 return get_tv_string_buf_chk(varp, mybuf); 22886 } 22887 22888 char_u * 22889 get_tv_string_buf_chk(typval_T *varp, char_u *buf) 22890 { 22891 switch (varp->v_type) 22892 { 22893 case VAR_NUMBER: 22894 sprintf((char *)buf, "%ld", (long)varp->vval.v_number); 22895 return buf; 22896 case VAR_FUNC: 22897 case VAR_PARTIAL: 22898 EMSG(_("E729: using Funcref as a String")); 22899 break; 22900 case VAR_LIST: 22901 EMSG(_("E730: using List as a String")); 22902 break; 22903 case VAR_DICT: 22904 EMSG(_("E731: using Dictionary as a String")); 22905 break; 22906 case VAR_FLOAT: 22907 #ifdef FEAT_FLOAT 22908 EMSG(_(e_float_as_string)); 22909 break; 22910 #endif 22911 case VAR_STRING: 22912 if (varp->vval.v_string != NULL) 22913 return varp->vval.v_string; 22914 return (char_u *)""; 22915 case VAR_SPECIAL: 22916 STRCPY(buf, get_var_special_name(varp->vval.v_number)); 22917 return buf; 22918 case VAR_JOB: 22919 #ifdef FEAT_JOB_CHANNEL 22920 { 22921 job_T *job = varp->vval.v_job; 22922 char *status; 22923 22924 if (job == NULL) 22925 return (char_u *)"no process"; 22926 status = job->jv_status == JOB_FAILED ? "fail" 22927 : job->jv_status == JOB_ENDED ? "dead" 22928 : "run"; 22929 # ifdef UNIX 22930 vim_snprintf((char *)buf, NUMBUFLEN, 22931 "process %ld %s", (long)job->jv_pid, status); 22932 # elif defined(WIN32) 22933 vim_snprintf((char *)buf, NUMBUFLEN, 22934 "process %ld %s", 22935 (long)job->jv_proc_info.dwProcessId, 22936 status); 22937 # else 22938 /* fall-back */ 22939 vim_snprintf((char *)buf, NUMBUFLEN, "process ? %s", status); 22940 # endif 22941 return buf; 22942 } 22943 #endif 22944 break; 22945 case VAR_CHANNEL: 22946 #ifdef FEAT_JOB_CHANNEL 22947 { 22948 channel_T *channel = varp->vval.v_channel; 22949 char *status = channel_status(channel); 22950 22951 if (channel == NULL) 22952 vim_snprintf((char *)buf, NUMBUFLEN, "channel %s", status); 22953 else 22954 vim_snprintf((char *)buf, NUMBUFLEN, 22955 "channel %d %s", channel->ch_id, status); 22956 return buf; 22957 } 22958 #endif 22959 break; 22960 case VAR_UNKNOWN: 22961 EMSG(_("E908: using an invalid value as a String")); 22962 break; 22963 } 22964 return NULL; 22965 } 22966 22967 /* 22968 * Find variable "name" in the list of variables. 22969 * Return a pointer to it if found, NULL if not found. 22970 * Careful: "a:0" variables don't have a name. 22971 * When "htp" is not NULL we are writing to the variable, set "htp" to the 22972 * hashtab_T used. 22973 */ 22974 static dictitem_T * 22975 find_var(char_u *name, hashtab_T **htp, int no_autoload) 22976 { 22977 char_u *varname; 22978 hashtab_T *ht; 22979 22980 ht = find_var_ht(name, &varname); 22981 if (htp != NULL) 22982 *htp = ht; 22983 if (ht == NULL) 22984 return NULL; 22985 return find_var_in_ht(ht, *name, varname, no_autoload || htp != NULL); 22986 } 22987 22988 /* 22989 * Find variable "varname" in hashtab "ht" with name "htname". 22990 * Returns NULL if not found. 22991 */ 22992 static dictitem_T * 22993 find_var_in_ht( 22994 hashtab_T *ht, 22995 int htname, 22996 char_u *varname, 22997 int no_autoload) 22998 { 22999 hashitem_T *hi; 23000 23001 if (*varname == NUL) 23002 { 23003 /* Must be something like "s:", otherwise "ht" would be NULL. */ 23004 switch (htname) 23005 { 23006 case 's': return &SCRIPT_SV(current_SID)->sv_var; 23007 case 'g': return &globvars_var; 23008 case 'v': return &vimvars_var; 23009 case 'b': return &curbuf->b_bufvar; 23010 case 'w': return &curwin->w_winvar; 23011 #ifdef FEAT_WINDOWS 23012 case 't': return &curtab->tp_winvar; 23013 #endif 23014 case 'l': return current_funccal == NULL 23015 ? NULL : ¤t_funccal->l_vars_var; 23016 case 'a': return current_funccal == NULL 23017 ? NULL : ¤t_funccal->l_avars_var; 23018 } 23019 return NULL; 23020 } 23021 23022 hi = hash_find(ht, varname); 23023 if (HASHITEM_EMPTY(hi)) 23024 { 23025 /* For global variables we may try auto-loading the script. If it 23026 * worked find the variable again. Don't auto-load a script if it was 23027 * loaded already, otherwise it would be loaded every time when 23028 * checking if a function name is a Funcref variable. */ 23029 if (ht == &globvarht && !no_autoload) 23030 { 23031 /* Note: script_autoload() may make "hi" invalid. It must either 23032 * be obtained again or not used. */ 23033 if (!script_autoload(varname, FALSE) || aborting()) 23034 return NULL; 23035 hi = hash_find(ht, varname); 23036 } 23037 if (HASHITEM_EMPTY(hi)) 23038 return NULL; 23039 } 23040 return HI2DI(hi); 23041 } 23042 23043 /* 23044 * Find the hashtab used for a variable name. 23045 * Return NULL if the name is not valid. 23046 * Set "varname" to the start of name without ':'. 23047 */ 23048 static hashtab_T * 23049 find_var_ht(char_u *name, char_u **varname) 23050 { 23051 hashitem_T *hi; 23052 23053 if (name[0] == NUL) 23054 return NULL; 23055 if (name[1] != ':') 23056 { 23057 /* The name must not start with a colon or #. */ 23058 if (name[0] == ':' || name[0] == AUTOLOAD_CHAR) 23059 return NULL; 23060 *varname = name; 23061 23062 /* "version" is "v:version" in all scopes */ 23063 hi = hash_find(&compat_hashtab, name); 23064 if (!HASHITEM_EMPTY(hi)) 23065 return &compat_hashtab; 23066 23067 if (current_funccal == NULL) 23068 return &globvarht; /* global variable */ 23069 return &get_funccal()->l_vars.dv_hashtab; /* l: variable */ 23070 } 23071 *varname = name + 2; 23072 if (*name == 'g') /* global variable */ 23073 return &globvarht; 23074 /* There must be no ':' or '#' in the rest of the name, unless g: is used 23075 */ 23076 if (vim_strchr(name + 2, ':') != NULL 23077 || vim_strchr(name + 2, AUTOLOAD_CHAR) != NULL) 23078 return NULL; 23079 if (*name == 'b') /* buffer variable */ 23080 return &curbuf->b_vars->dv_hashtab; 23081 if (*name == 'w') /* window variable */ 23082 return &curwin->w_vars->dv_hashtab; 23083 #ifdef FEAT_WINDOWS 23084 if (*name == 't') /* tab page variable */ 23085 return &curtab->tp_vars->dv_hashtab; 23086 #endif 23087 if (*name == 'v') /* v: variable */ 23088 return &vimvarht; 23089 if (*name == 'a' && current_funccal != NULL) /* function argument */ 23090 return &get_funccal()->l_avars.dv_hashtab; 23091 if (*name == 'l' && current_funccal != NULL) /* local function variable */ 23092 return &get_funccal()->l_vars.dv_hashtab; 23093 if (*name == 's' /* script variable */ 23094 && current_SID > 0 && current_SID <= ga_scripts.ga_len) 23095 return &SCRIPT_VARS(current_SID); 23096 return NULL; 23097 } 23098 23099 /* 23100 * Get function call environment based on bactrace debug level 23101 */ 23102 static funccall_T * 23103 get_funccal(void) 23104 { 23105 int i; 23106 funccall_T *funccal; 23107 funccall_T *temp_funccal; 23108 23109 funccal = current_funccal; 23110 if (debug_backtrace_level > 0) 23111 { 23112 for (i = 0; i < debug_backtrace_level; i++) 23113 { 23114 temp_funccal = funccal->caller; 23115 if (temp_funccal) 23116 funccal = temp_funccal; 23117 else 23118 /* backtrace level overflow. reset to max */ 23119 debug_backtrace_level = i; 23120 } 23121 } 23122 return funccal; 23123 } 23124 23125 /* 23126 * Get the string value of a (global/local) variable. 23127 * Note: see get_tv_string() for how long the pointer remains valid. 23128 * Returns NULL when it doesn't exist. 23129 */ 23130 char_u * 23131 get_var_value(char_u *name) 23132 { 23133 dictitem_T *v; 23134 23135 v = find_var(name, NULL, FALSE); 23136 if (v == NULL) 23137 return NULL; 23138 return get_tv_string(&v->di_tv); 23139 } 23140 23141 /* 23142 * Allocate a new hashtab for a sourced script. It will be used while 23143 * sourcing this script and when executing functions defined in the script. 23144 */ 23145 void 23146 new_script_vars(scid_T id) 23147 { 23148 int i; 23149 hashtab_T *ht; 23150 scriptvar_T *sv; 23151 23152 if (ga_grow(&ga_scripts, (int)(id - ga_scripts.ga_len)) == OK) 23153 { 23154 /* Re-allocating ga_data means that an ht_array pointing to 23155 * ht_smallarray becomes invalid. We can recognize this: ht_mask is 23156 * at its init value. Also reset "v_dict", it's always the same. */ 23157 for (i = 1; i <= ga_scripts.ga_len; ++i) 23158 { 23159 ht = &SCRIPT_VARS(i); 23160 if (ht->ht_mask == HT_INIT_SIZE - 1) 23161 ht->ht_array = ht->ht_smallarray; 23162 sv = SCRIPT_SV(i); 23163 sv->sv_var.di_tv.vval.v_dict = &sv->sv_dict; 23164 } 23165 23166 while (ga_scripts.ga_len < id) 23167 { 23168 sv = SCRIPT_SV(ga_scripts.ga_len + 1) = 23169 (scriptvar_T *)alloc_clear(sizeof(scriptvar_T)); 23170 init_var_dict(&sv->sv_dict, &sv->sv_var, VAR_SCOPE); 23171 ++ga_scripts.ga_len; 23172 } 23173 } 23174 } 23175 23176 /* 23177 * Initialize dictionary "dict" as a scope and set variable "dict_var" to 23178 * point to it. 23179 */ 23180 void 23181 init_var_dict(dict_T *dict, dictitem_T *dict_var, int scope) 23182 { 23183 hash_init(&dict->dv_hashtab); 23184 dict->dv_lock = 0; 23185 dict->dv_scope = scope; 23186 dict->dv_refcount = DO_NOT_FREE_CNT; 23187 dict->dv_copyID = 0; 23188 dict_var->di_tv.vval.v_dict = dict; 23189 dict_var->di_tv.v_type = VAR_DICT; 23190 dict_var->di_tv.v_lock = VAR_FIXED; 23191 dict_var->di_flags = DI_FLAGS_RO | DI_FLAGS_FIX; 23192 dict_var->di_key[0] = NUL; 23193 } 23194 23195 /* 23196 * Unreference a dictionary initialized by init_var_dict(). 23197 */ 23198 void 23199 unref_var_dict(dict_T *dict) 23200 { 23201 /* Now the dict needs to be freed if no one else is using it, go back to 23202 * normal reference counting. */ 23203 dict->dv_refcount -= DO_NOT_FREE_CNT - 1; 23204 dict_unref(dict); 23205 } 23206 23207 /* 23208 * Clean up a list of internal variables. 23209 * Frees all allocated variables and the value they contain. 23210 * Clears hashtab "ht", does not free it. 23211 */ 23212 void 23213 vars_clear(hashtab_T *ht) 23214 { 23215 vars_clear_ext(ht, TRUE); 23216 } 23217 23218 /* 23219 * Like vars_clear(), but only free the value if "free_val" is TRUE. 23220 */ 23221 static void 23222 vars_clear_ext(hashtab_T *ht, int free_val) 23223 { 23224 int todo; 23225 hashitem_T *hi; 23226 dictitem_T *v; 23227 23228 hash_lock(ht); 23229 todo = (int)ht->ht_used; 23230 for (hi = ht->ht_array; todo > 0; ++hi) 23231 { 23232 if (!HASHITEM_EMPTY(hi)) 23233 { 23234 --todo; 23235 23236 /* Free the variable. Don't remove it from the hashtab, 23237 * ht_array might change then. hash_clear() takes care of it 23238 * later. */ 23239 v = HI2DI(hi); 23240 if (free_val) 23241 clear_tv(&v->di_tv); 23242 if (v->di_flags & DI_FLAGS_ALLOC) 23243 vim_free(v); 23244 } 23245 } 23246 hash_clear(ht); 23247 ht->ht_used = 0; 23248 } 23249 23250 /* 23251 * Delete a variable from hashtab "ht" at item "hi". 23252 * Clear the variable value and free the dictitem. 23253 */ 23254 static void 23255 delete_var(hashtab_T *ht, hashitem_T *hi) 23256 { 23257 dictitem_T *di = HI2DI(hi); 23258 23259 hash_remove(ht, hi); 23260 clear_tv(&di->di_tv); 23261 vim_free(di); 23262 } 23263 23264 /* 23265 * List the value of one internal variable. 23266 */ 23267 static void 23268 list_one_var(dictitem_T *v, char_u *prefix, int *first) 23269 { 23270 char_u *tofree; 23271 char_u *s; 23272 char_u numbuf[NUMBUFLEN]; 23273 23274 s = echo_string(&v->di_tv, &tofree, numbuf, get_copyID()); 23275 list_one_var_a(prefix, v->di_key, v->di_tv.v_type, 23276 s == NULL ? (char_u *)"" : s, first); 23277 vim_free(tofree); 23278 } 23279 23280 static void 23281 list_one_var_a( 23282 char_u *prefix, 23283 char_u *name, 23284 int type, 23285 char_u *string, 23286 int *first) /* when TRUE clear rest of screen and set to FALSE */ 23287 { 23288 /* don't use msg() or msg_attr() to avoid overwriting "v:statusmsg" */ 23289 msg_start(); 23290 msg_puts(prefix); 23291 if (name != NULL) /* "a:" vars don't have a name stored */ 23292 msg_puts(name); 23293 msg_putchar(' '); 23294 msg_advance(22); 23295 if (type == VAR_NUMBER) 23296 msg_putchar('#'); 23297 else if (type == VAR_FUNC || type == VAR_PARTIAL) 23298 msg_putchar('*'); 23299 else if (type == VAR_LIST) 23300 { 23301 msg_putchar('['); 23302 if (*string == '[') 23303 ++string; 23304 } 23305 else if (type == VAR_DICT) 23306 { 23307 msg_putchar('{'); 23308 if (*string == '{') 23309 ++string; 23310 } 23311 else 23312 msg_putchar(' '); 23313 23314 msg_outtrans(string); 23315 23316 if (type == VAR_FUNC || type == VAR_PARTIAL) 23317 msg_puts((char_u *)"()"); 23318 if (*first) 23319 { 23320 msg_clr_eos(); 23321 *first = FALSE; 23322 } 23323 } 23324 23325 /* 23326 * Set variable "name" to value in "tv". 23327 * If the variable already exists, the value is updated. 23328 * Otherwise the variable is created. 23329 */ 23330 static void 23331 set_var( 23332 char_u *name, 23333 typval_T *tv, 23334 int copy) /* make copy of value in "tv" */ 23335 { 23336 dictitem_T *v; 23337 char_u *varname; 23338 hashtab_T *ht; 23339 23340 ht = find_var_ht(name, &varname); 23341 if (ht == NULL || *varname == NUL) 23342 { 23343 EMSG2(_(e_illvar), name); 23344 return; 23345 } 23346 v = find_var_in_ht(ht, 0, varname, TRUE); 23347 23348 if ((tv->v_type == VAR_FUNC || tv->v_type == VAR_PARTIAL) 23349 && var_check_func_name(name, v == NULL)) 23350 return; 23351 23352 if (v != NULL) 23353 { 23354 /* existing variable, need to clear the value */ 23355 if (var_check_ro(v->di_flags, name, FALSE) 23356 || tv_check_lock(v->di_tv.v_lock, name, FALSE)) 23357 return; 23358 23359 /* 23360 * Handle setting internal v: variables separately where needed to 23361 * prevent changing the type. 23362 */ 23363 if (ht == &vimvarht) 23364 { 23365 if (v->di_tv.v_type == VAR_STRING) 23366 { 23367 vim_free(v->di_tv.vval.v_string); 23368 if (copy || tv->v_type != VAR_STRING) 23369 v->di_tv.vval.v_string = vim_strsave(get_tv_string(tv)); 23370 else 23371 { 23372 /* Take over the string to avoid an extra alloc/free. */ 23373 v->di_tv.vval.v_string = tv->vval.v_string; 23374 tv->vval.v_string = NULL; 23375 } 23376 return; 23377 } 23378 else if (v->di_tv.v_type == VAR_NUMBER) 23379 { 23380 v->di_tv.vval.v_number = get_tv_number(tv); 23381 if (STRCMP(varname, "searchforward") == 0) 23382 set_search_direction(v->di_tv.vval.v_number ? '/' : '?'); 23383 #ifdef FEAT_SEARCH_EXTRA 23384 else if (STRCMP(varname, "hlsearch") == 0) 23385 { 23386 no_hlsearch = !v->di_tv.vval.v_number; 23387 redraw_all_later(SOME_VALID); 23388 } 23389 #endif 23390 return; 23391 } 23392 else if (v->di_tv.v_type != tv->v_type) 23393 EMSG2(_(e_intern2), "set_var()"); 23394 } 23395 23396 clear_tv(&v->di_tv); 23397 } 23398 else /* add a new variable */ 23399 { 23400 /* Can't add "v:" variable. */ 23401 if (ht == &vimvarht) 23402 { 23403 EMSG2(_(e_illvar), name); 23404 return; 23405 } 23406 23407 /* Make sure the variable name is valid. */ 23408 if (!valid_varname(varname)) 23409 return; 23410 23411 v = (dictitem_T *)alloc((unsigned)(sizeof(dictitem_T) 23412 + STRLEN(varname))); 23413 if (v == NULL) 23414 return; 23415 STRCPY(v->di_key, varname); 23416 if (hash_add(ht, DI2HIKEY(v)) == FAIL) 23417 { 23418 vim_free(v); 23419 return; 23420 } 23421 v->di_flags = DI_FLAGS_ALLOC; 23422 } 23423 23424 if (copy || tv->v_type == VAR_NUMBER || tv->v_type == VAR_FLOAT) 23425 copy_tv(tv, &v->di_tv); 23426 else 23427 { 23428 v->di_tv = *tv; 23429 v->di_tv.v_lock = 0; 23430 init_tv(tv); 23431 } 23432 } 23433 23434 /* 23435 * Return TRUE if di_flags "flags" indicates variable "name" is read-only. 23436 * Also give an error message. 23437 */ 23438 static int 23439 var_check_ro(int flags, char_u *name, int use_gettext) 23440 { 23441 if (flags & DI_FLAGS_RO) 23442 { 23443 EMSG2(_(e_readonlyvar), use_gettext ? (char_u *)_(name) : name); 23444 return TRUE; 23445 } 23446 if ((flags & DI_FLAGS_RO_SBX) && sandbox) 23447 { 23448 EMSG2(_(e_readonlysbx), use_gettext ? (char_u *)_(name) : name); 23449 return TRUE; 23450 } 23451 return FALSE; 23452 } 23453 23454 /* 23455 * Return TRUE if di_flags "flags" indicates variable "name" is fixed. 23456 * Also give an error message. 23457 */ 23458 static int 23459 var_check_fixed(int flags, char_u *name, int use_gettext) 23460 { 23461 if (flags & DI_FLAGS_FIX) 23462 { 23463 EMSG2(_("E795: Cannot delete variable %s"), 23464 use_gettext ? (char_u *)_(name) : name); 23465 return TRUE; 23466 } 23467 return FALSE; 23468 } 23469 23470 /* 23471 * Check if a funcref is assigned to a valid variable name. 23472 * Return TRUE and give an error if not. 23473 */ 23474 static int 23475 var_check_func_name( 23476 char_u *name, /* points to start of variable name */ 23477 int new_var) /* TRUE when creating the variable */ 23478 { 23479 /* Allow for w: b: s: and t:. */ 23480 if (!(vim_strchr((char_u *)"wbst", name[0]) != NULL && name[1] == ':') 23481 && !ASCII_ISUPPER((name[0] != NUL && name[1] == ':') 23482 ? name[2] : name[0])) 23483 { 23484 EMSG2(_("E704: Funcref variable name must start with a capital: %s"), 23485 name); 23486 return TRUE; 23487 } 23488 /* Don't allow hiding a function. When "v" is not NULL we might be 23489 * assigning another function to the same var, the type is checked 23490 * below. */ 23491 if (new_var && function_exists(name)) 23492 { 23493 EMSG2(_("E705: Variable name conflicts with existing function: %s"), 23494 name); 23495 return TRUE; 23496 } 23497 return FALSE; 23498 } 23499 23500 /* 23501 * Check if a variable name is valid. 23502 * Return FALSE and give an error if not. 23503 */ 23504 static int 23505 valid_varname(char_u *varname) 23506 { 23507 char_u *p; 23508 23509 for (p = varname; *p != NUL; ++p) 23510 if (!eval_isnamec1(*p) && (p == varname || !VIM_ISDIGIT(*p)) 23511 && *p != AUTOLOAD_CHAR) 23512 { 23513 EMSG2(_(e_illvar), varname); 23514 return FALSE; 23515 } 23516 return TRUE; 23517 } 23518 23519 /* 23520 * Return TRUE if typeval "tv" is set to be locked (immutable). 23521 * Also give an error message, using "name" or _("name") when use_gettext is 23522 * TRUE. 23523 */ 23524 static int 23525 tv_check_lock(int lock, char_u *name, int use_gettext) 23526 { 23527 if (lock & VAR_LOCKED) 23528 { 23529 EMSG2(_("E741: Value is locked: %s"), 23530 name == NULL ? (char_u *)_("Unknown") 23531 : use_gettext ? (char_u *)_(name) 23532 : name); 23533 return TRUE; 23534 } 23535 if (lock & VAR_FIXED) 23536 { 23537 EMSG2(_("E742: Cannot change value of %s"), 23538 name == NULL ? (char_u *)_("Unknown") 23539 : use_gettext ? (char_u *)_(name) 23540 : name); 23541 return TRUE; 23542 } 23543 return FALSE; 23544 } 23545 23546 /* 23547 * Copy the values from typval_T "from" to typval_T "to". 23548 * When needed allocates string or increases reference count. 23549 * Does not make a copy of a list or dict but copies the reference! 23550 * It is OK for "from" and "to" to point to the same item. This is used to 23551 * make a copy later. 23552 */ 23553 void 23554 copy_tv(typval_T *from, typval_T *to) 23555 { 23556 to->v_type = from->v_type; 23557 to->v_lock = 0; 23558 switch (from->v_type) 23559 { 23560 case VAR_NUMBER: 23561 case VAR_SPECIAL: 23562 to->vval.v_number = from->vval.v_number; 23563 break; 23564 case VAR_FLOAT: 23565 #ifdef FEAT_FLOAT 23566 to->vval.v_float = from->vval.v_float; 23567 break; 23568 #endif 23569 case VAR_JOB: 23570 #ifdef FEAT_JOB_CHANNEL 23571 to->vval.v_job = from->vval.v_job; 23572 if (to->vval.v_job != NULL) 23573 ++to->vval.v_job->jv_refcount; 23574 break; 23575 #endif 23576 case VAR_CHANNEL: 23577 #ifdef FEAT_JOB_CHANNEL 23578 to->vval.v_channel = from->vval.v_channel; 23579 if (to->vval.v_channel != NULL) 23580 ++to->vval.v_channel->ch_refcount; 23581 break; 23582 #endif 23583 case VAR_STRING: 23584 case VAR_FUNC: 23585 if (from->vval.v_string == NULL) 23586 to->vval.v_string = NULL; 23587 else 23588 { 23589 to->vval.v_string = vim_strsave(from->vval.v_string); 23590 if (from->v_type == VAR_FUNC) 23591 func_ref(to->vval.v_string); 23592 } 23593 break; 23594 case VAR_PARTIAL: 23595 if (from->vval.v_partial == NULL) 23596 to->vval.v_partial = NULL; 23597 else 23598 { 23599 to->vval.v_partial = from->vval.v_partial; 23600 ++to->vval.v_partial->pt_refcount; 23601 } 23602 break; 23603 case VAR_LIST: 23604 if (from->vval.v_list == NULL) 23605 to->vval.v_list = NULL; 23606 else 23607 { 23608 to->vval.v_list = from->vval.v_list; 23609 ++to->vval.v_list->lv_refcount; 23610 } 23611 break; 23612 case VAR_DICT: 23613 if (from->vval.v_dict == NULL) 23614 to->vval.v_dict = NULL; 23615 else 23616 { 23617 to->vval.v_dict = from->vval.v_dict; 23618 ++to->vval.v_dict->dv_refcount; 23619 } 23620 break; 23621 case VAR_UNKNOWN: 23622 EMSG2(_(e_intern2), "copy_tv(UNKNOWN)"); 23623 break; 23624 } 23625 } 23626 23627 /* 23628 * Make a copy of an item. 23629 * Lists and Dictionaries are also copied. A deep copy if "deep" is set. 23630 * For deepcopy() "copyID" is zero for a full copy or the ID for when a 23631 * reference to an already copied list/dict can be used. 23632 * Returns FAIL or OK. 23633 */ 23634 static int 23635 item_copy( 23636 typval_T *from, 23637 typval_T *to, 23638 int deep, 23639 int copyID) 23640 { 23641 static int recurse = 0; 23642 int ret = OK; 23643 23644 if (recurse >= DICT_MAXNEST) 23645 { 23646 EMSG(_("E698: variable nested too deep for making a copy")); 23647 return FAIL; 23648 } 23649 ++recurse; 23650 23651 switch (from->v_type) 23652 { 23653 case VAR_NUMBER: 23654 case VAR_FLOAT: 23655 case VAR_STRING: 23656 case VAR_FUNC: 23657 case VAR_PARTIAL: 23658 case VAR_SPECIAL: 23659 case VAR_JOB: 23660 case VAR_CHANNEL: 23661 copy_tv(from, to); 23662 break; 23663 case VAR_LIST: 23664 to->v_type = VAR_LIST; 23665 to->v_lock = 0; 23666 if (from->vval.v_list == NULL) 23667 to->vval.v_list = NULL; 23668 else if (copyID != 0 && from->vval.v_list->lv_copyID == copyID) 23669 { 23670 /* use the copy made earlier */ 23671 to->vval.v_list = from->vval.v_list->lv_copylist; 23672 ++to->vval.v_list->lv_refcount; 23673 } 23674 else 23675 to->vval.v_list = list_copy(from->vval.v_list, deep, copyID); 23676 if (to->vval.v_list == NULL) 23677 ret = FAIL; 23678 break; 23679 case VAR_DICT: 23680 to->v_type = VAR_DICT; 23681 to->v_lock = 0; 23682 if (from->vval.v_dict == NULL) 23683 to->vval.v_dict = NULL; 23684 else if (copyID != 0 && from->vval.v_dict->dv_copyID == copyID) 23685 { 23686 /* use the copy made earlier */ 23687 to->vval.v_dict = from->vval.v_dict->dv_copydict; 23688 ++to->vval.v_dict->dv_refcount; 23689 } 23690 else 23691 to->vval.v_dict = dict_copy(from->vval.v_dict, deep, copyID); 23692 if (to->vval.v_dict == NULL) 23693 ret = FAIL; 23694 break; 23695 case VAR_UNKNOWN: 23696 EMSG2(_(e_intern2), "item_copy(UNKNOWN)"); 23697 ret = FAIL; 23698 } 23699 --recurse; 23700 return ret; 23701 } 23702 23703 /* 23704 * ":echo expr1 ..." print each argument separated with a space, add a 23705 * newline at the end. 23706 * ":echon expr1 ..." print each argument plain. 23707 */ 23708 void 23709 ex_echo(exarg_T *eap) 23710 { 23711 char_u *arg = eap->arg; 23712 typval_T rettv; 23713 char_u *tofree; 23714 char_u *p; 23715 int needclr = TRUE; 23716 int atstart = TRUE; 23717 char_u numbuf[NUMBUFLEN]; 23718 23719 if (eap->skip) 23720 ++emsg_skip; 23721 while (*arg != NUL && *arg != '|' && *arg != '\n' && !got_int) 23722 { 23723 /* If eval1() causes an error message the text from the command may 23724 * still need to be cleared. E.g., "echo 22,44". */ 23725 need_clr_eos = needclr; 23726 23727 p = arg; 23728 if (eval1(&arg, &rettv, !eap->skip) == FAIL) 23729 { 23730 /* 23731 * Report the invalid expression unless the expression evaluation 23732 * has been cancelled due to an aborting error, an interrupt, or an 23733 * exception. 23734 */ 23735 if (!aborting()) 23736 EMSG2(_(e_invexpr2), p); 23737 need_clr_eos = FALSE; 23738 break; 23739 } 23740 need_clr_eos = FALSE; 23741 23742 if (!eap->skip) 23743 { 23744 if (atstart) 23745 { 23746 atstart = FALSE; 23747 /* Call msg_start() after eval1(), evaluating the expression 23748 * may cause a message to appear. */ 23749 if (eap->cmdidx == CMD_echo) 23750 { 23751 /* Mark the saved text as finishing the line, so that what 23752 * follows is displayed on a new line when scrolling back 23753 * at the more prompt. */ 23754 msg_sb_eol(); 23755 msg_start(); 23756 } 23757 } 23758 else if (eap->cmdidx == CMD_echo) 23759 msg_puts_attr((char_u *)" ", echo_attr); 23760 p = echo_string(&rettv, &tofree, numbuf, get_copyID()); 23761 if (p != NULL) 23762 for ( ; *p != NUL && !got_int; ++p) 23763 { 23764 if (*p == '\n' || *p == '\r' || *p == TAB) 23765 { 23766 if (*p != TAB && needclr) 23767 { 23768 /* remove any text still there from the command */ 23769 msg_clr_eos(); 23770 needclr = FALSE; 23771 } 23772 msg_putchar_attr(*p, echo_attr); 23773 } 23774 else 23775 { 23776 #ifdef FEAT_MBYTE 23777 if (has_mbyte) 23778 { 23779 int i = (*mb_ptr2len)(p); 23780 23781 (void)msg_outtrans_len_attr(p, i, echo_attr); 23782 p += i - 1; 23783 } 23784 else 23785 #endif 23786 (void)msg_outtrans_len_attr(p, 1, echo_attr); 23787 } 23788 } 23789 vim_free(tofree); 23790 } 23791 clear_tv(&rettv); 23792 arg = skipwhite(arg); 23793 } 23794 eap->nextcmd = check_nextcmd(arg); 23795 23796 if (eap->skip) 23797 --emsg_skip; 23798 else 23799 { 23800 /* remove text that may still be there from the command */ 23801 if (needclr) 23802 msg_clr_eos(); 23803 if (eap->cmdidx == CMD_echo) 23804 msg_end(); 23805 } 23806 } 23807 23808 /* 23809 * ":echohl {name}". 23810 */ 23811 void 23812 ex_echohl(exarg_T *eap) 23813 { 23814 int id; 23815 23816 id = syn_name2id(eap->arg); 23817 if (id == 0) 23818 echo_attr = 0; 23819 else 23820 echo_attr = syn_id2attr(id); 23821 } 23822 23823 /* 23824 * ":execute expr1 ..." execute the result of an expression. 23825 * ":echomsg expr1 ..." Print a message 23826 * ":echoerr expr1 ..." Print an error 23827 * Each gets spaces around each argument and a newline at the end for 23828 * echo commands 23829 */ 23830 void 23831 ex_execute(exarg_T *eap) 23832 { 23833 char_u *arg = eap->arg; 23834 typval_T rettv; 23835 int ret = OK; 23836 char_u *p; 23837 garray_T ga; 23838 int len; 23839 int save_did_emsg; 23840 23841 ga_init2(&ga, 1, 80); 23842 23843 if (eap->skip) 23844 ++emsg_skip; 23845 while (*arg != NUL && *arg != '|' && *arg != '\n') 23846 { 23847 p = arg; 23848 if (eval1(&arg, &rettv, !eap->skip) == FAIL) 23849 { 23850 /* 23851 * Report the invalid expression unless the expression evaluation 23852 * has been cancelled due to an aborting error, an interrupt, or an 23853 * exception. 23854 */ 23855 if (!aborting()) 23856 EMSG2(_(e_invexpr2), p); 23857 ret = FAIL; 23858 break; 23859 } 23860 23861 if (!eap->skip) 23862 { 23863 p = get_tv_string(&rettv); 23864 len = (int)STRLEN(p); 23865 if (ga_grow(&ga, len + 2) == FAIL) 23866 { 23867 clear_tv(&rettv); 23868 ret = FAIL; 23869 break; 23870 } 23871 if (ga.ga_len) 23872 ((char_u *)(ga.ga_data))[ga.ga_len++] = ' '; 23873 STRCPY((char_u *)(ga.ga_data) + ga.ga_len, p); 23874 ga.ga_len += len; 23875 } 23876 23877 clear_tv(&rettv); 23878 arg = skipwhite(arg); 23879 } 23880 23881 if (ret != FAIL && ga.ga_data != NULL) 23882 { 23883 if (eap->cmdidx == CMD_echomsg) 23884 { 23885 MSG_ATTR(ga.ga_data, echo_attr); 23886 out_flush(); 23887 } 23888 else if (eap->cmdidx == CMD_echoerr) 23889 { 23890 /* We don't want to abort following commands, restore did_emsg. */ 23891 save_did_emsg = did_emsg; 23892 EMSG((char_u *)ga.ga_data); 23893 if (!force_abort) 23894 did_emsg = save_did_emsg; 23895 } 23896 else if (eap->cmdidx == CMD_execute) 23897 do_cmdline((char_u *)ga.ga_data, 23898 eap->getline, eap->cookie, DOCMD_NOWAIT|DOCMD_VERBOSE); 23899 } 23900 23901 ga_clear(&ga); 23902 23903 if (eap->skip) 23904 --emsg_skip; 23905 23906 eap->nextcmd = check_nextcmd(arg); 23907 } 23908 23909 /* 23910 * Skip over the name of an option: "&option", "&g:option" or "&l:option". 23911 * "arg" points to the "&" or '+' when called, to "option" when returning. 23912 * Returns NULL when no option name found. Otherwise pointer to the char 23913 * after the option name. 23914 */ 23915 static char_u * 23916 find_option_end(char_u **arg, int *opt_flags) 23917 { 23918 char_u *p = *arg; 23919 23920 ++p; 23921 if (*p == 'g' && p[1] == ':') 23922 { 23923 *opt_flags = OPT_GLOBAL; 23924 p += 2; 23925 } 23926 else if (*p == 'l' && p[1] == ':') 23927 { 23928 *opt_flags = OPT_LOCAL; 23929 p += 2; 23930 } 23931 else 23932 *opt_flags = 0; 23933 23934 if (!ASCII_ISALPHA(*p)) 23935 return NULL; 23936 *arg = p; 23937 23938 if (p[0] == 't' && p[1] == '_' && p[2] != NUL && p[3] != NUL) 23939 p += 4; /* termcap option */ 23940 else 23941 while (ASCII_ISALPHA(*p)) 23942 ++p; 23943 return p; 23944 } 23945 23946 /* 23947 * ":function" 23948 */ 23949 void 23950 ex_function(exarg_T *eap) 23951 { 23952 char_u *theline; 23953 int i; 23954 int j; 23955 int c; 23956 int saved_did_emsg; 23957 int saved_wait_return = need_wait_return; 23958 char_u *name = NULL; 23959 char_u *p; 23960 char_u *arg; 23961 char_u *line_arg = NULL; 23962 garray_T newargs; 23963 garray_T newlines; 23964 int varargs = FALSE; 23965 int mustend = FALSE; 23966 int flags = 0; 23967 ufunc_T *fp; 23968 int indent; 23969 int nesting; 23970 char_u *skip_until = NULL; 23971 dictitem_T *v; 23972 funcdict_T fudi; 23973 static int func_nr = 0; /* number for nameless function */ 23974 int paren; 23975 hashtab_T *ht; 23976 int todo; 23977 hashitem_T *hi; 23978 int sourcing_lnum_off; 23979 23980 /* 23981 * ":function" without argument: list functions. 23982 */ 23983 if (ends_excmd(*eap->arg)) 23984 { 23985 if (!eap->skip) 23986 { 23987 todo = (int)func_hashtab.ht_used; 23988 for (hi = func_hashtab.ht_array; todo > 0 && !got_int; ++hi) 23989 { 23990 if (!HASHITEM_EMPTY(hi)) 23991 { 23992 --todo; 23993 fp = HI2UF(hi); 23994 if (!isdigit(*fp->uf_name)) 23995 list_func_head(fp, FALSE); 23996 } 23997 } 23998 } 23999 eap->nextcmd = check_nextcmd(eap->arg); 24000 return; 24001 } 24002 24003 /* 24004 * ":function /pat": list functions matching pattern. 24005 */ 24006 if (*eap->arg == '/') 24007 { 24008 p = skip_regexp(eap->arg + 1, '/', TRUE, NULL); 24009 if (!eap->skip) 24010 { 24011 regmatch_T regmatch; 24012 24013 c = *p; 24014 *p = NUL; 24015 regmatch.regprog = vim_regcomp(eap->arg + 1, RE_MAGIC); 24016 *p = c; 24017 if (regmatch.regprog != NULL) 24018 { 24019 regmatch.rm_ic = p_ic; 24020 24021 todo = (int)func_hashtab.ht_used; 24022 for (hi = func_hashtab.ht_array; todo > 0 && !got_int; ++hi) 24023 { 24024 if (!HASHITEM_EMPTY(hi)) 24025 { 24026 --todo; 24027 fp = HI2UF(hi); 24028 if (!isdigit(*fp->uf_name) 24029 && vim_regexec(®match, fp->uf_name, 0)) 24030 list_func_head(fp, FALSE); 24031 } 24032 } 24033 vim_regfree(regmatch.regprog); 24034 } 24035 } 24036 if (*p == '/') 24037 ++p; 24038 eap->nextcmd = check_nextcmd(p); 24039 return; 24040 } 24041 24042 /* 24043 * Get the function name. There are these situations: 24044 * func normal function name 24045 * "name" == func, "fudi.fd_dict" == NULL 24046 * dict.func new dictionary entry 24047 * "name" == NULL, "fudi.fd_dict" set, 24048 * "fudi.fd_di" == NULL, "fudi.fd_newkey" == func 24049 * dict.func existing dict entry with a Funcref 24050 * "name" == func, "fudi.fd_dict" set, 24051 * "fudi.fd_di" set, "fudi.fd_newkey" == NULL 24052 * dict.func existing dict entry that's not a Funcref 24053 * "name" == NULL, "fudi.fd_dict" set, 24054 * "fudi.fd_di" set, "fudi.fd_newkey" == NULL 24055 * s:func script-local function name 24056 * g:func global function name, same as "func" 24057 */ 24058 p = eap->arg; 24059 name = trans_function_name(&p, eap->skip, 0, &fudi, NULL); 24060 paren = (vim_strchr(p, '(') != NULL); 24061 if (name == NULL && (fudi.fd_dict == NULL || !paren) && !eap->skip) 24062 { 24063 /* 24064 * Return on an invalid expression in braces, unless the expression 24065 * evaluation has been cancelled due to an aborting error, an 24066 * interrupt, or an exception. 24067 */ 24068 if (!aborting()) 24069 { 24070 if (!eap->skip && fudi.fd_newkey != NULL) 24071 EMSG2(_(e_dictkey), fudi.fd_newkey); 24072 vim_free(fudi.fd_newkey); 24073 return; 24074 } 24075 else 24076 eap->skip = TRUE; 24077 } 24078 24079 /* An error in a function call during evaluation of an expression in magic 24080 * braces should not cause the function not to be defined. */ 24081 saved_did_emsg = did_emsg; 24082 did_emsg = FALSE; 24083 24084 /* 24085 * ":function func" with only function name: list function. 24086 */ 24087 if (!paren) 24088 { 24089 if (!ends_excmd(*skipwhite(p))) 24090 { 24091 EMSG(_(e_trailing)); 24092 goto ret_free; 24093 } 24094 eap->nextcmd = check_nextcmd(p); 24095 if (eap->nextcmd != NULL) 24096 *p = NUL; 24097 if (!eap->skip && !got_int) 24098 { 24099 fp = find_func(name); 24100 if (fp != NULL) 24101 { 24102 list_func_head(fp, TRUE); 24103 for (j = 0; j < fp->uf_lines.ga_len && !got_int; ++j) 24104 { 24105 if (FUNCLINE(fp, j) == NULL) 24106 continue; 24107 msg_putchar('\n'); 24108 msg_outnum((long)(j + 1)); 24109 if (j < 9) 24110 msg_putchar(' '); 24111 if (j < 99) 24112 msg_putchar(' '); 24113 msg_prt_line(FUNCLINE(fp, j), FALSE); 24114 out_flush(); /* show a line at a time */ 24115 ui_breakcheck(); 24116 } 24117 if (!got_int) 24118 { 24119 msg_putchar('\n'); 24120 msg_puts((char_u *)" endfunction"); 24121 } 24122 } 24123 else 24124 emsg_funcname(N_("E123: Undefined function: %s"), name); 24125 } 24126 goto ret_free; 24127 } 24128 24129 /* 24130 * ":function name(arg1, arg2)" Define function. 24131 */ 24132 p = skipwhite(p); 24133 if (*p != '(') 24134 { 24135 if (!eap->skip) 24136 { 24137 EMSG2(_("E124: Missing '(': %s"), eap->arg); 24138 goto ret_free; 24139 } 24140 /* attempt to continue by skipping some text */ 24141 if (vim_strchr(p, '(') != NULL) 24142 p = vim_strchr(p, '('); 24143 } 24144 p = skipwhite(p + 1); 24145 24146 ga_init2(&newargs, (int)sizeof(char_u *), 3); 24147 ga_init2(&newlines, (int)sizeof(char_u *), 3); 24148 24149 if (!eap->skip) 24150 { 24151 /* Check the name of the function. Unless it's a dictionary function 24152 * (that we are overwriting). */ 24153 if (name != NULL) 24154 arg = name; 24155 else 24156 arg = fudi.fd_newkey; 24157 if (arg != NULL && (fudi.fd_di == NULL 24158 || (fudi.fd_di->di_tv.v_type != VAR_FUNC 24159 && fudi.fd_di->di_tv.v_type != VAR_PARTIAL))) 24160 { 24161 if (*arg == K_SPECIAL) 24162 j = 3; 24163 else 24164 j = 0; 24165 while (arg[j] != NUL && (j == 0 ? eval_isnamec1(arg[j]) 24166 : eval_isnamec(arg[j]))) 24167 ++j; 24168 if (arg[j] != NUL) 24169 emsg_funcname((char *)e_invarg2, arg); 24170 } 24171 /* Disallow using the g: dict. */ 24172 if (fudi.fd_dict != NULL && fudi.fd_dict->dv_scope == VAR_DEF_SCOPE) 24173 EMSG(_("E862: Cannot use g: here")); 24174 } 24175 24176 /* 24177 * Isolate the arguments: "arg1, arg2, ...)" 24178 */ 24179 while (*p != ')') 24180 { 24181 if (p[0] == '.' && p[1] == '.' && p[2] == '.') 24182 { 24183 varargs = TRUE; 24184 p += 3; 24185 mustend = TRUE; 24186 } 24187 else 24188 { 24189 arg = p; 24190 while (ASCII_ISALNUM(*p) || *p == '_') 24191 ++p; 24192 if (arg == p || isdigit(*arg) 24193 || (p - arg == 9 && STRNCMP(arg, "firstline", 9) == 0) 24194 || (p - arg == 8 && STRNCMP(arg, "lastline", 8) == 0)) 24195 { 24196 if (!eap->skip) 24197 EMSG2(_("E125: Illegal argument: %s"), arg); 24198 break; 24199 } 24200 if (ga_grow(&newargs, 1) == FAIL) 24201 goto erret; 24202 c = *p; 24203 *p = NUL; 24204 arg = vim_strsave(arg); 24205 if (arg == NULL) 24206 goto erret; 24207 24208 /* Check for duplicate argument name. */ 24209 for (i = 0; i < newargs.ga_len; ++i) 24210 if (STRCMP(((char_u **)(newargs.ga_data))[i], arg) == 0) 24211 { 24212 EMSG2(_("E853: Duplicate argument name: %s"), arg); 24213 vim_free(arg); 24214 goto erret; 24215 } 24216 24217 ((char_u **)(newargs.ga_data))[newargs.ga_len] = arg; 24218 *p = c; 24219 newargs.ga_len++; 24220 if (*p == ',') 24221 ++p; 24222 else 24223 mustend = TRUE; 24224 } 24225 p = skipwhite(p); 24226 if (mustend && *p != ')') 24227 { 24228 if (!eap->skip) 24229 EMSG2(_(e_invarg2), eap->arg); 24230 break; 24231 } 24232 } 24233 if (*p != ')') 24234 goto erret; 24235 ++p; /* skip the ')' */ 24236 24237 /* find extra arguments "range", "dict" and "abort" */ 24238 for (;;) 24239 { 24240 p = skipwhite(p); 24241 if (STRNCMP(p, "range", 5) == 0) 24242 { 24243 flags |= FC_RANGE; 24244 p += 5; 24245 } 24246 else if (STRNCMP(p, "dict", 4) == 0) 24247 { 24248 flags |= FC_DICT; 24249 p += 4; 24250 } 24251 else if (STRNCMP(p, "abort", 5) == 0) 24252 { 24253 flags |= FC_ABORT; 24254 p += 5; 24255 } 24256 else 24257 break; 24258 } 24259 24260 /* When there is a line break use what follows for the function body. 24261 * Makes 'exe "func Test()\n...\nendfunc"' work. */ 24262 if (*p == '\n') 24263 line_arg = p + 1; 24264 else if (*p != NUL && *p != '"' && !eap->skip && !did_emsg) 24265 EMSG(_(e_trailing)); 24266 24267 /* 24268 * Read the body of the function, until ":endfunction" is found. 24269 */ 24270 if (KeyTyped) 24271 { 24272 /* Check if the function already exists, don't let the user type the 24273 * whole function before telling him it doesn't work! For a script we 24274 * need to skip the body to be able to find what follows. */ 24275 if (!eap->skip && !eap->forceit) 24276 { 24277 if (fudi.fd_dict != NULL && fudi.fd_newkey == NULL) 24278 EMSG(_(e_funcdict)); 24279 else if (name != NULL && find_func(name) != NULL) 24280 emsg_funcname(e_funcexts, name); 24281 } 24282 24283 if (!eap->skip && did_emsg) 24284 goto erret; 24285 24286 msg_putchar('\n'); /* don't overwrite the function name */ 24287 cmdline_row = msg_row; 24288 } 24289 24290 indent = 2; 24291 nesting = 0; 24292 for (;;) 24293 { 24294 if (KeyTyped) 24295 { 24296 msg_scroll = TRUE; 24297 saved_wait_return = FALSE; 24298 } 24299 need_wait_return = FALSE; 24300 sourcing_lnum_off = sourcing_lnum; 24301 24302 if (line_arg != NULL) 24303 { 24304 /* Use eap->arg, split up in parts by line breaks. */ 24305 theline = line_arg; 24306 p = vim_strchr(theline, '\n'); 24307 if (p == NULL) 24308 line_arg += STRLEN(line_arg); 24309 else 24310 { 24311 *p = NUL; 24312 line_arg = p + 1; 24313 } 24314 } 24315 else if (eap->getline == NULL) 24316 theline = getcmdline(':', 0L, indent); 24317 else 24318 theline = eap->getline(':', eap->cookie, indent); 24319 if (KeyTyped) 24320 lines_left = Rows - 1; 24321 if (theline == NULL) 24322 { 24323 EMSG(_("E126: Missing :endfunction")); 24324 goto erret; 24325 } 24326 24327 /* Detect line continuation: sourcing_lnum increased more than one. */ 24328 if (sourcing_lnum > sourcing_lnum_off + 1) 24329 sourcing_lnum_off = sourcing_lnum - sourcing_lnum_off - 1; 24330 else 24331 sourcing_lnum_off = 0; 24332 24333 if (skip_until != NULL) 24334 { 24335 /* between ":append" and "." and between ":python <<EOF" and "EOF" 24336 * don't check for ":endfunc". */ 24337 if (STRCMP(theline, skip_until) == 0) 24338 { 24339 vim_free(skip_until); 24340 skip_until = NULL; 24341 } 24342 } 24343 else 24344 { 24345 /* skip ':' and blanks*/ 24346 for (p = theline; vim_iswhite(*p) || *p == ':'; ++p) 24347 ; 24348 24349 /* Check for "endfunction". */ 24350 if (checkforcmd(&p, "endfunction", 4) && nesting-- == 0) 24351 { 24352 if (line_arg == NULL) 24353 vim_free(theline); 24354 break; 24355 } 24356 24357 /* Increase indent inside "if", "while", "for" and "try", decrease 24358 * at "end". */ 24359 if (indent > 2 && STRNCMP(p, "end", 3) == 0) 24360 indent -= 2; 24361 else if (STRNCMP(p, "if", 2) == 0 24362 || STRNCMP(p, "wh", 2) == 0 24363 || STRNCMP(p, "for", 3) == 0 24364 || STRNCMP(p, "try", 3) == 0) 24365 indent += 2; 24366 24367 /* Check for defining a function inside this function. */ 24368 if (checkforcmd(&p, "function", 2)) 24369 { 24370 if (*p == '!') 24371 p = skipwhite(p + 1); 24372 p += eval_fname_script(p); 24373 vim_free(trans_function_name(&p, TRUE, 0, NULL, NULL)); 24374 if (*skipwhite(p) == '(') 24375 { 24376 ++nesting; 24377 indent += 2; 24378 } 24379 } 24380 24381 /* Check for ":append" or ":insert". */ 24382 p = skip_range(p, NULL); 24383 if ((p[0] == 'a' && (!ASCII_ISALPHA(p[1]) || p[1] == 'p')) 24384 || (p[0] == 'i' 24385 && (!ASCII_ISALPHA(p[1]) || (p[1] == 'n' 24386 && (!ASCII_ISALPHA(p[2]) || (p[2] == 's')))))) 24387 skip_until = vim_strsave((char_u *)"."); 24388 24389 /* Check for ":python <<EOF", ":tcl <<EOF", etc. */ 24390 arg = skipwhite(skiptowhite(p)); 24391 if (arg[0] == '<' && arg[1] =='<' 24392 && ((p[0] == 'p' && p[1] == 'y' 24393 && (!ASCII_ISALPHA(p[2]) || p[2] == 't')) 24394 || (p[0] == 'p' && p[1] == 'e' 24395 && (!ASCII_ISALPHA(p[2]) || p[2] == 'r')) 24396 || (p[0] == 't' && p[1] == 'c' 24397 && (!ASCII_ISALPHA(p[2]) || p[2] == 'l')) 24398 || (p[0] == 'l' && p[1] == 'u' && p[2] == 'a' 24399 && !ASCII_ISALPHA(p[3])) 24400 || (p[0] == 'r' && p[1] == 'u' && p[2] == 'b' 24401 && (!ASCII_ISALPHA(p[3]) || p[3] == 'y')) 24402 || (p[0] == 'm' && p[1] == 'z' 24403 && (!ASCII_ISALPHA(p[2]) || p[2] == 's')) 24404 )) 24405 { 24406 /* ":python <<" continues until a dot, like ":append" */ 24407 p = skipwhite(arg + 2); 24408 if (*p == NUL) 24409 skip_until = vim_strsave((char_u *)"."); 24410 else 24411 skip_until = vim_strsave(p); 24412 } 24413 } 24414 24415 /* Add the line to the function. */ 24416 if (ga_grow(&newlines, 1 + sourcing_lnum_off) == FAIL) 24417 { 24418 if (line_arg == NULL) 24419 vim_free(theline); 24420 goto erret; 24421 } 24422 24423 /* Copy the line to newly allocated memory. get_one_sourceline() 24424 * allocates 250 bytes per line, this saves 80% on average. The cost 24425 * is an extra alloc/free. */ 24426 p = vim_strsave(theline); 24427 if (p != NULL) 24428 { 24429 if (line_arg == NULL) 24430 vim_free(theline); 24431 theline = p; 24432 } 24433 24434 ((char_u **)(newlines.ga_data))[newlines.ga_len++] = theline; 24435 24436 /* Add NULL lines for continuation lines, so that the line count is 24437 * equal to the index in the growarray. */ 24438 while (sourcing_lnum_off-- > 0) 24439 ((char_u **)(newlines.ga_data))[newlines.ga_len++] = NULL; 24440 24441 /* Check for end of eap->arg. */ 24442 if (line_arg != NULL && *line_arg == NUL) 24443 line_arg = NULL; 24444 } 24445 24446 /* Don't define the function when skipping commands or when an error was 24447 * detected. */ 24448 if (eap->skip || did_emsg) 24449 goto erret; 24450 24451 /* 24452 * If there are no errors, add the function 24453 */ 24454 if (fudi.fd_dict == NULL) 24455 { 24456 v = find_var(name, &ht, FALSE); 24457 if (v != NULL && v->di_tv.v_type == VAR_FUNC) 24458 { 24459 emsg_funcname(N_("E707: Function name conflicts with variable: %s"), 24460 name); 24461 goto erret; 24462 } 24463 24464 fp = find_func(name); 24465 if (fp != NULL) 24466 { 24467 if (!eap->forceit) 24468 { 24469 emsg_funcname(e_funcexts, name); 24470 goto erret; 24471 } 24472 if (fp->uf_calls > 0) 24473 { 24474 emsg_funcname(N_("E127: Cannot redefine function %s: It is in use"), 24475 name); 24476 goto erret; 24477 } 24478 /* redefine existing function */ 24479 ga_clear_strings(&(fp->uf_args)); 24480 ga_clear_strings(&(fp->uf_lines)); 24481 vim_free(name); 24482 name = NULL; 24483 } 24484 } 24485 else 24486 { 24487 char numbuf[20]; 24488 24489 fp = NULL; 24490 if (fudi.fd_newkey == NULL && !eap->forceit) 24491 { 24492 EMSG(_(e_funcdict)); 24493 goto erret; 24494 } 24495 if (fudi.fd_di == NULL) 24496 { 24497 /* Can't add a function to a locked dictionary */ 24498 if (tv_check_lock(fudi.fd_dict->dv_lock, eap->arg, FALSE)) 24499 goto erret; 24500 } 24501 /* Can't change an existing function if it is locked */ 24502 else if (tv_check_lock(fudi.fd_di->di_tv.v_lock, eap->arg, FALSE)) 24503 goto erret; 24504 24505 /* Give the function a sequential number. Can only be used with a 24506 * Funcref! */ 24507 vim_free(name); 24508 sprintf(numbuf, "%d", ++func_nr); 24509 name = vim_strsave((char_u *)numbuf); 24510 if (name == NULL) 24511 goto erret; 24512 } 24513 24514 if (fp == NULL) 24515 { 24516 if (fudi.fd_dict == NULL && vim_strchr(name, AUTOLOAD_CHAR) != NULL) 24517 { 24518 int slen, plen; 24519 char_u *scriptname; 24520 24521 /* Check that the autoload name matches the script name. */ 24522 j = FAIL; 24523 if (sourcing_name != NULL) 24524 { 24525 scriptname = autoload_name(name); 24526 if (scriptname != NULL) 24527 { 24528 p = vim_strchr(scriptname, '/'); 24529 plen = (int)STRLEN(p); 24530 slen = (int)STRLEN(sourcing_name); 24531 if (slen > plen && fnamecmp(p, 24532 sourcing_name + slen - plen) == 0) 24533 j = OK; 24534 vim_free(scriptname); 24535 } 24536 } 24537 if (j == FAIL) 24538 { 24539 EMSG2(_("E746: Function name does not match script file name: %s"), name); 24540 goto erret; 24541 } 24542 } 24543 24544 fp = (ufunc_T *)alloc((unsigned)(sizeof(ufunc_T) + STRLEN(name))); 24545 if (fp == NULL) 24546 goto erret; 24547 24548 if (fudi.fd_dict != NULL) 24549 { 24550 if (fudi.fd_di == NULL) 24551 { 24552 /* add new dict entry */ 24553 fudi.fd_di = dictitem_alloc(fudi.fd_newkey); 24554 if (fudi.fd_di == NULL) 24555 { 24556 vim_free(fp); 24557 goto erret; 24558 } 24559 if (dict_add(fudi.fd_dict, fudi.fd_di) == FAIL) 24560 { 24561 vim_free(fudi.fd_di); 24562 vim_free(fp); 24563 goto erret; 24564 } 24565 } 24566 else 24567 /* overwrite existing dict entry */ 24568 clear_tv(&fudi.fd_di->di_tv); 24569 fudi.fd_di->di_tv.v_type = VAR_FUNC; 24570 fudi.fd_di->di_tv.v_lock = 0; 24571 fudi.fd_di->di_tv.vval.v_string = vim_strsave(name); 24572 fp->uf_refcount = 1; 24573 24574 /* behave like "dict" was used */ 24575 flags |= FC_DICT; 24576 } 24577 24578 /* insert the new function in the function list */ 24579 STRCPY(fp->uf_name, name); 24580 if (hash_add(&func_hashtab, UF2HIKEY(fp)) == FAIL) 24581 { 24582 vim_free(fp); 24583 goto erret; 24584 } 24585 } 24586 fp->uf_args = newargs; 24587 fp->uf_lines = newlines; 24588 #ifdef FEAT_PROFILE 24589 fp->uf_tml_count = NULL; 24590 fp->uf_tml_total = NULL; 24591 fp->uf_tml_self = NULL; 24592 fp->uf_profiling = FALSE; 24593 if (prof_def_func()) 24594 func_do_profile(fp); 24595 #endif 24596 fp->uf_varargs = varargs; 24597 fp->uf_flags = flags; 24598 fp->uf_calls = 0; 24599 fp->uf_script_ID = current_SID; 24600 goto ret_free; 24601 24602 erret: 24603 ga_clear_strings(&newargs); 24604 ga_clear_strings(&newlines); 24605 ret_free: 24606 vim_free(skip_until); 24607 vim_free(fudi.fd_newkey); 24608 vim_free(name); 24609 did_emsg |= saved_did_emsg; 24610 need_wait_return |= saved_wait_return; 24611 } 24612 24613 /* 24614 * Get a function name, translating "<SID>" and "<SNR>". 24615 * Also handles a Funcref in a List or Dictionary. 24616 * Returns the function name in allocated memory, or NULL for failure. 24617 * flags: 24618 * TFN_INT: internal function name OK 24619 * TFN_QUIET: be quiet 24620 * TFN_NO_AUTOLOAD: do not use script autoloading 24621 * Advances "pp" to just after the function name (if no error). 24622 */ 24623 static char_u * 24624 trans_function_name( 24625 char_u **pp, 24626 int skip, /* only find the end, don't evaluate */ 24627 int flags, 24628 funcdict_T *fdp, /* return: info about dictionary used */ 24629 partial_T **partial) /* return: partial of a FuncRef */ 24630 { 24631 char_u *name = NULL; 24632 char_u *start; 24633 char_u *end; 24634 int lead; 24635 char_u sid_buf[20]; 24636 int len; 24637 lval_T lv; 24638 24639 if (fdp != NULL) 24640 vim_memset(fdp, 0, sizeof(funcdict_T)); 24641 start = *pp; 24642 24643 /* Check for hard coded <SNR>: already translated function ID (from a user 24644 * command). */ 24645 if ((*pp)[0] == K_SPECIAL && (*pp)[1] == KS_EXTRA 24646 && (*pp)[2] == (int)KE_SNR) 24647 { 24648 *pp += 3; 24649 len = get_id_len(pp) + 3; 24650 return vim_strnsave(start, len); 24651 } 24652 24653 /* A name starting with "<SID>" or "<SNR>" is local to a script. But 24654 * don't skip over "s:", get_lval() needs it for "s:dict.func". */ 24655 lead = eval_fname_script(start); 24656 if (lead > 2) 24657 start += lead; 24658 24659 /* Note that TFN_ flags use the same values as GLV_ flags. */ 24660 end = get_lval(start, NULL, &lv, FALSE, skip, flags, 24661 lead > 2 ? 0 : FNE_CHECK_START); 24662 if (end == start) 24663 { 24664 if (!skip) 24665 EMSG(_("E129: Function name required")); 24666 goto theend; 24667 } 24668 if (end == NULL || (lv.ll_tv != NULL && (lead > 2 || lv.ll_range))) 24669 { 24670 /* 24671 * Report an invalid expression in braces, unless the expression 24672 * evaluation has been cancelled due to an aborting error, an 24673 * interrupt, or an exception. 24674 */ 24675 if (!aborting()) 24676 { 24677 if (end != NULL) 24678 EMSG2(_(e_invarg2), start); 24679 } 24680 else 24681 *pp = find_name_end(start, NULL, NULL, FNE_INCL_BR); 24682 goto theend; 24683 } 24684 24685 if (lv.ll_tv != NULL) 24686 { 24687 if (fdp != NULL) 24688 { 24689 fdp->fd_dict = lv.ll_dict; 24690 fdp->fd_newkey = lv.ll_newkey; 24691 lv.ll_newkey = NULL; 24692 fdp->fd_di = lv.ll_di; 24693 } 24694 if (lv.ll_tv->v_type == VAR_FUNC && lv.ll_tv->vval.v_string != NULL) 24695 { 24696 name = vim_strsave(lv.ll_tv->vval.v_string); 24697 *pp = end; 24698 } 24699 else if (lv.ll_tv->v_type == VAR_PARTIAL 24700 && lv.ll_tv->vval.v_partial != NULL) 24701 { 24702 name = vim_strsave(lv.ll_tv->vval.v_partial->pt_name); 24703 *pp = end; 24704 if (partial != NULL) 24705 *partial = lv.ll_tv->vval.v_partial; 24706 } 24707 else 24708 { 24709 if (!skip && !(flags & TFN_QUIET) && (fdp == NULL 24710 || lv.ll_dict == NULL || fdp->fd_newkey == NULL)) 24711 EMSG(_(e_funcref)); 24712 else 24713 *pp = end; 24714 name = NULL; 24715 } 24716 goto theend; 24717 } 24718 24719 if (lv.ll_name == NULL) 24720 { 24721 /* Error found, but continue after the function name. */ 24722 *pp = end; 24723 goto theend; 24724 } 24725 24726 /* Check if the name is a Funcref. If so, use the value. */ 24727 if (lv.ll_exp_name != NULL) 24728 { 24729 len = (int)STRLEN(lv.ll_exp_name); 24730 name = deref_func_name(lv.ll_exp_name, &len, partial, 24731 flags & TFN_NO_AUTOLOAD); 24732 if (name == lv.ll_exp_name) 24733 name = NULL; 24734 } 24735 else 24736 { 24737 len = (int)(end - *pp); 24738 name = deref_func_name(*pp, &len, partial, flags & TFN_NO_AUTOLOAD); 24739 if (name == *pp) 24740 name = NULL; 24741 } 24742 if (name != NULL) 24743 { 24744 name = vim_strsave(name); 24745 *pp = end; 24746 if (STRNCMP(name, "<SNR>", 5) == 0) 24747 { 24748 /* Change "<SNR>" to the byte sequence. */ 24749 name[0] = K_SPECIAL; 24750 name[1] = KS_EXTRA; 24751 name[2] = (int)KE_SNR; 24752 mch_memmove(name + 3, name + 5, STRLEN(name + 5) + 1); 24753 } 24754 goto theend; 24755 } 24756 24757 if (lv.ll_exp_name != NULL) 24758 { 24759 len = (int)STRLEN(lv.ll_exp_name); 24760 if (lead <= 2 && lv.ll_name == lv.ll_exp_name 24761 && STRNCMP(lv.ll_name, "s:", 2) == 0) 24762 { 24763 /* When there was "s:" already or the name expanded to get a 24764 * leading "s:" then remove it. */ 24765 lv.ll_name += 2; 24766 len -= 2; 24767 lead = 2; 24768 } 24769 } 24770 else 24771 { 24772 /* skip over "s:" and "g:" */ 24773 if (lead == 2 || (lv.ll_name[0] == 'g' && lv.ll_name[1] == ':')) 24774 lv.ll_name += 2; 24775 len = (int)(end - lv.ll_name); 24776 } 24777 24778 /* 24779 * Copy the function name to allocated memory. 24780 * Accept <SID>name() inside a script, translate into <SNR>123_name(). 24781 * Accept <SNR>123_name() outside a script. 24782 */ 24783 if (skip) 24784 lead = 0; /* do nothing */ 24785 else if (lead > 0) 24786 { 24787 lead = 3; 24788 if ((lv.ll_exp_name != NULL && eval_fname_sid(lv.ll_exp_name)) 24789 || eval_fname_sid(*pp)) 24790 { 24791 /* It's "s:" or "<SID>" */ 24792 if (current_SID <= 0) 24793 { 24794 EMSG(_(e_usingsid)); 24795 goto theend; 24796 } 24797 sprintf((char *)sid_buf, "%ld_", (long)current_SID); 24798 lead += (int)STRLEN(sid_buf); 24799 } 24800 } 24801 else if (!(flags & TFN_INT) && builtin_function(lv.ll_name, len)) 24802 { 24803 EMSG2(_("E128: Function name must start with a capital or \"s:\": %s"), 24804 start); 24805 goto theend; 24806 } 24807 if (!skip && !(flags & TFN_QUIET)) 24808 { 24809 char_u *cp = vim_strchr(lv.ll_name, ':'); 24810 24811 if (cp != NULL && cp < end) 24812 { 24813 EMSG2(_("E884: Function name cannot contain a colon: %s"), start); 24814 goto theend; 24815 } 24816 } 24817 24818 name = alloc((unsigned)(len + lead + 1)); 24819 if (name != NULL) 24820 { 24821 if (lead > 0) 24822 { 24823 name[0] = K_SPECIAL; 24824 name[1] = KS_EXTRA; 24825 name[2] = (int)KE_SNR; 24826 if (lead > 3) /* If it's "<SID>" */ 24827 STRCPY(name + 3, sid_buf); 24828 } 24829 mch_memmove(name + lead, lv.ll_name, (size_t)len); 24830 name[lead + len] = NUL; 24831 } 24832 *pp = end; 24833 24834 theend: 24835 clear_lval(&lv); 24836 return name; 24837 } 24838 24839 /* 24840 * Return 5 if "p" starts with "<SID>" or "<SNR>" (ignoring case). 24841 * Return 2 if "p" starts with "s:". 24842 * Return 0 otherwise. 24843 */ 24844 static int 24845 eval_fname_script(char_u *p) 24846 { 24847 /* Use MB_STRICMP() because in Turkish comparing the "I" may not work with 24848 * the standard library function. */ 24849 if (p[0] == '<' && (MB_STRNICMP(p + 1, "SID>", 4) == 0 24850 || MB_STRNICMP(p + 1, "SNR>", 4) == 0)) 24851 return 5; 24852 if (p[0] == 's' && p[1] == ':') 24853 return 2; 24854 return 0; 24855 } 24856 24857 /* 24858 * Return TRUE if "p" starts with "<SID>" or "s:". 24859 * Only works if eval_fname_script() returned non-zero for "p"! 24860 */ 24861 static int 24862 eval_fname_sid(char_u *p) 24863 { 24864 return (*p == 's' || TOUPPER_ASC(p[2]) == 'I'); 24865 } 24866 24867 /* 24868 * List the head of the function: "name(arg1, arg2)". 24869 */ 24870 static void 24871 list_func_head(ufunc_T *fp, int indent) 24872 { 24873 int j; 24874 24875 msg_start(); 24876 if (indent) 24877 MSG_PUTS(" "); 24878 MSG_PUTS("function "); 24879 if (fp->uf_name[0] == K_SPECIAL) 24880 { 24881 MSG_PUTS_ATTR("<SNR>", hl_attr(HLF_8)); 24882 msg_puts(fp->uf_name + 3); 24883 } 24884 else 24885 msg_puts(fp->uf_name); 24886 msg_putchar('('); 24887 for (j = 0; j < fp->uf_args.ga_len; ++j) 24888 { 24889 if (j) 24890 MSG_PUTS(", "); 24891 msg_puts(FUNCARG(fp, j)); 24892 } 24893 if (fp->uf_varargs) 24894 { 24895 if (j) 24896 MSG_PUTS(", "); 24897 MSG_PUTS("..."); 24898 } 24899 msg_putchar(')'); 24900 if (fp->uf_flags & FC_ABORT) 24901 MSG_PUTS(" abort"); 24902 if (fp->uf_flags & FC_RANGE) 24903 MSG_PUTS(" range"); 24904 if (fp->uf_flags & FC_DICT) 24905 MSG_PUTS(" dict"); 24906 msg_clr_eos(); 24907 if (p_verbose > 0) 24908 last_set_msg(fp->uf_script_ID); 24909 } 24910 24911 /* 24912 * Find a function by name, return pointer to it in ufuncs. 24913 * Return NULL for unknown function. 24914 */ 24915 static ufunc_T * 24916 find_func(char_u *name) 24917 { 24918 hashitem_T *hi; 24919 24920 hi = hash_find(&func_hashtab, name); 24921 if (!HASHITEM_EMPTY(hi)) 24922 return HI2UF(hi); 24923 return NULL; 24924 } 24925 24926 #if defined(EXITFREE) || defined(PROTO) 24927 void 24928 free_all_functions(void) 24929 { 24930 hashitem_T *hi; 24931 24932 /* Need to start all over every time, because func_free() may change the 24933 * hash table. */ 24934 while (func_hashtab.ht_used > 0) 24935 for (hi = func_hashtab.ht_array; ; ++hi) 24936 if (!HASHITEM_EMPTY(hi)) 24937 { 24938 func_free(HI2UF(hi)); 24939 break; 24940 } 24941 } 24942 #endif 24943 24944 int 24945 translated_function_exists(char_u *name) 24946 { 24947 if (builtin_function(name, -1)) 24948 return find_internal_func(name) >= 0; 24949 return find_func(name) != NULL; 24950 } 24951 24952 /* 24953 * Return TRUE if a function "name" exists. 24954 */ 24955 static int 24956 function_exists(char_u *name) 24957 { 24958 char_u *nm = name; 24959 char_u *p; 24960 int n = FALSE; 24961 24962 p = trans_function_name(&nm, FALSE, TFN_INT|TFN_QUIET|TFN_NO_AUTOLOAD, 24963 NULL, NULL); 24964 nm = skipwhite(nm); 24965 24966 /* Only accept "funcname", "funcname ", "funcname (..." and 24967 * "funcname(...", not "funcname!...". */ 24968 if (p != NULL && (*nm == NUL || *nm == '(')) 24969 n = translated_function_exists(p); 24970 vim_free(p); 24971 return n; 24972 } 24973 24974 char_u * 24975 get_expanded_name(char_u *name, int check) 24976 { 24977 char_u *nm = name; 24978 char_u *p; 24979 24980 p = trans_function_name(&nm, FALSE, TFN_INT|TFN_QUIET, NULL, NULL); 24981 24982 if (p != NULL && *nm == NUL) 24983 if (!check || translated_function_exists(p)) 24984 return p; 24985 24986 vim_free(p); 24987 return NULL; 24988 } 24989 24990 /* 24991 * Return TRUE if "name" looks like a builtin function name: starts with a 24992 * lower case letter and doesn't contain AUTOLOAD_CHAR. 24993 * "len" is the length of "name", or -1 for NUL terminated. 24994 */ 24995 static int 24996 builtin_function(char_u *name, int len) 24997 { 24998 char_u *p; 24999 25000 if (!ASCII_ISLOWER(name[0])) 25001 return FALSE; 25002 p = vim_strchr(name, AUTOLOAD_CHAR); 25003 return p == NULL || (len > 0 && p > name + len); 25004 } 25005 25006 #if defined(FEAT_PROFILE) || defined(PROTO) 25007 /* 25008 * Start profiling function "fp". 25009 */ 25010 static void 25011 func_do_profile(ufunc_T *fp) 25012 { 25013 int len = fp->uf_lines.ga_len; 25014 25015 if (len == 0) 25016 len = 1; /* avoid getting error for allocating zero bytes */ 25017 fp->uf_tm_count = 0; 25018 profile_zero(&fp->uf_tm_self); 25019 profile_zero(&fp->uf_tm_total); 25020 if (fp->uf_tml_count == NULL) 25021 fp->uf_tml_count = (int *)alloc_clear((unsigned) (sizeof(int) * len)); 25022 if (fp->uf_tml_total == NULL) 25023 fp->uf_tml_total = (proftime_T *)alloc_clear((unsigned) 25024 (sizeof(proftime_T) * len)); 25025 if (fp->uf_tml_self == NULL) 25026 fp->uf_tml_self = (proftime_T *)alloc_clear((unsigned) 25027 (sizeof(proftime_T) * len)); 25028 fp->uf_tml_idx = -1; 25029 if (fp->uf_tml_count == NULL || fp->uf_tml_total == NULL 25030 || fp->uf_tml_self == NULL) 25031 return; /* out of memory */ 25032 25033 fp->uf_profiling = TRUE; 25034 } 25035 25036 /* 25037 * Dump the profiling results for all functions in file "fd". 25038 */ 25039 void 25040 func_dump_profile(FILE *fd) 25041 { 25042 hashitem_T *hi; 25043 int todo; 25044 ufunc_T *fp; 25045 int i; 25046 ufunc_T **sorttab; 25047 int st_len = 0; 25048 25049 todo = (int)func_hashtab.ht_used; 25050 if (todo == 0) 25051 return; /* nothing to dump */ 25052 25053 sorttab = (ufunc_T **)alloc((unsigned)(sizeof(ufunc_T *) * todo)); 25054 25055 for (hi = func_hashtab.ht_array; todo > 0; ++hi) 25056 { 25057 if (!HASHITEM_EMPTY(hi)) 25058 { 25059 --todo; 25060 fp = HI2UF(hi); 25061 if (fp->uf_profiling) 25062 { 25063 if (sorttab != NULL) 25064 sorttab[st_len++] = fp; 25065 25066 if (fp->uf_name[0] == K_SPECIAL) 25067 fprintf(fd, "FUNCTION <SNR>%s()\n", fp->uf_name + 3); 25068 else 25069 fprintf(fd, "FUNCTION %s()\n", fp->uf_name); 25070 if (fp->uf_tm_count == 1) 25071 fprintf(fd, "Called 1 time\n"); 25072 else 25073 fprintf(fd, "Called %d times\n", fp->uf_tm_count); 25074 fprintf(fd, "Total time: %s\n", profile_msg(&fp->uf_tm_total)); 25075 fprintf(fd, " Self time: %s\n", profile_msg(&fp->uf_tm_self)); 25076 fprintf(fd, "\n"); 25077 fprintf(fd, "count total (s) self (s)\n"); 25078 25079 for (i = 0; i < fp->uf_lines.ga_len; ++i) 25080 { 25081 if (FUNCLINE(fp, i) == NULL) 25082 continue; 25083 prof_func_line(fd, fp->uf_tml_count[i], 25084 &fp->uf_tml_total[i], &fp->uf_tml_self[i], TRUE); 25085 fprintf(fd, "%s\n", FUNCLINE(fp, i)); 25086 } 25087 fprintf(fd, "\n"); 25088 } 25089 } 25090 } 25091 25092 if (sorttab != NULL && st_len > 0) 25093 { 25094 qsort((void *)sorttab, (size_t)st_len, sizeof(ufunc_T *), 25095 prof_total_cmp); 25096 prof_sort_list(fd, sorttab, st_len, "TOTAL", FALSE); 25097 qsort((void *)sorttab, (size_t)st_len, sizeof(ufunc_T *), 25098 prof_self_cmp); 25099 prof_sort_list(fd, sorttab, st_len, "SELF", TRUE); 25100 } 25101 25102 vim_free(sorttab); 25103 } 25104 25105 static void 25106 prof_sort_list( 25107 FILE *fd, 25108 ufunc_T **sorttab, 25109 int st_len, 25110 char *title, 25111 int prefer_self) /* when equal print only self time */ 25112 { 25113 int i; 25114 ufunc_T *fp; 25115 25116 fprintf(fd, "FUNCTIONS SORTED ON %s TIME\n", title); 25117 fprintf(fd, "count total (s) self (s) function\n"); 25118 for (i = 0; i < 20 && i < st_len; ++i) 25119 { 25120 fp = sorttab[i]; 25121 prof_func_line(fd, fp->uf_tm_count, &fp->uf_tm_total, &fp->uf_tm_self, 25122 prefer_self); 25123 if (fp->uf_name[0] == K_SPECIAL) 25124 fprintf(fd, " <SNR>%s()\n", fp->uf_name + 3); 25125 else 25126 fprintf(fd, " %s()\n", fp->uf_name); 25127 } 25128 fprintf(fd, "\n"); 25129 } 25130 25131 /* 25132 * Print the count and times for one function or function line. 25133 */ 25134 static void 25135 prof_func_line( 25136 FILE *fd, 25137 int count, 25138 proftime_T *total, 25139 proftime_T *self, 25140 int prefer_self) /* when equal print only self time */ 25141 { 25142 if (count > 0) 25143 { 25144 fprintf(fd, "%5d ", count); 25145 if (prefer_self && profile_equal(total, self)) 25146 fprintf(fd, " "); 25147 else 25148 fprintf(fd, "%s ", profile_msg(total)); 25149 if (!prefer_self && profile_equal(total, self)) 25150 fprintf(fd, " "); 25151 else 25152 fprintf(fd, "%s ", profile_msg(self)); 25153 } 25154 else 25155 fprintf(fd, " "); 25156 } 25157 25158 /* 25159 * Compare function for total time sorting. 25160 */ 25161 static int 25162 #ifdef __BORLANDC__ 25163 _RTLENTRYF 25164 #endif 25165 prof_total_cmp(const void *s1, const void *s2) 25166 { 25167 ufunc_T *p1, *p2; 25168 25169 p1 = *(ufunc_T **)s1; 25170 p2 = *(ufunc_T **)s2; 25171 return profile_cmp(&p1->uf_tm_total, &p2->uf_tm_total); 25172 } 25173 25174 /* 25175 * Compare function for self time sorting. 25176 */ 25177 static int 25178 #ifdef __BORLANDC__ 25179 _RTLENTRYF 25180 #endif 25181 prof_self_cmp(const void *s1, const void *s2) 25182 { 25183 ufunc_T *p1, *p2; 25184 25185 p1 = *(ufunc_T **)s1; 25186 p2 = *(ufunc_T **)s2; 25187 return profile_cmp(&p1->uf_tm_self, &p2->uf_tm_self); 25188 } 25189 25190 #endif 25191 25192 /* 25193 * If "name" has a package name try autoloading the script for it. 25194 * Return TRUE if a package was loaded. 25195 */ 25196 static int 25197 script_autoload( 25198 char_u *name, 25199 int reload) /* load script again when already loaded */ 25200 { 25201 char_u *p; 25202 char_u *scriptname, *tofree; 25203 int ret = FALSE; 25204 int i; 25205 25206 /* If there is no '#' after name[0] there is no package name. */ 25207 p = vim_strchr(name, AUTOLOAD_CHAR); 25208 if (p == NULL || p == name) 25209 return FALSE; 25210 25211 tofree = scriptname = autoload_name(name); 25212 25213 /* Find the name in the list of previously loaded package names. Skip 25214 * "autoload/", it's always the same. */ 25215 for (i = 0; i < ga_loaded.ga_len; ++i) 25216 if (STRCMP(((char_u **)ga_loaded.ga_data)[i] + 9, scriptname + 9) == 0) 25217 break; 25218 if (!reload && i < ga_loaded.ga_len) 25219 ret = FALSE; /* was loaded already */ 25220 else 25221 { 25222 /* Remember the name if it wasn't loaded already. */ 25223 if (i == ga_loaded.ga_len && ga_grow(&ga_loaded, 1) == OK) 25224 { 25225 ((char_u **)ga_loaded.ga_data)[ga_loaded.ga_len++] = scriptname; 25226 tofree = NULL; 25227 } 25228 25229 /* Try loading the package from $VIMRUNTIME/autoload/<name>.vim */ 25230 if (source_runtime(scriptname, 0) == OK) 25231 ret = TRUE; 25232 } 25233 25234 vim_free(tofree); 25235 return ret; 25236 } 25237 25238 /* 25239 * Return the autoload script name for a function or variable name. 25240 * Returns NULL when out of memory. 25241 */ 25242 static char_u * 25243 autoload_name(char_u *name) 25244 { 25245 char_u *p; 25246 char_u *scriptname; 25247 25248 /* Get the script file name: replace '#' with '/', append ".vim". */ 25249 scriptname = alloc((unsigned)(STRLEN(name) + 14)); 25250 if (scriptname == NULL) 25251 return FALSE; 25252 STRCPY(scriptname, "autoload/"); 25253 STRCAT(scriptname, name); 25254 *vim_strrchr(scriptname, AUTOLOAD_CHAR) = NUL; 25255 STRCAT(scriptname, ".vim"); 25256 while ((p = vim_strchr(scriptname, AUTOLOAD_CHAR)) != NULL) 25257 *p = '/'; 25258 return scriptname; 25259 } 25260 25261 #if defined(FEAT_CMDL_COMPL) || defined(PROTO) 25262 25263 /* 25264 * Function given to ExpandGeneric() to obtain the list of user defined 25265 * function names. 25266 */ 25267 char_u * 25268 get_user_func_name(expand_T *xp, int idx) 25269 { 25270 static long_u done; 25271 static hashitem_T *hi; 25272 ufunc_T *fp; 25273 25274 if (idx == 0) 25275 { 25276 done = 0; 25277 hi = func_hashtab.ht_array; 25278 } 25279 if (done < func_hashtab.ht_used) 25280 { 25281 if (done++ > 0) 25282 ++hi; 25283 while (HASHITEM_EMPTY(hi)) 25284 ++hi; 25285 fp = HI2UF(hi); 25286 25287 if (fp->uf_flags & FC_DICT) 25288 return (char_u *)""; /* don't show dict functions */ 25289 25290 if (STRLEN(fp->uf_name) + 4 >= IOSIZE) 25291 return fp->uf_name; /* prevents overflow */ 25292 25293 cat_func_name(IObuff, fp); 25294 if (xp->xp_context != EXPAND_USER_FUNC) 25295 { 25296 STRCAT(IObuff, "("); 25297 if (!fp->uf_varargs && fp->uf_args.ga_len == 0) 25298 STRCAT(IObuff, ")"); 25299 } 25300 return IObuff; 25301 } 25302 return NULL; 25303 } 25304 25305 #endif /* FEAT_CMDL_COMPL */ 25306 25307 /* 25308 * Copy the function name of "fp" to buffer "buf". 25309 * "buf" must be able to hold the function name plus three bytes. 25310 * Takes care of script-local function names. 25311 */ 25312 static void 25313 cat_func_name(char_u *buf, ufunc_T *fp) 25314 { 25315 if (fp->uf_name[0] == K_SPECIAL) 25316 { 25317 STRCPY(buf, "<SNR>"); 25318 STRCAT(buf, fp->uf_name + 3); 25319 } 25320 else 25321 STRCPY(buf, fp->uf_name); 25322 } 25323 25324 /* 25325 * ":delfunction {name}" 25326 */ 25327 void 25328 ex_delfunction(exarg_T *eap) 25329 { 25330 ufunc_T *fp = NULL; 25331 char_u *p; 25332 char_u *name; 25333 funcdict_T fudi; 25334 25335 p = eap->arg; 25336 name = trans_function_name(&p, eap->skip, 0, &fudi, NULL); 25337 vim_free(fudi.fd_newkey); 25338 if (name == NULL) 25339 { 25340 if (fudi.fd_dict != NULL && !eap->skip) 25341 EMSG(_(e_funcref)); 25342 return; 25343 } 25344 if (!ends_excmd(*skipwhite(p))) 25345 { 25346 vim_free(name); 25347 EMSG(_(e_trailing)); 25348 return; 25349 } 25350 eap->nextcmd = check_nextcmd(p); 25351 if (eap->nextcmd != NULL) 25352 *p = NUL; 25353 25354 if (!eap->skip) 25355 fp = find_func(name); 25356 vim_free(name); 25357 25358 if (!eap->skip) 25359 { 25360 if (fp == NULL) 25361 { 25362 EMSG2(_(e_nofunc), eap->arg); 25363 return; 25364 } 25365 if (fp->uf_calls > 0) 25366 { 25367 EMSG2(_("E131: Cannot delete function %s: It is in use"), eap->arg); 25368 return; 25369 } 25370 25371 if (fudi.fd_dict != NULL) 25372 { 25373 /* Delete the dict item that refers to the function, it will 25374 * invoke func_unref() and possibly delete the function. */ 25375 dictitem_remove(fudi.fd_dict, fudi.fd_di); 25376 } 25377 else 25378 func_free(fp); 25379 } 25380 } 25381 25382 /* 25383 * Free a function and remove it from the list of functions. 25384 */ 25385 static void 25386 func_free(ufunc_T *fp) 25387 { 25388 hashitem_T *hi; 25389 25390 /* clear this function */ 25391 ga_clear_strings(&(fp->uf_args)); 25392 ga_clear_strings(&(fp->uf_lines)); 25393 #ifdef FEAT_PROFILE 25394 vim_free(fp->uf_tml_count); 25395 vim_free(fp->uf_tml_total); 25396 vim_free(fp->uf_tml_self); 25397 #endif 25398 25399 /* remove the function from the function hashtable */ 25400 hi = hash_find(&func_hashtab, UF2HIKEY(fp)); 25401 if (HASHITEM_EMPTY(hi)) 25402 EMSG2(_(e_intern2), "func_free()"); 25403 else 25404 hash_remove(&func_hashtab, hi); 25405 25406 vim_free(fp); 25407 } 25408 25409 /* 25410 * Unreference a Function: decrement the reference count and free it when it 25411 * becomes zero. Only for numbered functions. 25412 */ 25413 void 25414 func_unref(char_u *name) 25415 { 25416 ufunc_T *fp; 25417 25418 if (name != NULL && isdigit(*name)) 25419 { 25420 fp = find_func(name); 25421 if (fp == NULL) 25422 { 25423 #ifdef EXITFREE 25424 if (!entered_free_all_mem) 25425 #endif 25426 EMSG2(_(e_intern2), "func_unref()"); 25427 } 25428 else if (--fp->uf_refcount <= 0) 25429 { 25430 /* Only delete it when it's not being used. Otherwise it's done 25431 * when "uf_calls" becomes zero. */ 25432 if (fp->uf_calls == 0) 25433 func_free(fp); 25434 } 25435 } 25436 } 25437 25438 /* 25439 * Count a reference to a Function. 25440 */ 25441 void 25442 func_ref(char_u *name) 25443 { 25444 ufunc_T *fp; 25445 25446 if (name != NULL && isdigit(*name)) 25447 { 25448 fp = find_func(name); 25449 if (fp == NULL) 25450 EMSG2(_(e_intern2), "func_ref()"); 25451 else 25452 ++fp->uf_refcount; 25453 } 25454 } 25455 25456 /* 25457 * Call a user function. 25458 */ 25459 static void 25460 call_user_func( 25461 ufunc_T *fp, /* pointer to function */ 25462 int argcount, /* nr of args */ 25463 typval_T *argvars, /* arguments */ 25464 typval_T *rettv, /* return value */ 25465 linenr_T firstline, /* first line of range */ 25466 linenr_T lastline, /* last line of range */ 25467 dict_T *selfdict) /* Dictionary for "self" */ 25468 { 25469 char_u *save_sourcing_name; 25470 linenr_T save_sourcing_lnum; 25471 scid_T save_current_SID; 25472 funccall_T *fc; 25473 int save_did_emsg; 25474 static int depth = 0; 25475 dictitem_T *v; 25476 int fixvar_idx = 0; /* index in fixvar[] */ 25477 int i; 25478 int ai; 25479 char_u numbuf[NUMBUFLEN]; 25480 char_u *name; 25481 size_t len; 25482 #ifdef FEAT_PROFILE 25483 proftime_T wait_start; 25484 proftime_T call_start; 25485 #endif 25486 25487 /* If depth of calling is getting too high, don't execute the function */ 25488 if (depth >= p_mfd) 25489 { 25490 EMSG(_("E132: Function call depth is higher than 'maxfuncdepth'")); 25491 rettv->v_type = VAR_NUMBER; 25492 rettv->vval.v_number = -1; 25493 return; 25494 } 25495 ++depth; 25496 25497 line_breakcheck(); /* check for CTRL-C hit */ 25498 25499 fc = (funccall_T *)alloc(sizeof(funccall_T)); 25500 fc->caller = current_funccal; 25501 current_funccal = fc; 25502 fc->func = fp; 25503 fc->rettv = rettv; 25504 rettv->vval.v_number = 0; 25505 fc->linenr = 0; 25506 fc->returned = FALSE; 25507 fc->level = ex_nesting_level; 25508 /* Check if this function has a breakpoint. */ 25509 fc->breakpoint = dbg_find_breakpoint(FALSE, fp->uf_name, (linenr_T)0); 25510 fc->dbg_tick = debug_tick; 25511 25512 /* 25513 * Note about using fc->fixvar[]: This is an array of FIXVAR_CNT variables 25514 * with names up to VAR_SHORT_LEN long. This avoids having to alloc/free 25515 * each argument variable and saves a lot of time. 25516 */ 25517 /* 25518 * Init l: variables. 25519 */ 25520 init_var_dict(&fc->l_vars, &fc->l_vars_var, VAR_DEF_SCOPE); 25521 if (selfdict != NULL) 25522 { 25523 /* Set l:self to "selfdict". Use "name" to avoid a warning from 25524 * some compiler that checks the destination size. */ 25525 v = &fc->fixvar[fixvar_idx++].var; 25526 name = v->di_key; 25527 STRCPY(name, "self"); 25528 v->di_flags = DI_FLAGS_RO + DI_FLAGS_FIX; 25529 hash_add(&fc->l_vars.dv_hashtab, DI2HIKEY(v)); 25530 v->di_tv.v_type = VAR_DICT; 25531 v->di_tv.v_lock = 0; 25532 v->di_tv.vval.v_dict = selfdict; 25533 ++selfdict->dv_refcount; 25534 } 25535 25536 /* 25537 * Init a: variables. 25538 * Set a:0 to "argcount". 25539 * Set a:000 to a list with room for the "..." arguments. 25540 */ 25541 init_var_dict(&fc->l_avars, &fc->l_avars_var, VAR_SCOPE); 25542 add_nr_var(&fc->l_avars, &fc->fixvar[fixvar_idx++].var, "0", 25543 (varnumber_T)(argcount - fp->uf_args.ga_len)); 25544 /* Use "name" to avoid a warning from some compiler that checks the 25545 * destination size. */ 25546 v = &fc->fixvar[fixvar_idx++].var; 25547 name = v->di_key; 25548 STRCPY(name, "000"); 25549 v->di_flags = DI_FLAGS_RO | DI_FLAGS_FIX; 25550 hash_add(&fc->l_avars.dv_hashtab, DI2HIKEY(v)); 25551 v->di_tv.v_type = VAR_LIST; 25552 v->di_tv.v_lock = VAR_FIXED; 25553 v->di_tv.vval.v_list = &fc->l_varlist; 25554 vim_memset(&fc->l_varlist, 0, sizeof(list_T)); 25555 fc->l_varlist.lv_refcount = DO_NOT_FREE_CNT; 25556 fc->l_varlist.lv_lock = VAR_FIXED; 25557 25558 /* 25559 * Set a:firstline to "firstline" and a:lastline to "lastline". 25560 * Set a:name to named arguments. 25561 * Set a:N to the "..." arguments. 25562 */ 25563 add_nr_var(&fc->l_avars, &fc->fixvar[fixvar_idx++].var, "firstline", 25564 (varnumber_T)firstline); 25565 add_nr_var(&fc->l_avars, &fc->fixvar[fixvar_idx++].var, "lastline", 25566 (varnumber_T)lastline); 25567 for (i = 0; i < argcount; ++i) 25568 { 25569 ai = i - fp->uf_args.ga_len; 25570 if (ai < 0) 25571 /* named argument a:name */ 25572 name = FUNCARG(fp, i); 25573 else 25574 { 25575 /* "..." argument a:1, a:2, etc. */ 25576 sprintf((char *)numbuf, "%d", ai + 1); 25577 name = numbuf; 25578 } 25579 if (fixvar_idx < FIXVAR_CNT && STRLEN(name) <= VAR_SHORT_LEN) 25580 { 25581 v = &fc->fixvar[fixvar_idx++].var; 25582 v->di_flags = DI_FLAGS_RO | DI_FLAGS_FIX; 25583 } 25584 else 25585 { 25586 v = (dictitem_T *)alloc((unsigned)(sizeof(dictitem_T) 25587 + STRLEN(name))); 25588 if (v == NULL) 25589 break; 25590 v->di_flags = DI_FLAGS_RO | DI_FLAGS_FIX | DI_FLAGS_ALLOC; 25591 } 25592 STRCPY(v->di_key, name); 25593 hash_add(&fc->l_avars.dv_hashtab, DI2HIKEY(v)); 25594 25595 /* Note: the values are copied directly to avoid alloc/free. 25596 * "argvars" must have VAR_FIXED for v_lock. */ 25597 v->di_tv = argvars[i]; 25598 v->di_tv.v_lock = VAR_FIXED; 25599 25600 if (ai >= 0 && ai < MAX_FUNC_ARGS) 25601 { 25602 list_append(&fc->l_varlist, &fc->l_listitems[ai]); 25603 fc->l_listitems[ai].li_tv = argvars[i]; 25604 fc->l_listitems[ai].li_tv.v_lock = VAR_FIXED; 25605 } 25606 } 25607 25608 /* Don't redraw while executing the function. */ 25609 ++RedrawingDisabled; 25610 save_sourcing_name = sourcing_name; 25611 save_sourcing_lnum = sourcing_lnum; 25612 sourcing_lnum = 1; 25613 /* need space for function name + ("function " + 3) or "[number]" */ 25614 len = (save_sourcing_name == NULL ? 0 : STRLEN(save_sourcing_name)) 25615 + STRLEN(fp->uf_name) + 20; 25616 sourcing_name = alloc((unsigned)len); 25617 if (sourcing_name != NULL) 25618 { 25619 if (save_sourcing_name != NULL 25620 && STRNCMP(save_sourcing_name, "function ", 9) == 0) 25621 sprintf((char *)sourcing_name, "%s[%d]..", 25622 save_sourcing_name, (int)save_sourcing_lnum); 25623 else 25624 STRCPY(sourcing_name, "function "); 25625 cat_func_name(sourcing_name + STRLEN(sourcing_name), fp); 25626 25627 if (p_verbose >= 12) 25628 { 25629 ++no_wait_return; 25630 verbose_enter_scroll(); 25631 25632 smsg((char_u *)_("calling %s"), sourcing_name); 25633 if (p_verbose >= 14) 25634 { 25635 char_u buf[MSG_BUF_LEN]; 25636 char_u numbuf2[NUMBUFLEN]; 25637 char_u *tofree; 25638 char_u *s; 25639 25640 msg_puts((char_u *)"("); 25641 for (i = 0; i < argcount; ++i) 25642 { 25643 if (i > 0) 25644 msg_puts((char_u *)", "); 25645 if (argvars[i].v_type == VAR_NUMBER) 25646 msg_outnum((long)argvars[i].vval.v_number); 25647 else 25648 { 25649 /* Do not want errors such as E724 here. */ 25650 ++emsg_off; 25651 s = tv2string(&argvars[i], &tofree, numbuf2, 0); 25652 --emsg_off; 25653 if (s != NULL) 25654 { 25655 if (vim_strsize(s) > MSG_BUF_CLEN) 25656 { 25657 trunc_string(s, buf, MSG_BUF_CLEN, MSG_BUF_LEN); 25658 s = buf; 25659 } 25660 msg_puts(s); 25661 vim_free(tofree); 25662 } 25663 } 25664 } 25665 msg_puts((char_u *)")"); 25666 } 25667 msg_puts((char_u *)"\n"); /* don't overwrite this either */ 25668 25669 verbose_leave_scroll(); 25670 --no_wait_return; 25671 } 25672 } 25673 #ifdef FEAT_PROFILE 25674 if (do_profiling == PROF_YES) 25675 { 25676 if (!fp->uf_profiling && has_profiling(FALSE, fp->uf_name, NULL)) 25677 func_do_profile(fp); 25678 if (fp->uf_profiling 25679 || (fc->caller != NULL && fc->caller->func->uf_profiling)) 25680 { 25681 ++fp->uf_tm_count; 25682 profile_start(&call_start); 25683 profile_zero(&fp->uf_tm_children); 25684 } 25685 script_prof_save(&wait_start); 25686 } 25687 #endif 25688 25689 save_current_SID = current_SID; 25690 current_SID = fp->uf_script_ID; 25691 save_did_emsg = did_emsg; 25692 did_emsg = FALSE; 25693 25694 /* call do_cmdline() to execute the lines */ 25695 do_cmdline(NULL, get_func_line, (void *)fc, 25696 DOCMD_NOWAIT|DOCMD_VERBOSE|DOCMD_REPEAT); 25697 25698 --RedrawingDisabled; 25699 25700 /* when the function was aborted because of an error, return -1 */ 25701 if ((did_emsg && (fp->uf_flags & FC_ABORT)) || rettv->v_type == VAR_UNKNOWN) 25702 { 25703 clear_tv(rettv); 25704 rettv->v_type = VAR_NUMBER; 25705 rettv->vval.v_number = -1; 25706 } 25707 25708 #ifdef FEAT_PROFILE 25709 if (do_profiling == PROF_YES && (fp->uf_profiling 25710 || (fc->caller != NULL && fc->caller->func->uf_profiling))) 25711 { 25712 profile_end(&call_start); 25713 profile_sub_wait(&wait_start, &call_start); 25714 profile_add(&fp->uf_tm_total, &call_start); 25715 profile_self(&fp->uf_tm_self, &call_start, &fp->uf_tm_children); 25716 if (fc->caller != NULL && fc->caller->func->uf_profiling) 25717 { 25718 profile_add(&fc->caller->func->uf_tm_children, &call_start); 25719 profile_add(&fc->caller->func->uf_tml_children, &call_start); 25720 } 25721 } 25722 #endif 25723 25724 /* when being verbose, mention the return value */ 25725 if (p_verbose >= 12) 25726 { 25727 ++no_wait_return; 25728 verbose_enter_scroll(); 25729 25730 if (aborting()) 25731 smsg((char_u *)_("%s aborted"), sourcing_name); 25732 else if (fc->rettv->v_type == VAR_NUMBER) 25733 smsg((char_u *)_("%s returning #%ld"), sourcing_name, 25734 (long)fc->rettv->vval.v_number); 25735 else 25736 { 25737 char_u buf[MSG_BUF_LEN]; 25738 char_u numbuf2[NUMBUFLEN]; 25739 char_u *tofree; 25740 char_u *s; 25741 25742 /* The value may be very long. Skip the middle part, so that we 25743 * have some idea how it starts and ends. smsg() would always 25744 * truncate it at the end. Don't want errors such as E724 here. */ 25745 ++emsg_off; 25746 s = tv2string(fc->rettv, &tofree, numbuf2, 0); 25747 --emsg_off; 25748 if (s != NULL) 25749 { 25750 if (vim_strsize(s) > MSG_BUF_CLEN) 25751 { 25752 trunc_string(s, buf, MSG_BUF_CLEN, MSG_BUF_LEN); 25753 s = buf; 25754 } 25755 smsg((char_u *)_("%s returning %s"), sourcing_name, s); 25756 vim_free(tofree); 25757 } 25758 } 25759 msg_puts((char_u *)"\n"); /* don't overwrite this either */ 25760 25761 verbose_leave_scroll(); 25762 --no_wait_return; 25763 } 25764 25765 vim_free(sourcing_name); 25766 sourcing_name = save_sourcing_name; 25767 sourcing_lnum = save_sourcing_lnum; 25768 current_SID = save_current_SID; 25769 #ifdef FEAT_PROFILE 25770 if (do_profiling == PROF_YES) 25771 script_prof_restore(&wait_start); 25772 #endif 25773 25774 if (p_verbose >= 12 && sourcing_name != NULL) 25775 { 25776 ++no_wait_return; 25777 verbose_enter_scroll(); 25778 25779 smsg((char_u *)_("continuing in %s"), sourcing_name); 25780 msg_puts((char_u *)"\n"); /* don't overwrite this either */ 25781 25782 verbose_leave_scroll(); 25783 --no_wait_return; 25784 } 25785 25786 did_emsg |= save_did_emsg; 25787 current_funccal = fc->caller; 25788 --depth; 25789 25790 /* If the a:000 list and the l: and a: dicts are not referenced we can 25791 * free the funccall_T and what's in it. */ 25792 if (fc->l_varlist.lv_refcount == DO_NOT_FREE_CNT 25793 && fc->l_vars.dv_refcount == DO_NOT_FREE_CNT 25794 && fc->l_avars.dv_refcount == DO_NOT_FREE_CNT) 25795 { 25796 free_funccal(fc, FALSE); 25797 } 25798 else 25799 { 25800 hashitem_T *hi; 25801 listitem_T *li; 25802 int todo; 25803 25804 /* "fc" is still in use. This can happen when returning "a:000" or 25805 * assigning "l:" to a global variable. 25806 * Link "fc" in the list for garbage collection later. */ 25807 fc->caller = previous_funccal; 25808 previous_funccal = fc; 25809 25810 /* Make a copy of the a: variables, since we didn't do that above. */ 25811 todo = (int)fc->l_avars.dv_hashtab.ht_used; 25812 for (hi = fc->l_avars.dv_hashtab.ht_array; todo > 0; ++hi) 25813 { 25814 if (!HASHITEM_EMPTY(hi)) 25815 { 25816 --todo; 25817 v = HI2DI(hi); 25818 copy_tv(&v->di_tv, &v->di_tv); 25819 } 25820 } 25821 25822 /* Make a copy of the a:000 items, since we didn't do that above. */ 25823 for (li = fc->l_varlist.lv_first; li != NULL; li = li->li_next) 25824 copy_tv(&li->li_tv, &li->li_tv); 25825 } 25826 } 25827 25828 /* 25829 * Return TRUE if items in "fc" do not have "copyID". That means they are not 25830 * referenced from anywhere that is in use. 25831 */ 25832 static int 25833 can_free_funccal(funccall_T *fc, int copyID) 25834 { 25835 return (fc->l_varlist.lv_copyID != copyID 25836 && fc->l_vars.dv_copyID != copyID 25837 && fc->l_avars.dv_copyID != copyID); 25838 } 25839 25840 /* 25841 * Free "fc" and what it contains. 25842 */ 25843 static void 25844 free_funccal( 25845 funccall_T *fc, 25846 int free_val) /* a: vars were allocated */ 25847 { 25848 listitem_T *li; 25849 25850 /* The a: variables typevals may not have been allocated, only free the 25851 * allocated variables. */ 25852 vars_clear_ext(&fc->l_avars.dv_hashtab, free_val); 25853 25854 /* free all l: variables */ 25855 vars_clear(&fc->l_vars.dv_hashtab); 25856 25857 /* Free the a:000 variables if they were allocated. */ 25858 if (free_val) 25859 for (li = fc->l_varlist.lv_first; li != NULL; li = li->li_next) 25860 clear_tv(&li->li_tv); 25861 25862 vim_free(fc); 25863 } 25864 25865 /* 25866 * Add a number variable "name" to dict "dp" with value "nr". 25867 */ 25868 static void 25869 add_nr_var( 25870 dict_T *dp, 25871 dictitem_T *v, 25872 char *name, 25873 varnumber_T nr) 25874 { 25875 STRCPY(v->di_key, name); 25876 v->di_flags = DI_FLAGS_RO | DI_FLAGS_FIX; 25877 hash_add(&dp->dv_hashtab, DI2HIKEY(v)); 25878 v->di_tv.v_type = VAR_NUMBER; 25879 v->di_tv.v_lock = VAR_FIXED; 25880 v->di_tv.vval.v_number = nr; 25881 } 25882 25883 /* 25884 * ":return [expr]" 25885 */ 25886 void 25887 ex_return(exarg_T *eap) 25888 { 25889 char_u *arg = eap->arg; 25890 typval_T rettv; 25891 int returning = FALSE; 25892 25893 if (current_funccal == NULL) 25894 { 25895 EMSG(_("E133: :return not inside a function")); 25896 return; 25897 } 25898 25899 if (eap->skip) 25900 ++emsg_skip; 25901 25902 eap->nextcmd = NULL; 25903 if ((*arg != NUL && *arg != '|' && *arg != '\n') 25904 && eval0(arg, &rettv, &eap->nextcmd, !eap->skip) != FAIL) 25905 { 25906 if (!eap->skip) 25907 returning = do_return(eap, FALSE, TRUE, &rettv); 25908 else 25909 clear_tv(&rettv); 25910 } 25911 /* It's safer to return also on error. */ 25912 else if (!eap->skip) 25913 { 25914 /* 25915 * Return unless the expression evaluation has been cancelled due to an 25916 * aborting error, an interrupt, or an exception. 25917 */ 25918 if (!aborting()) 25919 returning = do_return(eap, FALSE, TRUE, NULL); 25920 } 25921 25922 /* When skipping or the return gets pending, advance to the next command 25923 * in this line (!returning). Otherwise, ignore the rest of the line. 25924 * Following lines will be ignored by get_func_line(). */ 25925 if (returning) 25926 eap->nextcmd = NULL; 25927 else if (eap->nextcmd == NULL) /* no argument */ 25928 eap->nextcmd = check_nextcmd(arg); 25929 25930 if (eap->skip) 25931 --emsg_skip; 25932 } 25933 25934 /* 25935 * Return from a function. Possibly makes the return pending. Also called 25936 * for a pending return at the ":endtry" or after returning from an extra 25937 * do_cmdline(). "reanimate" is used in the latter case. "is_cmd" is set 25938 * when called due to a ":return" command. "rettv" may point to a typval_T 25939 * with the return rettv. Returns TRUE when the return can be carried out, 25940 * FALSE when the return gets pending. 25941 */ 25942 int 25943 do_return( 25944 exarg_T *eap, 25945 int reanimate, 25946 int is_cmd, 25947 void *rettv) 25948 { 25949 int idx; 25950 struct condstack *cstack = eap->cstack; 25951 25952 if (reanimate) 25953 /* Undo the return. */ 25954 current_funccal->returned = FALSE; 25955 25956 /* 25957 * Cleanup (and inactivate) conditionals, but stop when a try conditional 25958 * not in its finally clause (which then is to be executed next) is found. 25959 * In this case, make the ":return" pending for execution at the ":endtry". 25960 * Otherwise, return normally. 25961 */ 25962 idx = cleanup_conditionals(eap->cstack, 0, TRUE); 25963 if (idx >= 0) 25964 { 25965 cstack->cs_pending[idx] = CSTP_RETURN; 25966 25967 if (!is_cmd && !reanimate) 25968 /* A pending return again gets pending. "rettv" points to an 25969 * allocated variable with the rettv of the original ":return"'s 25970 * argument if present or is NULL else. */ 25971 cstack->cs_rettv[idx] = rettv; 25972 else 25973 { 25974 /* When undoing a return in order to make it pending, get the stored 25975 * return rettv. */ 25976 if (reanimate) 25977 rettv = current_funccal->rettv; 25978 25979 if (rettv != NULL) 25980 { 25981 /* Store the value of the pending return. */ 25982 if ((cstack->cs_rettv[idx] = alloc_tv()) != NULL) 25983 *(typval_T *)cstack->cs_rettv[idx] = *(typval_T *)rettv; 25984 else 25985 EMSG(_(e_outofmem)); 25986 } 25987 else 25988 cstack->cs_rettv[idx] = NULL; 25989 25990 if (reanimate) 25991 { 25992 /* The pending return value could be overwritten by a ":return" 25993 * without argument in a finally clause; reset the default 25994 * return value. */ 25995 current_funccal->rettv->v_type = VAR_NUMBER; 25996 current_funccal->rettv->vval.v_number = 0; 25997 } 25998 } 25999 report_make_pending(CSTP_RETURN, rettv); 26000 } 26001 else 26002 { 26003 current_funccal->returned = TRUE; 26004 26005 /* If the return is carried out now, store the return value. For 26006 * a return immediately after reanimation, the value is already 26007 * there. */ 26008 if (!reanimate && rettv != NULL) 26009 { 26010 clear_tv(current_funccal->rettv); 26011 *current_funccal->rettv = *(typval_T *)rettv; 26012 if (!is_cmd) 26013 vim_free(rettv); 26014 } 26015 } 26016 26017 return idx < 0; 26018 } 26019 26020 /* 26021 * Free the variable with a pending return value. 26022 */ 26023 void 26024 discard_pending_return(void *rettv) 26025 { 26026 free_tv((typval_T *)rettv); 26027 } 26028 26029 /* 26030 * Generate a return command for producing the value of "rettv". The result 26031 * is an allocated string. Used by report_pending() for verbose messages. 26032 */ 26033 char_u * 26034 get_return_cmd(void *rettv) 26035 { 26036 char_u *s = NULL; 26037 char_u *tofree = NULL; 26038 char_u numbuf[NUMBUFLEN]; 26039 26040 if (rettv != NULL) 26041 s = echo_string((typval_T *)rettv, &tofree, numbuf, 0); 26042 if (s == NULL) 26043 s = (char_u *)""; 26044 26045 STRCPY(IObuff, ":return "); 26046 STRNCPY(IObuff + 8, s, IOSIZE - 8); 26047 if (STRLEN(s) + 8 >= IOSIZE) 26048 STRCPY(IObuff + IOSIZE - 4, "..."); 26049 vim_free(tofree); 26050 return vim_strsave(IObuff); 26051 } 26052 26053 /* 26054 * Get next function line. 26055 * Called by do_cmdline() to get the next line. 26056 * Returns allocated string, or NULL for end of function. 26057 */ 26058 char_u * 26059 get_func_line( 26060 int c UNUSED, 26061 void *cookie, 26062 int indent UNUSED) 26063 { 26064 funccall_T *fcp = (funccall_T *)cookie; 26065 ufunc_T *fp = fcp->func; 26066 char_u *retval; 26067 garray_T *gap; /* growarray with function lines */ 26068 26069 /* If breakpoints have been added/deleted need to check for it. */ 26070 if (fcp->dbg_tick != debug_tick) 26071 { 26072 fcp->breakpoint = dbg_find_breakpoint(FALSE, fp->uf_name, 26073 sourcing_lnum); 26074 fcp->dbg_tick = debug_tick; 26075 } 26076 #ifdef FEAT_PROFILE 26077 if (do_profiling == PROF_YES) 26078 func_line_end(cookie); 26079 #endif 26080 26081 gap = &fp->uf_lines; 26082 if (((fp->uf_flags & FC_ABORT) && did_emsg && !aborted_in_try()) 26083 || fcp->returned) 26084 retval = NULL; 26085 else 26086 { 26087 /* Skip NULL lines (continuation lines). */ 26088 while (fcp->linenr < gap->ga_len 26089 && ((char_u **)(gap->ga_data))[fcp->linenr] == NULL) 26090 ++fcp->linenr; 26091 if (fcp->linenr >= gap->ga_len) 26092 retval = NULL; 26093 else 26094 { 26095 retval = vim_strsave(((char_u **)(gap->ga_data))[fcp->linenr++]); 26096 sourcing_lnum = fcp->linenr; 26097 #ifdef FEAT_PROFILE 26098 if (do_profiling == PROF_YES) 26099 func_line_start(cookie); 26100 #endif 26101 } 26102 } 26103 26104 /* Did we encounter a breakpoint? */ 26105 if (fcp->breakpoint != 0 && fcp->breakpoint <= sourcing_lnum) 26106 { 26107 dbg_breakpoint(fp->uf_name, sourcing_lnum); 26108 /* Find next breakpoint. */ 26109 fcp->breakpoint = dbg_find_breakpoint(FALSE, fp->uf_name, 26110 sourcing_lnum); 26111 fcp->dbg_tick = debug_tick; 26112 } 26113 26114 return retval; 26115 } 26116 26117 #if defined(FEAT_PROFILE) || defined(PROTO) 26118 /* 26119 * Called when starting to read a function line. 26120 * "sourcing_lnum" must be correct! 26121 * When skipping lines it may not actually be executed, but we won't find out 26122 * until later and we need to store the time now. 26123 */ 26124 void 26125 func_line_start(void *cookie) 26126 { 26127 funccall_T *fcp = (funccall_T *)cookie; 26128 ufunc_T *fp = fcp->func; 26129 26130 if (fp->uf_profiling && sourcing_lnum >= 1 26131 && sourcing_lnum <= fp->uf_lines.ga_len) 26132 { 26133 fp->uf_tml_idx = sourcing_lnum - 1; 26134 /* Skip continuation lines. */ 26135 while (fp->uf_tml_idx > 0 && FUNCLINE(fp, fp->uf_tml_idx) == NULL) 26136 --fp->uf_tml_idx; 26137 fp->uf_tml_execed = FALSE; 26138 profile_start(&fp->uf_tml_start); 26139 profile_zero(&fp->uf_tml_children); 26140 profile_get_wait(&fp->uf_tml_wait); 26141 } 26142 } 26143 26144 /* 26145 * Called when actually executing a function line. 26146 */ 26147 void 26148 func_line_exec(void *cookie) 26149 { 26150 funccall_T *fcp = (funccall_T *)cookie; 26151 ufunc_T *fp = fcp->func; 26152 26153 if (fp->uf_profiling && fp->uf_tml_idx >= 0) 26154 fp->uf_tml_execed = TRUE; 26155 } 26156 26157 /* 26158 * Called when done with a function line. 26159 */ 26160 void 26161 func_line_end(void *cookie) 26162 { 26163 funccall_T *fcp = (funccall_T *)cookie; 26164 ufunc_T *fp = fcp->func; 26165 26166 if (fp->uf_profiling && fp->uf_tml_idx >= 0) 26167 { 26168 if (fp->uf_tml_execed) 26169 { 26170 ++fp->uf_tml_count[fp->uf_tml_idx]; 26171 profile_end(&fp->uf_tml_start); 26172 profile_sub_wait(&fp->uf_tml_wait, &fp->uf_tml_start); 26173 profile_add(&fp->uf_tml_total[fp->uf_tml_idx], &fp->uf_tml_start); 26174 profile_self(&fp->uf_tml_self[fp->uf_tml_idx], &fp->uf_tml_start, 26175 &fp->uf_tml_children); 26176 } 26177 fp->uf_tml_idx = -1; 26178 } 26179 } 26180 #endif 26181 26182 /* 26183 * Return TRUE if the currently active function should be ended, because a 26184 * return was encountered or an error occurred. Used inside a ":while". 26185 */ 26186 int 26187 func_has_ended(void *cookie) 26188 { 26189 funccall_T *fcp = (funccall_T *)cookie; 26190 26191 /* Ignore the "abort" flag if the abortion behavior has been changed due to 26192 * an error inside a try conditional. */ 26193 return (((fcp->func->uf_flags & FC_ABORT) && did_emsg && !aborted_in_try()) 26194 || fcp->returned); 26195 } 26196 26197 /* 26198 * return TRUE if cookie indicates a function which "abort"s on errors. 26199 */ 26200 int 26201 func_has_abort( 26202 void *cookie) 26203 { 26204 return ((funccall_T *)cookie)->func->uf_flags & FC_ABORT; 26205 } 26206 26207 #if defined(FEAT_VIMINFO) || defined(FEAT_SESSION) 26208 typedef enum 26209 { 26210 VAR_FLAVOUR_DEFAULT, /* doesn't start with uppercase */ 26211 VAR_FLAVOUR_SESSION, /* starts with uppercase, some lower */ 26212 VAR_FLAVOUR_VIMINFO /* all uppercase */ 26213 } var_flavour_T; 26214 26215 static var_flavour_T var_flavour(char_u *varname); 26216 26217 static var_flavour_T 26218 var_flavour(char_u *varname) 26219 { 26220 char_u *p = varname; 26221 26222 if (ASCII_ISUPPER(*p)) 26223 { 26224 while (*(++p)) 26225 if (ASCII_ISLOWER(*p)) 26226 return VAR_FLAVOUR_SESSION; 26227 return VAR_FLAVOUR_VIMINFO; 26228 } 26229 else 26230 return VAR_FLAVOUR_DEFAULT; 26231 } 26232 #endif 26233 26234 #if defined(FEAT_VIMINFO) || defined(PROTO) 26235 /* 26236 * Restore global vars that start with a capital from the viminfo file 26237 */ 26238 int 26239 read_viminfo_varlist(vir_T *virp, int writing) 26240 { 26241 char_u *tab; 26242 int type = VAR_NUMBER; 26243 typval_T tv; 26244 funccall_T *save_funccal; 26245 26246 if (!writing && (find_viminfo_parameter('!') != NULL)) 26247 { 26248 tab = vim_strchr(virp->vir_line + 1, '\t'); 26249 if (tab != NULL) 26250 { 26251 *tab++ = '\0'; /* isolate the variable name */ 26252 switch (*tab) 26253 { 26254 case 'S': type = VAR_STRING; break; 26255 #ifdef FEAT_FLOAT 26256 case 'F': type = VAR_FLOAT; break; 26257 #endif 26258 case 'D': type = VAR_DICT; break; 26259 case 'L': type = VAR_LIST; break; 26260 case 'X': type = VAR_SPECIAL; break; 26261 } 26262 26263 tab = vim_strchr(tab, '\t'); 26264 if (tab != NULL) 26265 { 26266 tv.v_type = type; 26267 if (type == VAR_STRING || type == VAR_DICT || type == VAR_LIST) 26268 tv.vval.v_string = viminfo_readstring(virp, 26269 (int)(tab - virp->vir_line + 1), TRUE); 26270 #ifdef FEAT_FLOAT 26271 else if (type == VAR_FLOAT) 26272 (void)string2float(tab + 1, &tv.vval.v_float); 26273 #endif 26274 else 26275 tv.vval.v_number = atol((char *)tab + 1); 26276 if (type == VAR_DICT || type == VAR_LIST) 26277 { 26278 typval_T *etv = eval_expr(tv.vval.v_string, NULL); 26279 26280 if (etv == NULL) 26281 /* Failed to parse back the dict or list, use it as a 26282 * string. */ 26283 tv.v_type = VAR_STRING; 26284 else 26285 { 26286 vim_free(tv.vval.v_string); 26287 tv = *etv; 26288 vim_free(etv); 26289 } 26290 } 26291 26292 /* when in a function use global variables */ 26293 save_funccal = current_funccal; 26294 current_funccal = NULL; 26295 set_var(virp->vir_line + 1, &tv, FALSE); 26296 current_funccal = save_funccal; 26297 26298 if (tv.v_type == VAR_STRING) 26299 vim_free(tv.vval.v_string); 26300 else if (tv.v_type == VAR_DICT || tv.v_type == VAR_LIST) 26301 clear_tv(&tv); 26302 } 26303 } 26304 } 26305 26306 return viminfo_readline(virp); 26307 } 26308 26309 /* 26310 * Write global vars that start with a capital to the viminfo file 26311 */ 26312 void 26313 write_viminfo_varlist(FILE *fp) 26314 { 26315 hashitem_T *hi; 26316 dictitem_T *this_var; 26317 int todo; 26318 char *s = ""; 26319 char_u *p; 26320 char_u *tofree; 26321 char_u numbuf[NUMBUFLEN]; 26322 26323 if (find_viminfo_parameter('!') == NULL) 26324 return; 26325 26326 fputs(_("\n# global variables:\n"), fp); 26327 26328 todo = (int)globvarht.ht_used; 26329 for (hi = globvarht.ht_array; todo > 0; ++hi) 26330 { 26331 if (!HASHITEM_EMPTY(hi)) 26332 { 26333 --todo; 26334 this_var = HI2DI(hi); 26335 if (var_flavour(this_var->di_key) == VAR_FLAVOUR_VIMINFO) 26336 { 26337 switch (this_var->di_tv.v_type) 26338 { 26339 case VAR_STRING: s = "STR"; break; 26340 case VAR_NUMBER: s = "NUM"; break; 26341 case VAR_FLOAT: s = "FLO"; break; 26342 case VAR_DICT: s = "DIC"; break; 26343 case VAR_LIST: s = "LIS"; break; 26344 case VAR_SPECIAL: s = "XPL"; break; 26345 26346 case VAR_UNKNOWN: 26347 case VAR_FUNC: 26348 case VAR_PARTIAL: 26349 case VAR_JOB: 26350 case VAR_CHANNEL: 26351 continue; 26352 } 26353 fprintf(fp, "!%s\t%s\t", this_var->di_key, s); 26354 p = echo_string(&this_var->di_tv, &tofree, numbuf, 0); 26355 if (p != NULL) 26356 viminfo_writestring(fp, p); 26357 vim_free(tofree); 26358 } 26359 } 26360 } 26361 } 26362 #endif 26363 26364 #if defined(FEAT_SESSION) || defined(PROTO) 26365 int 26366 store_session_globals(FILE *fd) 26367 { 26368 hashitem_T *hi; 26369 dictitem_T *this_var; 26370 int todo; 26371 char_u *p, *t; 26372 26373 todo = (int)globvarht.ht_used; 26374 for (hi = globvarht.ht_array; todo > 0; ++hi) 26375 { 26376 if (!HASHITEM_EMPTY(hi)) 26377 { 26378 --todo; 26379 this_var = HI2DI(hi); 26380 if ((this_var->di_tv.v_type == VAR_NUMBER 26381 || this_var->di_tv.v_type == VAR_STRING) 26382 && var_flavour(this_var->di_key) == VAR_FLAVOUR_SESSION) 26383 { 26384 /* Escape special characters with a backslash. Turn a LF and 26385 * CR into \n and \r. */ 26386 p = vim_strsave_escaped(get_tv_string(&this_var->di_tv), 26387 (char_u *)"\\\"\n\r"); 26388 if (p == NULL) /* out of memory */ 26389 break; 26390 for (t = p; *t != NUL; ++t) 26391 if (*t == '\n') 26392 *t = 'n'; 26393 else if (*t == '\r') 26394 *t = 'r'; 26395 if ((fprintf(fd, "let %s = %c%s%c", 26396 this_var->di_key, 26397 (this_var->di_tv.v_type == VAR_STRING) ? '"' 26398 : ' ', 26399 p, 26400 (this_var->di_tv.v_type == VAR_STRING) ? '"' 26401 : ' ') < 0) 26402 || put_eol(fd) == FAIL) 26403 { 26404 vim_free(p); 26405 return FAIL; 26406 } 26407 vim_free(p); 26408 } 26409 #ifdef FEAT_FLOAT 26410 else if (this_var->di_tv.v_type == VAR_FLOAT 26411 && var_flavour(this_var->di_key) == VAR_FLAVOUR_SESSION) 26412 { 26413 float_T f = this_var->di_tv.vval.v_float; 26414 int sign = ' '; 26415 26416 if (f < 0) 26417 { 26418 f = -f; 26419 sign = '-'; 26420 } 26421 if ((fprintf(fd, "let %s = %c%f", 26422 this_var->di_key, sign, f) < 0) 26423 || put_eol(fd) == FAIL) 26424 return FAIL; 26425 } 26426 #endif 26427 } 26428 } 26429 return OK; 26430 } 26431 #endif 26432 26433 /* 26434 * Display script name where an item was last set. 26435 * Should only be invoked when 'verbose' is non-zero. 26436 */ 26437 void 26438 last_set_msg(scid_T scriptID) 26439 { 26440 char_u *p; 26441 26442 if (scriptID != 0) 26443 { 26444 p = home_replace_save(NULL, get_scriptname(scriptID)); 26445 if (p != NULL) 26446 { 26447 verbose_enter(); 26448 MSG_PUTS(_("\n\tLast set from ")); 26449 MSG_PUTS(p); 26450 vim_free(p); 26451 verbose_leave(); 26452 } 26453 } 26454 } 26455 26456 /* 26457 * List v:oldfiles in a nice way. 26458 */ 26459 void 26460 ex_oldfiles(exarg_T *eap UNUSED) 26461 { 26462 list_T *l = vimvars[VV_OLDFILES].vv_list; 26463 listitem_T *li; 26464 int nr = 0; 26465 26466 if (l == NULL) 26467 msg((char_u *)_("No old files")); 26468 else 26469 { 26470 msg_start(); 26471 msg_scroll = TRUE; 26472 for (li = l->lv_first; li != NULL && !got_int; li = li->li_next) 26473 { 26474 msg_outnum((long)++nr); 26475 MSG_PUTS(": "); 26476 msg_outtrans(get_tv_string(&li->li_tv)); 26477 msg_putchar('\n'); 26478 out_flush(); /* output one line at a time */ 26479 ui_breakcheck(); 26480 } 26481 /* Assume "got_int" was set to truncate the listing. */ 26482 got_int = FALSE; 26483 26484 #ifdef FEAT_BROWSE_CMD 26485 if (cmdmod.browse) 26486 { 26487 quit_more = FALSE; 26488 nr = prompt_for_number(FALSE); 26489 msg_starthere(); 26490 if (nr > 0) 26491 { 26492 char_u *p = list_find_str(get_vim_var_list(VV_OLDFILES), 26493 (long)nr); 26494 26495 if (p != NULL) 26496 { 26497 p = expand_env_save(p); 26498 eap->arg = p; 26499 eap->cmdidx = CMD_edit; 26500 cmdmod.browse = FALSE; 26501 do_exedit(eap, NULL); 26502 vim_free(p); 26503 } 26504 } 26505 } 26506 #endif 26507 } 26508 } 26509 26510 /* reset v:option_new, v:option_old and v:option_type */ 26511 void 26512 reset_v_option_vars(void) 26513 { 26514 set_vim_var_string(VV_OPTION_NEW, NULL, -1); 26515 set_vim_var_string(VV_OPTION_OLD, NULL, -1); 26516 set_vim_var_string(VV_OPTION_TYPE, NULL, -1); 26517 } 26518 26519 26520 #endif /* FEAT_EVAL */ 26521 26522 26523 #if defined(FEAT_MODIFY_FNAME) || defined(FEAT_EVAL) || defined(PROTO) 26524 26525 #ifdef WIN3264 26526 /* 26527 * Functions for ":8" filename modifier: get 8.3 version of a filename. 26528 */ 26529 static int get_short_pathname(char_u **fnamep, char_u **bufp, int *fnamelen); 26530 static int shortpath_for_invalid_fname(char_u **fname, char_u **bufp, int *fnamelen); 26531 static int shortpath_for_partial(char_u **fnamep, char_u **bufp, int *fnamelen); 26532 26533 /* 26534 * Get the short path (8.3) for the filename in "fnamep". 26535 * Only works for a valid file name. 26536 * When the path gets longer "fnamep" is changed and the allocated buffer 26537 * is put in "bufp". 26538 * *fnamelen is the length of "fnamep" and set to 0 for a nonexistent path. 26539 * Returns OK on success, FAIL on failure. 26540 */ 26541 static int 26542 get_short_pathname(char_u **fnamep, char_u **bufp, int *fnamelen) 26543 { 26544 int l, len; 26545 char_u *newbuf; 26546 26547 len = *fnamelen; 26548 l = GetShortPathName((LPSTR)*fnamep, (LPSTR)*fnamep, len); 26549 if (l > len - 1) 26550 { 26551 /* If that doesn't work (not enough space), then save the string 26552 * and try again with a new buffer big enough. */ 26553 newbuf = vim_strnsave(*fnamep, l); 26554 if (newbuf == NULL) 26555 return FAIL; 26556 26557 vim_free(*bufp); 26558 *fnamep = *bufp = newbuf; 26559 26560 /* Really should always succeed, as the buffer is big enough. */ 26561 l = GetShortPathName((LPSTR)*fnamep, (LPSTR)*fnamep, l+1); 26562 } 26563 26564 *fnamelen = l; 26565 return OK; 26566 } 26567 26568 /* 26569 * Get the short path (8.3) for the filename in "fname". The converted 26570 * path is returned in "bufp". 26571 * 26572 * Some of the directories specified in "fname" may not exist. This function 26573 * will shorten the existing directories at the beginning of the path and then 26574 * append the remaining non-existing path. 26575 * 26576 * fname - Pointer to the filename to shorten. On return, contains the 26577 * pointer to the shortened pathname 26578 * bufp - Pointer to an allocated buffer for the filename. 26579 * fnamelen - Length of the filename pointed to by fname 26580 * 26581 * Returns OK on success (or nothing done) and FAIL on failure (out of memory). 26582 */ 26583 static int 26584 shortpath_for_invalid_fname( 26585 char_u **fname, 26586 char_u **bufp, 26587 int *fnamelen) 26588 { 26589 char_u *short_fname, *save_fname, *pbuf_unused; 26590 char_u *endp, *save_endp; 26591 char_u ch; 26592 int old_len, len; 26593 int new_len, sfx_len; 26594 int retval = OK; 26595 26596 /* Make a copy */ 26597 old_len = *fnamelen; 26598 save_fname = vim_strnsave(*fname, old_len); 26599 pbuf_unused = NULL; 26600 short_fname = NULL; 26601 26602 endp = save_fname + old_len - 1; /* Find the end of the copy */ 26603 save_endp = endp; 26604 26605 /* 26606 * Try shortening the supplied path till it succeeds by removing one 26607 * directory at a time from the tail of the path. 26608 */ 26609 len = 0; 26610 for (;;) 26611 { 26612 /* go back one path-separator */ 26613 while (endp > save_fname && !after_pathsep(save_fname, endp + 1)) 26614 --endp; 26615 if (endp <= save_fname) 26616 break; /* processed the complete path */ 26617 26618 /* 26619 * Replace the path separator with a NUL and try to shorten the 26620 * resulting path. 26621 */ 26622 ch = *endp; 26623 *endp = 0; 26624 short_fname = save_fname; 26625 len = (int)STRLEN(short_fname) + 1; 26626 if (get_short_pathname(&short_fname, &pbuf_unused, &len) == FAIL) 26627 { 26628 retval = FAIL; 26629 goto theend; 26630 } 26631 *endp = ch; /* preserve the string */ 26632 26633 if (len > 0) 26634 break; /* successfully shortened the path */ 26635 26636 /* failed to shorten the path. Skip the path separator */ 26637 --endp; 26638 } 26639 26640 if (len > 0) 26641 { 26642 /* 26643 * Succeeded in shortening the path. Now concatenate the shortened 26644 * path with the remaining path at the tail. 26645 */ 26646 26647 /* Compute the length of the new path. */ 26648 sfx_len = (int)(save_endp - endp) + 1; 26649 new_len = len + sfx_len; 26650 26651 *fnamelen = new_len; 26652 vim_free(*bufp); 26653 if (new_len > old_len) 26654 { 26655 /* There is not enough space in the currently allocated string, 26656 * copy it to a buffer big enough. */ 26657 *fname = *bufp = vim_strnsave(short_fname, new_len); 26658 if (*fname == NULL) 26659 { 26660 retval = FAIL; 26661 goto theend; 26662 } 26663 } 26664 else 26665 { 26666 /* Transfer short_fname to the main buffer (it's big enough), 26667 * unless get_short_pathname() did its work in-place. */ 26668 *fname = *bufp = save_fname; 26669 if (short_fname != save_fname) 26670 vim_strncpy(save_fname, short_fname, len); 26671 save_fname = NULL; 26672 } 26673 26674 /* concat the not-shortened part of the path */ 26675 vim_strncpy(*fname + len, endp, sfx_len); 26676 (*fname)[new_len] = NUL; 26677 } 26678 26679 theend: 26680 vim_free(pbuf_unused); 26681 vim_free(save_fname); 26682 26683 return retval; 26684 } 26685 26686 /* 26687 * Get a pathname for a partial path. 26688 * Returns OK for success, FAIL for failure. 26689 */ 26690 static int 26691 shortpath_for_partial( 26692 char_u **fnamep, 26693 char_u **bufp, 26694 int *fnamelen) 26695 { 26696 int sepcount, len, tflen; 26697 char_u *p; 26698 char_u *pbuf, *tfname; 26699 int hasTilde; 26700 26701 /* Count up the path separators from the RHS.. so we know which part 26702 * of the path to return. */ 26703 sepcount = 0; 26704 for (p = *fnamep; p < *fnamep + *fnamelen; mb_ptr_adv(p)) 26705 if (vim_ispathsep(*p)) 26706 ++sepcount; 26707 26708 /* Need full path first (use expand_env() to remove a "~/") */ 26709 hasTilde = (**fnamep == '~'); 26710 if (hasTilde) 26711 pbuf = tfname = expand_env_save(*fnamep); 26712 else 26713 pbuf = tfname = FullName_save(*fnamep, FALSE); 26714 26715 len = tflen = (int)STRLEN(tfname); 26716 26717 if (get_short_pathname(&tfname, &pbuf, &len) == FAIL) 26718 return FAIL; 26719 26720 if (len == 0) 26721 { 26722 /* Don't have a valid filename, so shorten the rest of the 26723 * path if we can. This CAN give us invalid 8.3 filenames, but 26724 * there's not a lot of point in guessing what it might be. 26725 */ 26726 len = tflen; 26727 if (shortpath_for_invalid_fname(&tfname, &pbuf, &len) == FAIL) 26728 return FAIL; 26729 } 26730 26731 /* Count the paths backward to find the beginning of the desired string. */ 26732 for (p = tfname + len - 1; p >= tfname; --p) 26733 { 26734 #ifdef FEAT_MBYTE 26735 if (has_mbyte) 26736 p -= mb_head_off(tfname, p); 26737 #endif 26738 if (vim_ispathsep(*p)) 26739 { 26740 if (sepcount == 0 || (hasTilde && sepcount == 1)) 26741 break; 26742 else 26743 sepcount --; 26744 } 26745 } 26746 if (hasTilde) 26747 { 26748 --p; 26749 if (p >= tfname) 26750 *p = '~'; 26751 else 26752 return FAIL; 26753 } 26754 else 26755 ++p; 26756 26757 /* Copy in the string - p indexes into tfname - allocated at pbuf */ 26758 vim_free(*bufp); 26759 *fnamelen = (int)STRLEN(p); 26760 *bufp = pbuf; 26761 *fnamep = p; 26762 26763 return OK; 26764 } 26765 #endif /* WIN3264 */ 26766 26767 /* 26768 * Adjust a filename, according to a string of modifiers. 26769 * *fnamep must be NUL terminated when called. When returning, the length is 26770 * determined by *fnamelen. 26771 * Returns VALID_ flags or -1 for failure. 26772 * When there is an error, *fnamep is set to NULL. 26773 */ 26774 int 26775 modify_fname( 26776 char_u *src, /* string with modifiers */ 26777 int *usedlen, /* characters after src that are used */ 26778 char_u **fnamep, /* file name so far */ 26779 char_u **bufp, /* buffer for allocated file name or NULL */ 26780 int *fnamelen) /* length of fnamep */ 26781 { 26782 int valid = 0; 26783 char_u *tail; 26784 char_u *s, *p, *pbuf; 26785 char_u dirname[MAXPATHL]; 26786 int c; 26787 int has_fullname = 0; 26788 #ifdef WIN3264 26789 char_u *fname_start = *fnamep; 26790 int has_shortname = 0; 26791 #endif 26792 26793 repeat: 26794 /* ":p" - full path/file_name */ 26795 if (src[*usedlen] == ':' && src[*usedlen + 1] == 'p') 26796 { 26797 has_fullname = 1; 26798 26799 valid |= VALID_PATH; 26800 *usedlen += 2; 26801 26802 /* Expand "~/path" for all systems and "~user/path" for Unix and VMS */ 26803 if ((*fnamep)[0] == '~' 26804 #if !defined(UNIX) && !(defined(VMS) && defined(USER_HOME)) 26805 && ((*fnamep)[1] == '/' 26806 # ifdef BACKSLASH_IN_FILENAME 26807 || (*fnamep)[1] == '\\' 26808 # endif 26809 || (*fnamep)[1] == NUL) 26810 26811 #endif 26812 ) 26813 { 26814 *fnamep = expand_env_save(*fnamep); 26815 vim_free(*bufp); /* free any allocated file name */ 26816 *bufp = *fnamep; 26817 if (*fnamep == NULL) 26818 return -1; 26819 } 26820 26821 /* When "/." or "/.." is used: force expansion to get rid of it. */ 26822 for (p = *fnamep; *p != NUL; mb_ptr_adv(p)) 26823 { 26824 if (vim_ispathsep(*p) 26825 && p[1] == '.' 26826 && (p[2] == NUL 26827 || vim_ispathsep(p[2]) 26828 || (p[2] == '.' 26829 && (p[3] == NUL || vim_ispathsep(p[3]))))) 26830 break; 26831 } 26832 26833 /* FullName_save() is slow, don't use it when not needed. */ 26834 if (*p != NUL || !vim_isAbsName(*fnamep)) 26835 { 26836 *fnamep = FullName_save(*fnamep, *p != NUL); 26837 vim_free(*bufp); /* free any allocated file name */ 26838 *bufp = *fnamep; 26839 if (*fnamep == NULL) 26840 return -1; 26841 } 26842 26843 #ifdef WIN3264 26844 # if _WIN32_WINNT >= 0x0500 26845 if (vim_strchr(*fnamep, '~') != NULL) 26846 { 26847 /* Expand 8.3 filename to full path. Needed to make sure the same 26848 * file does not have two different names. 26849 * Note: problem does not occur if _WIN32_WINNT < 0x0500. */ 26850 p = alloc(_MAX_PATH + 1); 26851 if (p != NULL) 26852 { 26853 if (GetLongPathName((LPSTR)*fnamep, (LPSTR)p, _MAX_PATH)) 26854 { 26855 vim_free(*bufp); 26856 *bufp = *fnamep = p; 26857 } 26858 else 26859 vim_free(p); 26860 } 26861 } 26862 # endif 26863 #endif 26864 /* Append a path separator to a directory. */ 26865 if (mch_isdir(*fnamep)) 26866 { 26867 /* Make room for one or two extra characters. */ 26868 *fnamep = vim_strnsave(*fnamep, (int)STRLEN(*fnamep) + 2); 26869 vim_free(*bufp); /* free any allocated file name */ 26870 *bufp = *fnamep; 26871 if (*fnamep == NULL) 26872 return -1; 26873 add_pathsep(*fnamep); 26874 } 26875 } 26876 26877 /* ":." - path relative to the current directory */ 26878 /* ":~" - path relative to the home directory */ 26879 /* ":8" - shortname path - postponed till after */ 26880 while (src[*usedlen] == ':' 26881 && ((c = src[*usedlen + 1]) == '.' || c == '~' || c == '8')) 26882 { 26883 *usedlen += 2; 26884 if (c == '8') 26885 { 26886 #ifdef WIN3264 26887 has_shortname = 1; /* Postpone this. */ 26888 #endif 26889 continue; 26890 } 26891 pbuf = NULL; 26892 /* Need full path first (use expand_env() to remove a "~/") */ 26893 if (!has_fullname) 26894 { 26895 if (c == '.' && **fnamep == '~') 26896 p = pbuf = expand_env_save(*fnamep); 26897 else 26898 p = pbuf = FullName_save(*fnamep, FALSE); 26899 } 26900 else 26901 p = *fnamep; 26902 26903 has_fullname = 0; 26904 26905 if (p != NULL) 26906 { 26907 if (c == '.') 26908 { 26909 mch_dirname(dirname, MAXPATHL); 26910 s = shorten_fname(p, dirname); 26911 if (s != NULL) 26912 { 26913 *fnamep = s; 26914 if (pbuf != NULL) 26915 { 26916 vim_free(*bufp); /* free any allocated file name */ 26917 *bufp = pbuf; 26918 pbuf = NULL; 26919 } 26920 } 26921 } 26922 else 26923 { 26924 home_replace(NULL, p, dirname, MAXPATHL, TRUE); 26925 /* Only replace it when it starts with '~' */ 26926 if (*dirname == '~') 26927 { 26928 s = vim_strsave(dirname); 26929 if (s != NULL) 26930 { 26931 *fnamep = s; 26932 vim_free(*bufp); 26933 *bufp = s; 26934 } 26935 } 26936 } 26937 vim_free(pbuf); 26938 } 26939 } 26940 26941 tail = gettail(*fnamep); 26942 *fnamelen = (int)STRLEN(*fnamep); 26943 26944 /* ":h" - head, remove "/file_name", can be repeated */ 26945 /* Don't remove the first "/" or "c:\" */ 26946 while (src[*usedlen] == ':' && src[*usedlen + 1] == 'h') 26947 { 26948 valid |= VALID_HEAD; 26949 *usedlen += 2; 26950 s = get_past_head(*fnamep); 26951 while (tail > s && after_pathsep(s, tail)) 26952 mb_ptr_back(*fnamep, tail); 26953 *fnamelen = (int)(tail - *fnamep); 26954 #ifdef VMS 26955 if (*fnamelen > 0) 26956 *fnamelen += 1; /* the path separator is part of the path */ 26957 #endif 26958 if (*fnamelen == 0) 26959 { 26960 /* Result is empty. Turn it into "." to make ":cd %:h" work. */ 26961 p = vim_strsave((char_u *)"."); 26962 if (p == NULL) 26963 return -1; 26964 vim_free(*bufp); 26965 *bufp = *fnamep = tail = p; 26966 *fnamelen = 1; 26967 } 26968 else 26969 { 26970 while (tail > s && !after_pathsep(s, tail)) 26971 mb_ptr_back(*fnamep, tail); 26972 } 26973 } 26974 26975 /* ":8" - shortname */ 26976 if (src[*usedlen] == ':' && src[*usedlen + 1] == '8') 26977 { 26978 *usedlen += 2; 26979 #ifdef WIN3264 26980 has_shortname = 1; 26981 #endif 26982 } 26983 26984 #ifdef WIN3264 26985 /* 26986 * Handle ":8" after we have done 'heads' and before we do 'tails'. 26987 */ 26988 if (has_shortname) 26989 { 26990 /* Copy the string if it is shortened by :h and when it wasn't copied 26991 * yet, because we are going to change it in place. Avoids changing 26992 * the buffer name for "%:8". */ 26993 if (*fnamelen < (int)STRLEN(*fnamep) || *fnamep == fname_start) 26994 { 26995 p = vim_strnsave(*fnamep, *fnamelen); 26996 if (p == NULL) 26997 return -1; 26998 vim_free(*bufp); 26999 *bufp = *fnamep = p; 27000 } 27001 27002 /* Split into two implementations - makes it easier. First is where 27003 * there isn't a full name already, second is where there is. */ 27004 if (!has_fullname && !vim_isAbsName(*fnamep)) 27005 { 27006 if (shortpath_for_partial(fnamep, bufp, fnamelen) == FAIL) 27007 return -1; 27008 } 27009 else 27010 { 27011 int l = *fnamelen; 27012 27013 /* Simple case, already have the full-name. 27014 * Nearly always shorter, so try first time. */ 27015 if (get_short_pathname(fnamep, bufp, &l) == FAIL) 27016 return -1; 27017 27018 if (l == 0) 27019 { 27020 /* Couldn't find the filename, search the paths. */ 27021 l = *fnamelen; 27022 if (shortpath_for_invalid_fname(fnamep, bufp, &l) == FAIL) 27023 return -1; 27024 } 27025 *fnamelen = l; 27026 } 27027 } 27028 #endif /* WIN3264 */ 27029 27030 /* ":t" - tail, just the basename */ 27031 if (src[*usedlen] == ':' && src[*usedlen + 1] == 't') 27032 { 27033 *usedlen += 2; 27034 *fnamelen -= (int)(tail - *fnamep); 27035 *fnamep = tail; 27036 } 27037 27038 /* ":e" - extension, can be repeated */ 27039 /* ":r" - root, without extension, can be repeated */ 27040 while (src[*usedlen] == ':' 27041 && (src[*usedlen + 1] == 'e' || src[*usedlen + 1] == 'r')) 27042 { 27043 /* find a '.' in the tail: 27044 * - for second :e: before the current fname 27045 * - otherwise: The last '.' 27046 */ 27047 if (src[*usedlen + 1] == 'e' && *fnamep > tail) 27048 s = *fnamep - 2; 27049 else 27050 s = *fnamep + *fnamelen - 1; 27051 for ( ; s > tail; --s) 27052 if (s[0] == '.') 27053 break; 27054 if (src[*usedlen + 1] == 'e') /* :e */ 27055 { 27056 if (s > tail) 27057 { 27058 *fnamelen += (int)(*fnamep - (s + 1)); 27059 *fnamep = s + 1; 27060 #ifdef VMS 27061 /* cut version from the extension */ 27062 s = *fnamep + *fnamelen - 1; 27063 for ( ; s > *fnamep; --s) 27064 if (s[0] == ';') 27065 break; 27066 if (s > *fnamep) 27067 *fnamelen = s - *fnamep; 27068 #endif 27069 } 27070 else if (*fnamep <= tail) 27071 *fnamelen = 0; 27072 } 27073 else /* :r */ 27074 { 27075 if (s > tail) /* remove one extension */ 27076 *fnamelen = (int)(s - *fnamep); 27077 } 27078 *usedlen += 2; 27079 } 27080 27081 /* ":s?pat?foo?" - substitute */ 27082 /* ":gs?pat?foo?" - global substitute */ 27083 if (src[*usedlen] == ':' 27084 && (src[*usedlen + 1] == 's' 27085 || (src[*usedlen + 1] == 'g' && src[*usedlen + 2] == 's'))) 27086 { 27087 char_u *str; 27088 char_u *pat; 27089 char_u *sub; 27090 int sep; 27091 char_u *flags; 27092 int didit = FALSE; 27093 27094 flags = (char_u *)""; 27095 s = src + *usedlen + 2; 27096 if (src[*usedlen + 1] == 'g') 27097 { 27098 flags = (char_u *)"g"; 27099 ++s; 27100 } 27101 27102 sep = *s++; 27103 if (sep) 27104 { 27105 /* find end of pattern */ 27106 p = vim_strchr(s, sep); 27107 if (p != NULL) 27108 { 27109 pat = vim_strnsave(s, (int)(p - s)); 27110 if (pat != NULL) 27111 { 27112 s = p + 1; 27113 /* find end of substitution */ 27114 p = vim_strchr(s, sep); 27115 if (p != NULL) 27116 { 27117 sub = vim_strnsave(s, (int)(p - s)); 27118 str = vim_strnsave(*fnamep, *fnamelen); 27119 if (sub != NULL && str != NULL) 27120 { 27121 *usedlen = (int)(p + 1 - src); 27122 s = do_string_sub(str, pat, sub, flags); 27123 if (s != NULL) 27124 { 27125 *fnamep = s; 27126 *fnamelen = (int)STRLEN(s); 27127 vim_free(*bufp); 27128 *bufp = s; 27129 didit = TRUE; 27130 } 27131 } 27132 vim_free(sub); 27133 vim_free(str); 27134 } 27135 vim_free(pat); 27136 } 27137 } 27138 /* after using ":s", repeat all the modifiers */ 27139 if (didit) 27140 goto repeat; 27141 } 27142 } 27143 27144 if (src[*usedlen] == ':' && src[*usedlen + 1] == 'S') 27145 { 27146 /* vim_strsave_shellescape() needs a NUL terminated string. */ 27147 c = (*fnamep)[*fnamelen]; 27148 if (c != NUL) 27149 (*fnamep)[*fnamelen] = NUL; 27150 p = vim_strsave_shellescape(*fnamep, FALSE, FALSE); 27151 if (c != NUL) 27152 (*fnamep)[*fnamelen] = c; 27153 if (p == NULL) 27154 return -1; 27155 vim_free(*bufp); 27156 *bufp = *fnamep = p; 27157 *fnamelen = (int)STRLEN(p); 27158 *usedlen += 2; 27159 } 27160 27161 return valid; 27162 } 27163 27164 /* 27165 * Perform a substitution on "str" with pattern "pat" and substitute "sub". 27166 * "flags" can be "g" to do a global substitute. 27167 * Returns an allocated string, NULL for error. 27168 */ 27169 char_u * 27170 do_string_sub( 27171 char_u *str, 27172 char_u *pat, 27173 char_u *sub, 27174 char_u *flags) 27175 { 27176 int sublen; 27177 regmatch_T regmatch; 27178 int i; 27179 int do_all; 27180 char_u *tail; 27181 char_u *end; 27182 garray_T ga; 27183 char_u *ret; 27184 char_u *save_cpo; 27185 char_u *zero_width = NULL; 27186 27187 /* Make 'cpoptions' empty, so that the 'l' flag doesn't work here */ 27188 save_cpo = p_cpo; 27189 p_cpo = empty_option; 27190 27191 ga_init2(&ga, 1, 200); 27192 27193 do_all = (flags[0] == 'g'); 27194 27195 regmatch.rm_ic = p_ic; 27196 regmatch.regprog = vim_regcomp(pat, RE_MAGIC + RE_STRING); 27197 if (regmatch.regprog != NULL) 27198 { 27199 tail = str; 27200 end = str + STRLEN(str); 27201 while (vim_regexec_nl(®match, str, (colnr_T)(tail - str))) 27202 { 27203 /* Skip empty match except for first match. */ 27204 if (regmatch.startp[0] == regmatch.endp[0]) 27205 { 27206 if (zero_width == regmatch.startp[0]) 27207 { 27208 /* avoid getting stuck on a match with an empty string */ 27209 i = MB_PTR2LEN(tail); 27210 mch_memmove((char_u *)ga.ga_data + ga.ga_len, tail, 27211 (size_t)i); 27212 ga.ga_len += i; 27213 tail += i; 27214 continue; 27215 } 27216 zero_width = regmatch.startp[0]; 27217 } 27218 27219 /* 27220 * Get some space for a temporary buffer to do the substitution 27221 * into. It will contain: 27222 * - The text up to where the match is. 27223 * - The substituted text. 27224 * - The text after the match. 27225 */ 27226 sublen = vim_regsub(®match, sub, tail, FALSE, TRUE, FALSE); 27227 if (ga_grow(&ga, (int)((end - tail) + sublen - 27228 (regmatch.endp[0] - regmatch.startp[0]))) == FAIL) 27229 { 27230 ga_clear(&ga); 27231 break; 27232 } 27233 27234 /* copy the text up to where the match is */ 27235 i = (int)(regmatch.startp[0] - tail); 27236 mch_memmove((char_u *)ga.ga_data + ga.ga_len, tail, (size_t)i); 27237 /* add the substituted text */ 27238 (void)vim_regsub(®match, sub, (char_u *)ga.ga_data 27239 + ga.ga_len + i, TRUE, TRUE, FALSE); 27240 ga.ga_len += i + sublen - 1; 27241 tail = regmatch.endp[0]; 27242 if (*tail == NUL) 27243 break; 27244 if (!do_all) 27245 break; 27246 } 27247 27248 if (ga.ga_data != NULL) 27249 STRCPY((char *)ga.ga_data + ga.ga_len, tail); 27250 27251 vim_regfree(regmatch.regprog); 27252 } 27253 27254 ret = vim_strsave(ga.ga_data == NULL ? str : (char_u *)ga.ga_data); 27255 ga_clear(&ga); 27256 if (p_cpo == empty_option) 27257 p_cpo = save_cpo; 27258 else 27259 /* Darn, evaluating {sub} expression changed the value. */ 27260 free_string_option(save_cpo); 27261 27262 return ret; 27263 } 27264 27265 #endif /* defined(FEAT_MODIFY_FNAME) || defined(FEAT_EVAL) */ 27266