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 #if defined(MSDOS) || defined(MSWIN) 14 # include <io.h> /* for mch_open(), must be before vim.h */ 15 #endif 16 17 #include "vim.h" 18 19 #ifdef AMIGA 20 # include <time.h> /* for strftime() */ 21 #endif 22 23 #ifdef MACOS 24 # include <time.h> /* for time_t */ 25 #endif 26 27 #ifdef HAVE_FCNTL_H 28 # include <fcntl.h> 29 #endif 30 31 #if defined(FEAT_EVAL) || defined(PROTO) 32 33 #if SIZEOF_INT <= 3 /* use long if int is smaller than 32 bits */ 34 typedef long varnumber_T; 35 #else 36 typedef int varnumber_T; 37 #endif 38 39 /* 40 * Structure to hold an internal variable. 41 */ 42 typedef struct 43 { 44 char_u *var_name; /* name of variable */ 45 char var_type; /* VAR_NUMBER or VAR_STRING */ 46 union 47 { 48 varnumber_T var_number; /* number value */ 49 char_u *var_string; /* string value (Careful: can be NULL!) */ 50 } var_val; 51 } var; 52 53 #define VAR_UNKNOWN 0 54 #define VAR_NUMBER 1 55 #define VAR_STRING 2 56 57 typedef var * VAR; 58 59 /* 60 * All user-defined global variables are stored in "variables". 61 */ 62 garray_T variables = {0, 0, sizeof(var), 4, NULL}; 63 64 /* 65 * Array to hold an array with variables local to each sourced script. 66 */ 67 static garray_T ga_scripts = {0, 0, sizeof(garray_T), 4, NULL}; 68 #define SCRIPT_VARS(id) (((garray_T *)ga_scripts.ga_data)[(id) - 1]) 69 70 71 #define VAR_ENTRY(idx) (((VAR)(variables.ga_data))[idx]) 72 #define VAR_GAP_ENTRY(idx, gap) (((VAR)(gap->ga_data))[idx]) 73 #define BVAR_ENTRY(idx) (((VAR)(curbuf->b_vars.ga_data))[idx]) 74 #define WVAR_ENTRY(idx) (((VAR)(curwin->w_vars.ga_data))[idx]) 75 76 static int echo_attr = 0; /* attributes used for ":echo" */ 77 78 /* 79 * Structure to hold info for a user function. 80 */ 81 typedef struct ufunc ufunc_T; 82 83 struct ufunc 84 { 85 ufunc_T *next; /* next function in list */ 86 char_u *name; /* name of function; can start with <SNR>123_ 87 (<SNR> is K_SPECIAL KS_EXTRA KE_SNR) */ 88 int varargs; /* variable nr of arguments */ 89 int flags; 90 int calls; /* nr of active calls */ 91 garray_T args; /* arguments */ 92 garray_T lines; /* function lines */ 93 scid_T script_ID; /* ID of script where function was defined, 94 used for s: variables */ 95 }; 96 97 /* function flags */ 98 #define FC_ABORT 1 /* abort function on error */ 99 #define FC_RANGE 2 /* function accepts range */ 100 101 /* 102 * All user-defined functions are found in the forward-linked function list. 103 * The first function is pointed at by firstfunc. 104 */ 105 ufunc_T *firstfunc = NULL; 106 107 #define FUNCARG(fp, j) ((char_u **)(fp->args.ga_data))[j] 108 #define FUNCLINE(fp, j) ((char_u **)(fp->lines.ga_data))[j] 109 110 /* structure to hold info for a function that is currently being executed. */ 111 struct funccall 112 { 113 ufunc_T *func; /* function being called */ 114 int linenr; /* next line to be executed */ 115 int returned; /* ":return" used */ 116 int argcount; /* nr of arguments */ 117 VAR argvars; /* arguments */ 118 var a0_var; /* "a:0" variable */ 119 var firstline; /* "a:firstline" variable */ 120 var lastline; /* "a:lastline" variable */ 121 garray_T l_vars; /* local function variables */ 122 VAR retvar; /* return value variable */ 123 linenr_T breakpoint; /* next line with breakpoint or zero */ 124 int dbg_tick; /* debug_tick when breakpoint was set */ 125 int level; /* top nesting level of executed function */ 126 }; 127 128 /* 129 * Return the name of the executed function. 130 */ 131 char_u * 132 func_name(cookie) 133 void *cookie; 134 { 135 return ((struct funccall *)cookie)->func->name; 136 } 137 138 /* 139 * Return the address holding the next breakpoint line for a funccall cookie. 140 */ 141 linenr_T * 142 func_breakpoint(cookie) 143 void *cookie; 144 { 145 return &((struct funccall *)cookie)->breakpoint; 146 } 147 148 /* 149 * Return the address holding the debug tick for a funccall cookie. 150 */ 151 int * 152 func_dbg_tick(cookie) 153 void *cookie; 154 { 155 return &((struct funccall *)cookie)->dbg_tick; 156 } 157 158 /* 159 * Return the nesting level for a funccall cookie. 160 */ 161 int 162 func_level(cookie) 163 void *cookie; 164 { 165 return ((struct funccall *)cookie)->level; 166 } 167 168 /* pointer to funccal for currently active function */ 169 struct funccall *current_funccal = NULL; 170 171 /* 172 * Return TRUE when a function was ended by a ":return" command. 173 */ 174 int 175 current_func_returned() 176 { 177 return current_funccal->returned; 178 } 179 180 181 /* 182 * Array to hold the value of v: variables. 183 */ 184 #include "version.h" 185 186 /* values for flags: */ 187 #define VV_COMPAT 1 /* compatible, also used without "v:" */ 188 #define VV_RO 2 /* read-only */ 189 #define VV_RO_SBX 4 /* read-only in the sandbox*/ 190 191 struct vimvar 192 { 193 char *name; /* name of variable, without v: */ 194 int len; /* length of name */ 195 char_u *val; /* current value (can also be a number!) */ 196 char type; /* VAR_NUMBER or VAR_STRING */ 197 char flags; /* VV_COMPAT, VV_RO, VV_RO_SBX */ 198 } vimvars[VV_LEN] = 199 { /* The order here must match the VV_ defines in vim.h! */ 200 {"count", sizeof("count") - 1, NULL, VAR_NUMBER, VV_COMPAT+VV_RO}, 201 {"count1", sizeof("count1") - 1, NULL, VAR_NUMBER, VV_RO}, 202 {"prevcount", sizeof("prevcount") - 1, NULL, VAR_NUMBER, VV_RO}, 203 {"errmsg", sizeof("errmsg") - 1, NULL, VAR_STRING, VV_COMPAT}, 204 {"warningmsg", sizeof("warningmsg") - 1, NULL, VAR_STRING, 0}, 205 {"statusmsg", sizeof("statusmsg") - 1, NULL, VAR_STRING, 0}, 206 {"shell_error", sizeof("shell_error") - 1, NULL, VAR_NUMBER, 207 VV_COMPAT+VV_RO}, 208 {"this_session", sizeof("this_session") - 1, NULL, VAR_STRING, VV_COMPAT}, 209 {"version", sizeof("version") - 1, (char_u *)VIM_VERSION_100, 210 VAR_NUMBER, VV_COMPAT+VV_RO}, 211 {"lnum", sizeof("lnum") - 1, NULL, VAR_NUMBER, VV_RO_SBX}, 212 {"termresponse", sizeof("termresponse") - 1, NULL, VAR_STRING, VV_RO}, 213 {"fname", sizeof("fname") - 1, NULL, VAR_STRING, VV_RO}, 214 {"lang", sizeof("lang") - 1, NULL, VAR_STRING, VV_RO}, 215 {"lc_time", sizeof("lc_time") - 1, NULL, VAR_STRING, VV_RO}, 216 {"ctype", sizeof("ctype") - 1, NULL, VAR_STRING, VV_RO}, 217 {"charconvert_from", sizeof("charconvert_from") - 1, NULL, VAR_STRING, VV_RO}, 218 {"charconvert_to", sizeof("charconvert_to") - 1, NULL, VAR_STRING, VV_RO}, 219 {"fname_in", sizeof("fname_in") - 1, NULL, VAR_STRING, VV_RO}, 220 {"fname_out", sizeof("fname_out") - 1, NULL, VAR_STRING, VV_RO}, 221 {"fname_new", sizeof("fname_new") - 1, NULL, VAR_STRING, VV_RO}, 222 {"fname_diff", sizeof("fname_diff") - 1, NULL, VAR_STRING, VV_RO}, 223 {"cmdarg", sizeof("cmdarg") - 1, NULL, VAR_STRING, VV_RO}, 224 {"foldstart", sizeof("foldstart") - 1, NULL, VAR_NUMBER, VV_RO_SBX}, 225 {"foldend", sizeof("foldend") - 1, NULL, VAR_NUMBER, VV_RO_SBX}, 226 {"folddashes", sizeof("folddashes") - 1, NULL, VAR_STRING, VV_RO_SBX}, 227 {"foldlevel", sizeof("foldlevel") - 1, NULL, VAR_NUMBER, VV_RO_SBX}, 228 {"progname", sizeof("progname") - 1, NULL, VAR_STRING, VV_RO}, 229 {"servername", sizeof("servername") - 1, NULL, VAR_STRING, VV_RO}, 230 {"dying", sizeof("dying") - 1, NULL, VAR_NUMBER, VV_RO}, 231 {"exception", sizeof("exception") - 1, NULL, VAR_STRING, VV_RO}, 232 {"throwpoint", sizeof("throwpoint") - 1, NULL, VAR_STRING, VV_RO}, 233 {"register", sizeof("register") - 1, NULL, VAR_STRING, VV_RO}, 234 {"cmdbang", sizeof("cmdbang") - 1, NULL, VAR_NUMBER, VV_RO}, 235 {"insertmode", sizeof("insertmode") - 1, NULL, VAR_STRING, VV_RO}, 236 }; 237 238 static int eval0 __ARGS((char_u *arg, VAR retvar, char_u **nextcmd, int evaluate)); 239 static int eval1 __ARGS((char_u **arg, VAR retvar, int evaluate)); 240 static int eval2 __ARGS((char_u **arg, VAR retvar, int evaluate)); 241 static int eval3 __ARGS((char_u **arg, VAR retvar, int evaluate)); 242 static int eval4 __ARGS((char_u **arg, VAR retvar, int evaluate)); 243 static int eval5 __ARGS((char_u **arg, VAR retvar, int evaluate)); 244 static int eval6 __ARGS((char_u **arg, VAR retvar, int evaluate)); 245 static int eval7 __ARGS((char_u **arg, VAR retvar, int evaluate)); 246 static int get_option_var __ARGS((char_u **arg, VAR retvar, int evaluate)); 247 static int get_string_var __ARGS((char_u **arg, VAR retvar, int evaluate)); 248 static int get_lit_string_var __ARGS((char_u **arg, VAR retvar, int evaluate)); 249 static int get_env_var __ARGS((char_u **arg, VAR retvar, int evaluate)); 250 static int find_internal_func __ARGS((char_u *name)); 251 static int get_func_var __ARGS((char_u *name, int len, VAR retvar, char_u **arg, linenr_T firstline, linenr_T lastline, int *doesrange, int evaluate)); 252 static int call_func __ARGS((char_u *name, int len, VAR retvar, int argcount, VAR argvars, linenr_T firstline, linenr_T lastline, int *doesrange, int evaluate)); 253 static void f_append __ARGS((VAR argvars, VAR retvar)); 254 static void f_argc __ARGS((VAR argvars, VAR retvar)); 255 static void f_argidx __ARGS((VAR argvars, VAR retvar)); 256 static void f_argv __ARGS((VAR argvars, VAR retvar)); 257 static void f_browse __ARGS((VAR argvars, VAR retvar)); 258 static void f_browsedir __ARGS((VAR argvars, VAR retvar)); 259 static buf_T *find_buffer __ARGS((VAR avar)); 260 static void f_bufexists __ARGS((VAR argvars, VAR retvar)); 261 static void f_buflisted __ARGS((VAR argvars, VAR retvar)); 262 static void f_bufloaded __ARGS((VAR argvars, VAR retvar)); 263 static buf_T *get_buf_var __ARGS((VAR avar)); 264 static void f_bufname __ARGS((VAR argvars, VAR retvar)); 265 static void f_bufnr __ARGS((VAR argvars, VAR retvar)); 266 static void f_bufwinnr __ARGS((VAR argvars, VAR retvar)); 267 static void f_byte2line __ARGS((VAR argvars, VAR retvar)); 268 static void f_byteidx __ARGS((VAR argvars, VAR retvar)); 269 static void f_char2nr __ARGS((VAR argvars, VAR retvar)); 270 static void f_cindent __ARGS((VAR argvars, VAR retvar)); 271 static void f_col __ARGS((VAR argvars, VAR retvar)); 272 static void f_confirm __ARGS((VAR argvars, VAR retvar)); 273 static void f_cscope_connection __ARGS((VAR argvars, VAR retvar)); 274 static void f_cursor __ARGS((VAR argsvars, VAR retvar)); 275 static void f_delete __ARGS((VAR argvars, VAR retvar)); 276 static void f_did_filetype __ARGS((VAR argvars, VAR retvar)); 277 static void f_escape __ARGS((VAR argvars, VAR retvar)); 278 static void f_eventhandler __ARGS((VAR argvars, VAR retvar)); 279 static void f_executable __ARGS((VAR argvars, VAR retvar)); 280 static void f_exists __ARGS((VAR argvars, VAR retvar)); 281 static void f_expand __ARGS((VAR argvars, VAR retvar)); 282 static void f_filereadable __ARGS((VAR argvars, VAR retvar)); 283 static void f_filewritable __ARGS((VAR argvars, VAR retvar)); 284 static void f_finddir __ARGS((VAR argvars, VAR retvar)); 285 static void f_findfile __ARGS((VAR argvars, VAR retvar)); 286 static void f_findfilendir __ARGS((VAR argvars, VAR retvar, int dir)); 287 static void f_fnamemodify __ARGS((VAR argvars, VAR retvar)); 288 static void f_foldclosed __ARGS((VAR argvars, VAR retvar)); 289 static void f_foldclosedend __ARGS((VAR argvars, VAR retvar)); 290 static void foldclosed_both __ARGS((VAR argvars, VAR retvar, int end)); 291 static void f_foldlevel __ARGS((VAR argvars, VAR retvar)); 292 static void f_foldtext __ARGS((VAR argvars, VAR retvar)); 293 static void f_foldtextresult __ARGS((VAR argvars, VAR retvar)); 294 static void f_foreground __ARGS((VAR argvars, VAR retvar)); 295 static void f_getbufvar __ARGS((VAR argvars, VAR retvar)); 296 static void f_getchar __ARGS((VAR argvars, VAR retvar)); 297 static void f_getcharmod __ARGS((VAR argvars, VAR retvar)); 298 static void f_getcmdline __ARGS((VAR argvars, VAR retvar)); 299 static void f_getcmdpos __ARGS((VAR argvars, VAR retvar)); 300 static void f_getcwd __ARGS((VAR argvars, VAR retvar)); 301 static void f_getfperm __ARGS((VAR argvars, VAR retvar)); 302 static void f_getfsize __ARGS((VAR argvars, VAR retvar)); 303 static void f_getftime __ARGS((VAR argvars, VAR retvar)); 304 static void f_getftype __ARGS((VAR argvars, VAR retvar)); 305 static void f_getline __ARGS((VAR argvars, VAR retvar)); 306 static void f_getreg __ARGS((VAR argvars, VAR retvar)); 307 static void f_getregtype __ARGS((VAR argvars, VAR retvar)); 308 static void f_getwinposx __ARGS((VAR argvars, VAR retvar)); 309 static void f_getwinposy __ARGS((VAR argvars, VAR retvar)); 310 static void f_getwinvar __ARGS((VAR argvars, VAR retvar)); 311 static void f_glob __ARGS((VAR argvars, VAR retvar)); 312 static void f_globpath __ARGS((VAR argvars, VAR retvar)); 313 static void f_has __ARGS((VAR argvars, VAR retvar)); 314 static void f_hasmapto __ARGS((VAR argvars, VAR retvar)); 315 static void f_histadd __ARGS((VAR argvars, VAR retvar)); 316 static void f_histdel __ARGS((VAR argvars, VAR retvar)); 317 static void f_histget __ARGS((VAR argvars, VAR retvar)); 318 static void f_histnr __ARGS((VAR argvars, VAR retvar)); 319 static void f_hlexists __ARGS((VAR argvars, VAR retvar)); 320 static void f_hlID __ARGS((VAR argvars, VAR retvar)); 321 static void f_hostname __ARGS((VAR argvars, VAR retvar)); 322 static void f_iconv __ARGS((VAR argvars, VAR retvar)); 323 static void f_indent __ARGS((VAR argvars, VAR retvar)); 324 static void f_isdirectory __ARGS((VAR argvars, VAR retvar)); 325 static void f_input __ARGS((VAR argvars, VAR retvar)); 326 static void f_inputdialog __ARGS((VAR argvars, VAR retvar)); 327 static void f_inputrestore __ARGS((VAR argvars, VAR retvar)); 328 static void f_inputsave __ARGS((VAR argvars, VAR retvar)); 329 static void f_inputsecret __ARGS((VAR argvars, VAR retvar)); 330 static void f_last_buffer_nr __ARGS((VAR argvars, VAR retvar)); 331 static void f_libcall __ARGS((VAR argvars, VAR retvar)); 332 static void f_libcallnr __ARGS((VAR argvars, VAR retvar)); 333 static void libcall_common __ARGS((VAR argvars, VAR retvar, int type)); 334 static void f_line __ARGS((VAR argvars, VAR retvar)); 335 static void f_line2byte __ARGS((VAR argvars, VAR retvar)); 336 static void f_lispindent __ARGS((VAR argvars, VAR retvar)); 337 static void f_localtime __ARGS((VAR argvars, VAR retvar)); 338 static void f_maparg __ARGS((VAR argvars, VAR retvar)); 339 static void f_mapcheck __ARGS((VAR argvars, VAR retvar)); 340 static void get_maparg __ARGS((VAR argvars, VAR retvar, int exact)); 341 static void f_match __ARGS((VAR argvars, VAR retvar)); 342 static void f_matchend __ARGS((VAR argvars, VAR retvar)); 343 static void f_matchstr __ARGS((VAR argvars, VAR retvar)); 344 static void f_mode __ARGS((VAR argvars, VAR retvar)); 345 static void f_nextnonblank __ARGS((VAR argvars, VAR retvar)); 346 static void f_nr2char __ARGS((VAR argvars, VAR retvar)); 347 static void f_prevnonblank __ARGS((VAR argvars, VAR retvar)); 348 static void f_setbufvar __ARGS((VAR argvars, VAR retvar)); 349 static void f_setcmdpos __ARGS((VAR argvars, VAR retvar)); 350 static void f_setwinvar __ARGS((VAR argvars, VAR retvar)); 351 static void f_rename __ARGS((VAR argvars, VAR retvar)); 352 static void f_resolve __ARGS((VAR argvars, VAR retvar)); 353 static void f_search __ARGS((VAR argvars, VAR retvar)); 354 static void f_searchpair __ARGS((VAR argvars, VAR retvar)); 355 static int get_search_arg __ARGS((VAR varp, int *flagsp)); 356 static void f_remote_expr __ARGS((VAR argvars, VAR retvar)); 357 static void f_remote_foreground __ARGS((VAR argvars, VAR retvar)); 358 static void f_remote_peek __ARGS((VAR argvars, VAR retvar)); 359 static void f_remote_read __ARGS((VAR argvars, VAR retvar)); 360 static void f_remote_send __ARGS((VAR argvars, VAR retvar)); 361 static void f_repeat __ARGS((VAR argvars, VAR retvar)); 362 static void f_server2client __ARGS((VAR argvars, VAR retvar)); 363 static void f_serverlist __ARGS((VAR argvars, VAR retvar)); 364 static void f_setline __ARGS((VAR argvars, VAR retvar)); 365 static void f_setreg __ARGS((VAR argvars, VAR retvar)); 366 static void f_simplify __ARGS((VAR argvars, VAR retvar)); 367 static void find_some_match __ARGS((VAR argvars, VAR retvar, int start)); 368 static void f_strftime __ARGS((VAR argvars, VAR retvar)); 369 static void f_stridx __ARGS((VAR argvars, VAR retvar)); 370 static void f_strlen __ARGS((VAR argvars, VAR retvar)); 371 static void f_strpart __ARGS((VAR argvars, VAR retvar)); 372 static void f_strridx __ARGS((VAR argvars, VAR retvar)); 373 static void f_strtrans __ARGS((VAR argvars, VAR retvar)); 374 static void f_synID __ARGS((VAR argvars, VAR retvar)); 375 static void f_synIDattr __ARGS((VAR argvars, VAR retvar)); 376 static void f_synIDtrans __ARGS((VAR argvars, VAR retvar)); 377 static void f_system __ARGS((VAR argvars, VAR retvar)); 378 static void f_submatch __ARGS((VAR argvars, VAR retvar)); 379 static void f_substitute __ARGS((VAR argvars, VAR retvar)); 380 static void f_tempname __ARGS((VAR argvars, VAR retvar)); 381 static void f_tolower __ARGS((VAR argvars, VAR retvar)); 382 static void f_toupper __ARGS((VAR argvars, VAR retvar)); 383 static void f_tr __ARGS((VAR argvars, VAR retvar)); 384 static void f_type __ARGS((VAR argvars, VAR retvar)); 385 static void f_virtcol __ARGS((VAR argvars, VAR retvar)); 386 static void f_visualmode __ARGS((VAR argvars, VAR retvar)); 387 static void f_winbufnr __ARGS((VAR argvars, VAR retvar)); 388 static void f_wincol __ARGS((VAR argvars, VAR retvar)); 389 static void f_winheight __ARGS((VAR argvars, VAR retvar)); 390 static void f_winline __ARGS((VAR argvars, VAR retvar)); 391 static void f_winnr __ARGS((VAR argvars, VAR retvar)); 392 static void f_winrestcmd __ARGS((VAR argvars, VAR retvar)); 393 static void f_winwidth __ARGS((VAR argvars, VAR retvar)); 394 static win_T *find_win_by_nr __ARGS((VAR vp)); 395 static pos_T *var2fpos __ARGS((VAR varp, int lnum)); 396 static int get_env_len __ARGS((char_u **arg)); 397 static int get_id_len __ARGS((char_u **arg)); 398 static int get_func_len __ARGS((char_u **arg, char_u **alias, int evaluate)); 399 static char_u *find_name_end __ARGS((char_u *arg, char_u **expr_start, char_u **expr_end)); 400 static int eval_isnamec __ARGS((int c)); 401 static int find_vim_var __ARGS((char_u *name, int len)); 402 static int get_var_var __ARGS((char_u *name, int len, VAR retvar)); 403 static VAR alloc_var __ARGS((void)); 404 static VAR alloc_string_var __ARGS((char_u *string)); 405 static void free_var __ARGS((VAR varp)); 406 static void clear_var __ARGS((VAR varp)); 407 static long get_var_number __ARGS((VAR varp)); 408 static linenr_T get_var_lnum __ARGS((VAR argvars)); 409 static char_u *get_var_string __ARGS((VAR varp)); 410 static char_u *get_var_string_buf __ARGS((VAR varp, char_u *buf)); 411 static VAR find_var __ARGS((char_u *name, int writing)); 412 static VAR find_var_in_ga __ARGS((garray_T *gap, char_u *varname)); 413 static garray_T *find_var_ga __ARGS((char_u *name, char_u **varname)); 414 static void var_free_one __ARGS((VAR v)); 415 static void list_one_var __ARGS((VAR v, char_u *prefix)); 416 static void list_vim_var __ARGS((int i)); 417 static void list_one_var_a __ARGS((char_u *prefix, char_u *name, int type, char_u *string)); 418 static void set_var __ARGS((char_u *name, VAR varp)); 419 static void copy_var __ARGS((VAR from, VAR to)); 420 static char_u *find_option_end __ARGS((char_u **arg, int *opt_flags)); 421 static char_u *trans_function_name __ARGS((char_u **pp, int skip, int internal)); 422 static int eval_fname_script __ARGS((char_u *p)); 423 static int eval_fname_sid __ARGS((char_u *p)); 424 static void list_func_head __ARGS((ufunc_T *fp, int indent)); 425 static void cat_func_name __ARGS((char_u *buf, ufunc_T *fp)); 426 static ufunc_T *find_func __ARGS((char_u *name)); 427 static void call_user_func __ARGS((ufunc_T *fp, int argcount, VAR argvars, VAR retvar, linenr_T firstline, linenr_T lastline)); 428 429 /* Magic braces are always enabled, otherwise Vim scripts would not be 430 * portable. */ 431 #define FEAT_MAGIC_BRACES 432 433 #ifdef FEAT_MAGIC_BRACES 434 static char_u * make_expanded_name __ARGS((char_u *in_start, char_u *expr_start, char_u *expr_end, char_u *in_end)); 435 #endif 436 437 /* 438 * Set an internal variable to a string value. Creates the variable if it does 439 * not already exist. 440 */ 441 void 442 set_internal_string_var(name, value) 443 char_u *name; 444 char_u *value; 445 { 446 char_u *val; 447 VAR varp; 448 449 val = vim_strsave(value); 450 if (val != NULL) 451 { 452 varp = alloc_string_var(val); 453 if (varp != NULL) 454 { 455 set_var(name, varp); 456 free_var(varp); 457 } 458 } 459 } 460 461 # if defined(FEAT_MBYTE) || defined(PROTO) 462 int 463 eval_charconvert(enc_from, enc_to, fname_from, fname_to) 464 char_u *enc_from; 465 char_u *enc_to; 466 char_u *fname_from; 467 char_u *fname_to; 468 { 469 int err = FALSE; 470 471 set_vim_var_string(VV_CC_FROM, enc_from, -1); 472 set_vim_var_string(VV_CC_TO, enc_to, -1); 473 set_vim_var_string(VV_FNAME_IN, fname_from, -1); 474 set_vim_var_string(VV_FNAME_OUT, fname_to, -1); 475 if (eval_to_bool(p_ccv, &err, NULL, FALSE)) 476 err = TRUE; 477 set_vim_var_string(VV_CC_FROM, NULL, -1); 478 set_vim_var_string(VV_CC_TO, NULL, -1); 479 set_vim_var_string(VV_FNAME_IN, NULL, -1); 480 set_vim_var_string(VV_FNAME_OUT, NULL, -1); 481 482 if (err) 483 return FAIL; 484 return OK; 485 } 486 # endif 487 488 # if defined(FEAT_POSTSCRIPT) || defined(PROTO) 489 int 490 eval_printexpr(fname, args) 491 char_u *fname; 492 char_u *args; 493 { 494 int err = FALSE; 495 496 set_vim_var_string(VV_FNAME_IN, fname, -1); 497 set_vim_var_string(VV_CMDARG, args, -1); 498 if (eval_to_bool(p_pexpr, &err, NULL, FALSE)) 499 err = TRUE; 500 set_vim_var_string(VV_FNAME_IN, NULL, -1); 501 set_vim_var_string(VV_CMDARG, NULL, -1); 502 503 if (err) 504 { 505 mch_remove(fname); 506 return FAIL; 507 } 508 return OK; 509 } 510 # endif 511 512 # if defined(FEAT_DIFF) || defined(PROTO) 513 void 514 eval_diff(origfile, newfile, outfile) 515 char_u *origfile; 516 char_u *newfile; 517 char_u *outfile; 518 { 519 int err = FALSE; 520 521 set_vim_var_string(VV_FNAME_IN, origfile, -1); 522 set_vim_var_string(VV_FNAME_NEW, newfile, -1); 523 set_vim_var_string(VV_FNAME_OUT, outfile, -1); 524 (void)eval_to_bool(p_dex, &err, NULL, FALSE); 525 set_vim_var_string(VV_FNAME_IN, NULL, -1); 526 set_vim_var_string(VV_FNAME_NEW, NULL, -1); 527 set_vim_var_string(VV_FNAME_OUT, NULL, -1); 528 } 529 530 void 531 eval_patch(origfile, difffile, outfile) 532 char_u *origfile; 533 char_u *difffile; 534 char_u *outfile; 535 { 536 int err; 537 538 set_vim_var_string(VV_FNAME_IN, origfile, -1); 539 set_vim_var_string(VV_FNAME_DIFF, difffile, -1); 540 set_vim_var_string(VV_FNAME_OUT, outfile, -1); 541 (void)eval_to_bool(p_pex, &err, NULL, FALSE); 542 set_vim_var_string(VV_FNAME_IN, NULL, -1); 543 set_vim_var_string(VV_FNAME_DIFF, NULL, -1); 544 set_vim_var_string(VV_FNAME_OUT, NULL, -1); 545 } 546 # endif 547 548 /* 549 * Top level evaluation function, returning a boolean. 550 * Sets "error" to TRUE if there was an error. 551 * Return TRUE or FALSE. 552 */ 553 int 554 eval_to_bool(arg, error, nextcmd, skip) 555 char_u *arg; 556 int *error; 557 char_u **nextcmd; 558 int skip; /* only parse, don't execute */ 559 { 560 var retvar; 561 int retval = FALSE; 562 563 if (skip) 564 ++emsg_skip; 565 if (eval0(arg, &retvar, nextcmd, !skip) == FAIL) 566 { 567 *error = TRUE; 568 } 569 else 570 { 571 *error = FALSE; 572 if (!skip) 573 { 574 retval = (get_var_number(&retvar) != 0); 575 clear_var(&retvar); 576 } 577 } 578 if (skip) 579 --emsg_skip; 580 581 return retval; 582 } 583 584 /* 585 * Top level evaluation function, returning a string. If "skip" is TRUE, 586 * only parsing to "nextcmd" is done, without reporting errors. Return 587 * pointer to allocated memory, or NULL for failure or when "skip" is TRUE. 588 */ 589 char_u * 590 eval_to_string_skip(arg, nextcmd, skip) 591 char_u *arg; 592 char_u **nextcmd; 593 int skip; /* only parse, don't execute */ 594 { 595 var retvar; 596 char_u *retval; 597 598 if (skip) 599 ++emsg_skip; 600 if (eval0(arg, &retvar, nextcmd, !skip) == FAIL || skip) 601 retval = NULL; 602 else 603 { 604 retval = vim_strsave(get_var_string(&retvar)); 605 clear_var(&retvar); 606 } 607 if (skip) 608 --emsg_skip; 609 610 return retval; 611 } 612 613 /* 614 * Skip over an expression at "*pp". 615 * Return FAIL for an error, OK otherwise. 616 */ 617 int 618 skip_expr(pp) 619 char_u **pp; 620 { 621 var retvar; 622 623 *pp = skipwhite(*pp); 624 return eval1(pp, &retvar, FALSE); 625 } 626 627 /* 628 * Top level evaluation function, returning a string. 629 * Return pointer to allocated memory, or NULL for failure. 630 */ 631 char_u * 632 eval_to_string(arg, nextcmd) 633 char_u *arg; 634 char_u **nextcmd; 635 { 636 var retvar; 637 char_u *retval; 638 639 if (eval0(arg, &retvar, nextcmd, TRUE) == FAIL) 640 retval = NULL; 641 else 642 { 643 retval = vim_strsave(get_var_string(&retvar)); 644 clear_var(&retvar); 645 } 646 647 return retval; 648 } 649 650 /* 651 * Call eval_to_string() with "sandbox" set and not using local variables. 652 */ 653 char_u * 654 eval_to_string_safe(arg, nextcmd) 655 char_u *arg; 656 char_u **nextcmd; 657 { 658 char_u *retval; 659 void *save_funccalp; 660 661 save_funccalp = save_funccal(); 662 ++sandbox; 663 retval = eval_to_string(arg, nextcmd); 664 --sandbox; 665 restore_funccal(save_funccalp); 666 return retval; 667 } 668 669 #if 0 /* not used */ 670 /* 671 * Top level evaluation function, returning a string. 672 * Advances "arg" to the first non-blank after the evaluated expression. 673 * Return pointer to allocated memory, or NULL for failure. 674 * Doesn't give error messages. 675 */ 676 char_u * 677 eval_arg_to_string(arg) 678 char_u **arg; 679 { 680 var retvar; 681 char_u *retval; 682 int ret; 683 684 ++emsg_off; 685 686 ret = eval1(arg, &retvar, TRUE); 687 if (ret == FAIL) 688 retval = NULL; 689 else 690 { 691 retval = vim_strsave(get_var_string(&retvar)); 692 clear_var(&retvar); 693 } 694 695 --emsg_off; 696 697 return retval; 698 } 699 #endif 700 701 /* 702 * Top level evaluation function, returning a number. 703 * Evaluates "expr" silently. 704 * Returns -1 for an error. 705 */ 706 int 707 eval_to_number(expr) 708 char_u *expr; 709 { 710 var retvar; 711 int retval; 712 char_u *p = expr; 713 714 ++emsg_off; 715 716 if (eval1(&p, &retvar, TRUE) == FAIL) 717 retval = -1; 718 else 719 { 720 retval = get_var_number(&retvar); 721 clear_var(&retvar); 722 } 723 --emsg_off; 724 725 return retval; 726 } 727 728 #if (defined(FEAT_USR_CMDS) && defined(FEAT_CMDL_COMPL)) || defined(PROTO) 729 /* 730 * Call some vimL function and return the result as a string 731 * Uses argv[argc] for the function arguments. 732 */ 733 char_u * 734 call_vim_function(func, argc, argv, safe) 735 char_u *func; 736 int argc; 737 char_u **argv; 738 int safe; /* use the sandbox */ 739 { 740 char_u *retval = NULL; 741 var retvar; 742 VAR argvars; 743 long n; 744 int len; 745 int i; 746 int doesrange; 747 void *save_funccalp = NULL; 748 749 argvars = (VAR)alloc((unsigned)(argc * sizeof(var))); 750 if (argvars == NULL) 751 return NULL; 752 753 for (i = 0; i < argc; i++) 754 { 755 /* Pass a NULL or empty argument as an empty string */ 756 if (argv[i] == NULL || *argv[i] == NUL) 757 { 758 argvars[i].var_type = VAR_STRING; 759 argvars[i].var_val.var_string = (char_u *)""; 760 continue; 761 } 762 763 /* Recognize a number argument, the others must be strings. */ 764 vim_str2nr(argv[i], NULL, &len, TRUE, TRUE, &n, NULL); 765 if (len != 0 && len == (int)STRLEN(argv[i])) 766 { 767 argvars[i].var_type = VAR_NUMBER; 768 argvars[i].var_val.var_number = n; 769 } 770 else 771 { 772 argvars[i].var_type = VAR_STRING; 773 argvars[i].var_val.var_string = argv[i]; 774 } 775 } 776 777 if (safe) 778 { 779 save_funccalp = save_funccal(); 780 ++sandbox; 781 } 782 783 retvar.var_type = VAR_UNKNOWN; /* clear_var() uses this */ 784 if (call_func(func, (int)STRLEN(func), &retvar, argc, argvars, 785 curwin->w_cursor.lnum, curwin->w_cursor.lnum, 786 &doesrange, TRUE) == OK) 787 retval = vim_strsave(get_var_string(&retvar)); 788 789 clear_var(&retvar); 790 vim_free(argvars); 791 792 if (safe) 793 { 794 --sandbox; 795 restore_funccal(save_funccalp); 796 } 797 return retval; 798 } 799 #endif 800 801 /* 802 * Save the current function call pointer, and set it to NULL. 803 * Used when executing autocommands and for ":source". 804 */ 805 void * 806 save_funccal() 807 { 808 struct funccall *fc; 809 810 fc = current_funccal; 811 current_funccal = NULL; 812 return (void *)fc; 813 } 814 815 void 816 restore_funccal(fc) 817 void *fc; 818 { 819 current_funccal = (struct funccall *)fc; 820 } 821 822 #ifdef FEAT_FOLDING 823 /* 824 * Evaluate 'foldexpr'. Returns the foldlevel, and any character preceding 825 * it in "*cp". Doesn't give error messages. 826 */ 827 int 828 eval_foldexpr(arg, cp) 829 char_u *arg; 830 int *cp; 831 { 832 var retvar; 833 int retval; 834 char_u *s; 835 836 ++emsg_off; 837 ++sandbox; 838 *cp = NUL; 839 if (eval0(arg, &retvar, NULL, TRUE) == FAIL) 840 retval = 0; 841 else 842 { 843 /* If the result is a number, just return the number. */ 844 if (retvar.var_type == VAR_NUMBER) 845 retval = retvar.var_val.var_number; 846 else if (retvar.var_type == VAR_UNKNOWN 847 || retvar.var_val.var_string == NULL) 848 retval = 0; 849 else 850 { 851 /* If the result is a string, check if there is a non-digit before 852 * the number. */ 853 s = retvar.var_val.var_string; 854 if (!VIM_ISDIGIT(*s) && *s != '-') 855 *cp = *s++; 856 retval = atol((char *)s); 857 } 858 clear_var(&retvar); 859 } 860 --emsg_off; 861 --sandbox; 862 863 return retval; 864 } 865 #endif 866 867 #ifdef FEAT_MAGIC_BRACES 868 /* 869 * Expands out the 'magic' {}'s in a variable/function name. 870 * Note that this can call itself recursively, to deal with 871 * constructs like foo{bar}{baz}{bam} 872 * The four pointer arguments point to "foo{expre}ss{ion}bar" 873 * "in_start" ^ 874 * "expr_start" ^ 875 * "expr_end" ^ 876 * "in_end" ^ 877 * 878 * Returns a new allocated string, which the caller must free. 879 * Returns NULL for failure. 880 */ 881 static char_u * 882 make_expanded_name(in_start, expr_start, expr_end, in_end) 883 char_u *in_start; 884 char_u *expr_start; 885 char_u *expr_end; 886 char_u *in_end; 887 { 888 char_u c1; 889 char_u *retval = NULL; 890 char_u *temp_result; 891 char_u *nextcmd = NULL; 892 893 if (expr_end == NULL || in_end == NULL) 894 return NULL; 895 *expr_start = NUL; 896 *expr_end = NUL; 897 c1 = *in_end; 898 *in_end = NUL; 899 900 temp_result = eval_to_string(expr_start + 1, &nextcmd); 901 if (temp_result != NULL && nextcmd == NULL) 902 { 903 retval = alloc((unsigned)(STRLEN(temp_result) + (expr_start - in_start) 904 + (in_end - expr_end) + 1)); 905 906 if (retval != NULL) 907 { 908 STRCPY(retval, in_start); 909 STRCAT(retval, temp_result); 910 STRCAT(retval, expr_end + 1); 911 } 912 } 913 vim_free(temp_result); 914 915 *in_end = c1; /* put char back for error messages */ 916 *expr_start = '{'; 917 *expr_end = '}'; 918 919 if (retval != NULL) 920 { 921 temp_result = find_name_end(retval, &expr_start, &expr_end); 922 if (expr_start != NULL) 923 { 924 /* Further expansion! */ 925 temp_result = make_expanded_name(retval, expr_start, 926 expr_end, temp_result); 927 vim_free(retval); 928 retval = temp_result; 929 } 930 } 931 932 return retval; 933 934 } 935 #endif /* FEAT_MAGIC_BRACES */ 936 937 /* 938 * ":let var = expr" assignment command. 939 * ":let var" list one variable value 940 * ":let" list all variable values 941 */ 942 void 943 ex_let(eap) 944 exarg_T *eap; 945 { 946 char_u *arg = eap->arg; 947 char_u *expr; 948 char_u *name; 949 VAR varp; 950 var retvar; 951 char_u *p; 952 int c1 = 0, c2; 953 int i; 954 char_u *expr_start; 955 char_u *expr_end; 956 char_u *name_end; 957 958 name_end = find_name_end(arg, &expr_start, &expr_end); 959 expr = vim_strchr(name_end, '='); 960 if (expr == NULL) 961 { 962 if (ends_excmd(*arg)) 963 { 964 if (!eap->skip) 965 { 966 /* 967 * List all variables. 968 */ 969 for (i = 0; i < variables.ga_len && !got_int; ++i) 970 if (VAR_ENTRY(i).var_name != NULL) 971 list_one_var(&VAR_ENTRY(i), (char_u *)""); 972 for (i = 0; i < curbuf->b_vars.ga_len && !got_int; ++i) 973 if (BVAR_ENTRY(i).var_name != NULL) 974 list_one_var(&BVAR_ENTRY(i), (char_u *)"b:"); 975 for (i = 0; i < curwin->w_vars.ga_len && !got_int; ++i) 976 if (WVAR_ENTRY(i).var_name != NULL) 977 list_one_var(&WVAR_ENTRY(i), (char_u *)"w:"); 978 for (i = 0; i < VV_LEN && !got_int; ++i) 979 if (vimvars[i].type == VAR_NUMBER || vimvars[i].val != NULL) 980 list_vim_var(i); 981 } 982 } 983 else 984 { 985 int error = FALSE; 986 987 /* 988 * List variables. 989 */ 990 while (!ends_excmd(*arg) && !got_int) 991 { 992 char_u *temp_string = NULL; 993 int arg_len; 994 995 /* Find the end of the name. */ 996 name_end = find_name_end(arg, &expr_start, &expr_end); 997 998 if (!vim_iswhite(*name_end) && !ends_excmd(*name_end)) 999 { 1000 emsg_severe = TRUE; 1001 EMSG(_(e_trailing)); 1002 break; 1003 } 1004 if (!error && !eap->skip) 1005 { 1006 #ifdef FEAT_MAGIC_BRACES 1007 if (expr_start != NULL) 1008 { 1009 temp_string = make_expanded_name(arg, expr_start, 1010 expr_end, name_end); 1011 if (temp_string == NULL) 1012 { 1013 /* 1014 * Report an invalid expression in braces, unless 1015 * the expression evaluation has been cancelled due 1016 * to an aborting error, an interrupt, or an 1017 * exception. 1018 */ 1019 if (!aborting()) 1020 { 1021 emsg_severe = TRUE; 1022 EMSG2(_(e_invarg2), arg); 1023 break; 1024 } 1025 error = TRUE; 1026 arg = skipwhite(name_end); 1027 continue; 1028 } 1029 arg = temp_string; 1030 arg_len = STRLEN(temp_string); 1031 } 1032 else 1033 #endif 1034 { 1035 c1 = *name_end; 1036 *name_end = NUL; 1037 arg_len = (int)(name_end - arg); 1038 } 1039 i = find_vim_var(arg, arg_len); 1040 if (i >= 0) 1041 list_vim_var(i); 1042 else if (STRCMP("b:changedtick", arg) == 0) 1043 { 1044 char_u numbuf[NUMBUFLEN]; 1045 1046 sprintf((char *)numbuf, "%ld", 1047 (long)curbuf->b_changedtick); 1048 list_one_var_a((char_u *)"b:", (char_u *)"changedtick", 1049 VAR_NUMBER, numbuf); 1050 } 1051 else 1052 { 1053 varp = find_var(arg, FALSE); 1054 if (varp == NULL) 1055 { 1056 /* Skip further arguments but do continue to 1057 * search for a trailing command. */ 1058 EMSG2(_("E106: Unknown variable: \"%s\""), arg); 1059 error = TRUE; 1060 } 1061 else 1062 { 1063 name = vim_strchr(arg, ':'); 1064 if (name != NULL) 1065 { 1066 /* "a:" vars have no name stored, use whole 1067 * arg */ 1068 if (arg[0] == 'a' && arg[1] == ':') 1069 c2 = NUL; 1070 else 1071 { 1072 c2 = *++name; 1073 *name = NUL; 1074 } 1075 list_one_var(varp, arg); 1076 if (c2 != NUL) 1077 *name = c2; 1078 } 1079 else 1080 list_one_var(varp, (char_u *)""); 1081 } 1082 } 1083 #ifdef FEAT_MAGIC_BRACES 1084 if (expr_start != NULL) 1085 vim_free(temp_string); 1086 else 1087 #endif 1088 *name_end = c1; 1089 } 1090 arg = skipwhite(name_end); 1091 } 1092 } 1093 eap->nextcmd = check_nextcmd(arg); 1094 } 1095 else 1096 { 1097 if (eap->skip) 1098 ++emsg_skip; 1099 i = eval0(expr + 1, &retvar, &eap->nextcmd, !eap->skip); 1100 if (eap->skip) 1101 { 1102 if (i != FAIL) 1103 clear_var(&retvar); 1104 --emsg_skip; 1105 } 1106 else if (i != FAIL) 1107 { 1108 /* 1109 * ":let $VAR = expr": Set environment variable. 1110 */ 1111 if (*arg == '$') 1112 { 1113 int len; 1114 int cc; 1115 1116 /* Find the end of the name. */ 1117 ++arg; 1118 name = arg; 1119 len = get_env_len(&arg); 1120 if (len == 0) 1121 EMSG2(_(e_invarg2), name - 1); 1122 else 1123 { 1124 if (*skipwhite(arg) != '=') 1125 EMSG(_(e_letunexp)); 1126 else 1127 { 1128 cc = name[len]; 1129 name[len] = NUL; 1130 p = get_var_string(&retvar); 1131 vim_setenv(name, p); 1132 if (STRICMP(name, "HOME") == 0) 1133 init_homedir(); 1134 else if (didset_vim && STRICMP(name, "VIM") == 0) 1135 didset_vim = FALSE; 1136 else if (didset_vimruntime 1137 && STRICMP(name, "VIMRUNTIME") == 0) 1138 didset_vimruntime = FALSE; 1139 name[len] = cc; 1140 } 1141 } 1142 } 1143 1144 /* 1145 * ":let &option = expr": Set option value. 1146 * ":let &l:option = expr": Set local option value. 1147 * ":let &g:option = expr": Set global option value. 1148 */ 1149 else if (*arg == '&') 1150 { 1151 int opt_flags; 1152 1153 /* 1154 * Find the end of the name; 1155 */ 1156 p = find_option_end(&arg, &opt_flags); 1157 if (p == NULL || *skipwhite(p) != '=') 1158 EMSG(_(e_letunexp)); 1159 else 1160 { 1161 c1 = *p; 1162 *p = NUL; 1163 set_option_value(arg, get_var_number(&retvar), 1164 get_var_string(&retvar), opt_flags); 1165 *p = c1; /* put back for error messages */ 1166 } 1167 } 1168 1169 /* 1170 * ":let @r = expr": Set register contents. 1171 */ 1172 else if (*arg == '@') 1173 { 1174 ++arg; 1175 if (*skipwhite(arg + 1) != '=') 1176 EMSG(_(e_letunexp)); 1177 else 1178 write_reg_contents(*arg == '@' ? '"' : *arg, 1179 get_var_string(&retvar), -1, FALSE); 1180 } 1181 1182 /* 1183 * ":let var = expr": Set internal variable. 1184 */ 1185 else if (eval_isnamec(*arg) && !VIM_ISDIGIT(*arg)) 1186 { 1187 /* Find the end of the name. */ 1188 p = find_name_end(arg, &expr_start, &expr_end); 1189 1190 if (*skipwhite(p) != '=') 1191 EMSG(_(e_letunexp)); 1192 else if (p - arg == 13 1193 && STRNCMP(arg, "b:changedtick", 13) == 0) 1194 EMSG2(_(e_readonlyvar), arg); 1195 #ifdef FEAT_MAGIC_BRACES 1196 else if (expr_start != NULL) 1197 { 1198 char_u *temp_string; 1199 1200 temp_string = make_expanded_name(arg, expr_start, 1201 expr_end, p); 1202 if (temp_string == NULL) 1203 { 1204 /* 1205 * Report an invalid expression in braces, unless the 1206 * expression evaluation has been cancelled due to an 1207 * aborting error, an interrupt, or an exception. 1208 */ 1209 if (!aborting()) 1210 EMSG2(_(e_invarg2), arg); 1211 } 1212 else 1213 { 1214 set_var(temp_string, &retvar); 1215 vim_free(temp_string); 1216 } 1217 } 1218 #endif 1219 else 1220 { 1221 c1 = *p; 1222 *p = NUL; 1223 set_var(arg, &retvar); 1224 *p = c1; /* put char back for error messages */ 1225 } 1226 } 1227 1228 else 1229 { 1230 EMSG2(_(e_invarg2), arg); 1231 } 1232 1233 clear_var(&retvar); 1234 } 1235 } 1236 } 1237 1238 #if defined(FEAT_CMDL_COMPL) || defined(PROTO) 1239 1240 void 1241 set_context_for_expression(xp, arg, cmdidx) 1242 expand_T *xp; 1243 char_u *arg; 1244 cmdidx_T cmdidx; 1245 { 1246 int got_eq = FALSE; 1247 int c; 1248 1249 xp->xp_context = cmdidx == CMD_let ? EXPAND_USER_VARS 1250 : cmdidx == CMD_call ? EXPAND_FUNCTIONS 1251 : EXPAND_EXPRESSION; 1252 while ((xp->xp_pattern = vim_strpbrk(arg, 1253 (char_u *)"\"'+-*/%.=!?~|&$([<>,#")) != NULL) 1254 { 1255 c = *xp->xp_pattern; 1256 if (c == '&') 1257 { 1258 c = xp->xp_pattern[1]; 1259 if (c == '&') 1260 { 1261 ++xp->xp_pattern; 1262 xp->xp_context = cmdidx != CMD_let || got_eq 1263 ? EXPAND_EXPRESSION : EXPAND_NOTHING; 1264 } 1265 else if (c != ' ') 1266 xp->xp_context = EXPAND_SETTINGS; 1267 } 1268 else if (c == '$') 1269 { 1270 /* environment variable */ 1271 xp->xp_context = EXPAND_ENV_VARS; 1272 } 1273 else if (c == '=') 1274 { 1275 got_eq = TRUE; 1276 xp->xp_context = EXPAND_EXPRESSION; 1277 } 1278 else if (c == '<' 1279 && xp->xp_context == EXPAND_FUNCTIONS 1280 && vim_strchr(xp->xp_pattern, '(') == NULL) 1281 { 1282 /* Function name can start with "<SNR>" */ 1283 break; 1284 } 1285 else if (cmdidx != CMD_let || got_eq) 1286 { 1287 if (c == '"') /* string */ 1288 { 1289 while ((c = *++xp->xp_pattern) != NUL && c != '"') 1290 if (c == '\\' && xp->xp_pattern[1] != NUL) 1291 ++xp->xp_pattern; 1292 xp->xp_context = EXPAND_NOTHING; 1293 } 1294 else if (c == '\'') /* literal string */ 1295 { 1296 while ((c = *++xp->xp_pattern) != NUL && c != '\'') 1297 /* skip */ ; 1298 xp->xp_context = EXPAND_NOTHING; 1299 } 1300 else if (c == '|') 1301 { 1302 if (xp->xp_pattern[1] == '|') 1303 { 1304 ++xp->xp_pattern; 1305 xp->xp_context = EXPAND_EXPRESSION; 1306 } 1307 else 1308 xp->xp_context = EXPAND_COMMANDS; 1309 } 1310 else 1311 xp->xp_context = EXPAND_EXPRESSION; 1312 } 1313 else 1314 xp->xp_context = EXPAND_NOTHING; 1315 arg = xp->xp_pattern; 1316 if (*arg != NUL) 1317 while ((c = *++arg) != NUL && (c == ' ' || c == '\t')) 1318 /* skip */ ; 1319 } 1320 xp->xp_pattern = arg; 1321 } 1322 1323 #endif /* FEAT_CMDL_COMPL */ 1324 1325 /* 1326 * ":1,25call func(arg1, arg2)" function call. 1327 */ 1328 void 1329 ex_call(eap) 1330 exarg_T *eap; 1331 { 1332 char_u *arg = eap->arg; 1333 char_u *startarg; 1334 char_u *alias; 1335 char_u *name; 1336 var retvar; 1337 int len; 1338 linenr_T lnum; 1339 int doesrange; 1340 int failed = FALSE; 1341 1342 name = arg; 1343 len = get_func_len(&arg, &alias, !eap->skip); 1344 if (len == 0) 1345 goto end; 1346 if (alias != NULL) 1347 name = alias; 1348 1349 startarg = arg; 1350 retvar.var_type = VAR_UNKNOWN; /* clear_var() uses this */ 1351 1352 if (*startarg != '(') 1353 { 1354 EMSG2(_("E107: Missing braces: %s"), name); 1355 goto end; 1356 } 1357 1358 /* 1359 * When skipping, evaluate the function once, to find the end of the 1360 * arguments. 1361 * When the function takes a range, this is discovered after the first 1362 * call, and the loop is broken. 1363 */ 1364 if (eap->skip) 1365 { 1366 ++emsg_skip; 1367 lnum = eap->line2; /* do it once, also with an invalid range */ 1368 } 1369 else 1370 lnum = eap->line1; 1371 for ( ; lnum <= eap->line2; ++lnum) 1372 { 1373 if (!eap->skip && eap->addr_count > 0) 1374 { 1375 curwin->w_cursor.lnum = lnum; 1376 curwin->w_cursor.col = 0; 1377 } 1378 arg = startarg; 1379 if (get_func_var(name, len, &retvar, &arg, 1380 eap->line1, eap->line2, &doesrange, !eap->skip) == FAIL) 1381 { 1382 failed = TRUE; 1383 break; 1384 } 1385 clear_var(&retvar); 1386 if (doesrange || eap->skip) 1387 break; 1388 /* Stop when immediately aborting on error, or when an interrupt 1389 * occurred or an exception was thrown but not caught. get_func_var() 1390 * returned OK, so that the check for trailing characters below is 1391 * executed. */ 1392 if (aborting()) 1393 break; 1394 } 1395 if (eap->skip) 1396 --emsg_skip; 1397 1398 if (!failed) 1399 { 1400 /* Check for trailing illegal characters and a following command. */ 1401 if (!ends_excmd(*arg)) 1402 { 1403 emsg_severe = TRUE; 1404 EMSG(_(e_trailing)); 1405 } 1406 else 1407 eap->nextcmd = check_nextcmd(arg); 1408 } 1409 1410 end: 1411 if (alias != NULL) 1412 vim_free(alias); 1413 } 1414 1415 /* 1416 * ":unlet[!] var1 ... " command. 1417 */ 1418 void 1419 ex_unlet(eap) 1420 exarg_T *eap; 1421 { 1422 char_u *arg = eap->arg; 1423 char_u *name_end; 1424 char_u cc; 1425 char_u *expr_start; 1426 char_u *expr_end; 1427 int error = FALSE; 1428 1429 do 1430 { 1431 /* Find the end of the name. */ 1432 name_end = find_name_end(arg, &expr_start, &expr_end); 1433 1434 if (!vim_iswhite(*name_end) && !ends_excmd(*name_end)) 1435 { 1436 emsg_severe = TRUE; 1437 EMSG(_(e_trailing)); 1438 break; 1439 } 1440 1441 if (!error && !eap->skip) 1442 { 1443 #ifdef FEAT_MAGIC_BRACES 1444 if (expr_start != NULL) 1445 { 1446 char_u *temp_string; 1447 1448 temp_string = make_expanded_name(arg, expr_start, 1449 expr_end, name_end); 1450 if (temp_string == NULL) 1451 { 1452 /* 1453 * Report an invalid expression in braces, unless the 1454 * expression evaluation has been cancelled due to an 1455 * aborting error, an interrupt, or an exception. 1456 */ 1457 if (!aborting()) 1458 { 1459 emsg_severe = TRUE; 1460 EMSG2(_(e_invarg2), arg); 1461 break; 1462 } 1463 error = TRUE; 1464 } 1465 else 1466 { 1467 if (do_unlet(temp_string) == FAIL && !eap->forceit) 1468 { 1469 EMSG2(_("E108: No such variable: \"%s\""), temp_string); 1470 error = TRUE; 1471 } 1472 vim_free(temp_string); 1473 } 1474 } 1475 else 1476 #endif 1477 { 1478 cc = *name_end; 1479 *name_end = NUL; 1480 1481 if (do_unlet(arg) == FAIL && !eap->forceit) 1482 { 1483 EMSG2(_("E108: No such variable: \"%s\""), arg); 1484 error = TRUE; 1485 } 1486 1487 *name_end = cc; 1488 } 1489 } 1490 arg = skipwhite(name_end); 1491 } while (!ends_excmd(*arg)); 1492 1493 eap->nextcmd = check_nextcmd(arg); 1494 } 1495 1496 /* 1497 * "unlet" a variable. Return OK if it existed, FAIL if not. 1498 */ 1499 int 1500 do_unlet(name) 1501 char_u *name; 1502 { 1503 VAR v; 1504 1505 v = find_var(name, TRUE); 1506 if (v != NULL) 1507 { 1508 var_free_one(v); 1509 return OK; 1510 } 1511 return FAIL; 1512 } 1513 1514 #if (defined(FEAT_MENU) && defined(FEAT_MULTI_LANG)) || defined(PROTO) 1515 /* 1516 * Delete all "menutrans_" variables. 1517 */ 1518 void 1519 del_menutrans_vars() 1520 { 1521 int i; 1522 1523 for (i = 0; i < variables.ga_len; ++i) 1524 if (VAR_ENTRY(i).var_name != NULL 1525 && STRNCMP(VAR_ENTRY(i).var_name, "menutrans_", 10) == 0) 1526 var_free_one(&VAR_ENTRY(i)); 1527 } 1528 #endif 1529 1530 #if defined(FEAT_CMDL_COMPL) || defined(PROTO) 1531 1532 /* 1533 * Local string buffer for the next two functions to store a variable name 1534 * with its prefix. Allocated in cat_prefix_varname(), freed later in 1535 * get_user_var_name(). 1536 */ 1537 1538 static char_u *cat_prefix_varname __ARGS((int prefix, char_u *name)); 1539 1540 static char_u *varnamebuf = NULL; 1541 static int varnamebuflen = 0; 1542 1543 /* 1544 * Function to concatenate a prefix and a variable name. 1545 */ 1546 static char_u * 1547 cat_prefix_varname(prefix, name) 1548 int prefix; 1549 char_u *name; 1550 { 1551 int len; 1552 1553 len = (int)STRLEN(name) + 3; 1554 if (len > varnamebuflen) 1555 { 1556 vim_free(varnamebuf); 1557 len += 10; /* some additional space */ 1558 varnamebuf = alloc(len); 1559 if (varnamebuf == NULL) 1560 { 1561 varnamebuflen = 0; 1562 return NULL; 1563 } 1564 varnamebuflen = len; 1565 } 1566 *varnamebuf = prefix; 1567 varnamebuf[1] = ':'; 1568 STRCPY(varnamebuf + 2, name); 1569 return varnamebuf; 1570 } 1571 1572 /* 1573 * Function given to ExpandGeneric() to obtain the list of user defined 1574 * (global/buffer/window/built-in) variable names. 1575 */ 1576 /*ARGSUSED*/ 1577 char_u * 1578 get_user_var_name(xp, idx) 1579 expand_T *xp; 1580 int idx; 1581 { 1582 static int gidx; 1583 static int bidx; 1584 static int widx; 1585 static int vidx; 1586 char_u *name; 1587 1588 if (idx == 0) 1589 gidx = bidx = widx = vidx = 0; 1590 if (gidx < variables.ga_len) /* Global variables */ 1591 { 1592 while ((name = VAR_ENTRY(gidx++).var_name) == NULL 1593 && gidx < variables.ga_len) 1594 /* skip */; 1595 if (name != NULL) 1596 { 1597 if (STRNCMP("g:", xp->xp_pattern, 2) == 0) 1598 return cat_prefix_varname('g', name); 1599 else 1600 return name; 1601 } 1602 } 1603 if (bidx < curbuf->b_vars.ga_len) /* Current buffer variables */ 1604 { 1605 while ((name = BVAR_ENTRY(bidx++).var_name) == NULL 1606 && bidx < curbuf->b_vars.ga_len) 1607 /* skip */; 1608 if (name != NULL) 1609 return cat_prefix_varname('b', name); 1610 } 1611 if (bidx == curbuf->b_vars.ga_len) 1612 { 1613 ++bidx; 1614 return (char_u *)"b:changedtick"; 1615 } 1616 if (widx < curwin->w_vars.ga_len) /* Current window variables */ 1617 { 1618 while ((name = WVAR_ENTRY(widx++).var_name) == NULL 1619 && widx < curwin->w_vars.ga_len) 1620 /* skip */; 1621 if (name != NULL) 1622 return cat_prefix_varname('w', name); 1623 } 1624 if (vidx < VV_LEN) /* Built-in variables */ 1625 return cat_prefix_varname('v', (char_u *)vimvars[vidx++].name); 1626 1627 vim_free(varnamebuf); 1628 varnamebuf = NULL; 1629 varnamebuflen = 0; 1630 return NULL; 1631 } 1632 1633 #endif /* FEAT_CMDL_COMPL */ 1634 1635 /* 1636 * types for expressions. 1637 */ 1638 typedef enum 1639 { 1640 TYPE_UNKNOWN = 0 1641 , TYPE_EQUAL /* == */ 1642 , TYPE_NEQUAL /* != */ 1643 , TYPE_GREATER /* > */ 1644 , TYPE_GEQUAL /* >= */ 1645 , TYPE_SMALLER /* < */ 1646 , TYPE_SEQUAL /* <= */ 1647 , TYPE_MATCH /* =~ */ 1648 , TYPE_NOMATCH /* !~ */ 1649 } exptype_T; 1650 1651 /* 1652 * The "evaluate" argument: When FALSE, the argument is only parsed but not 1653 * executed. The function may return OK, but the retvar will be of type 1654 * VAR_UNKNOWN. The function still returns FAIL for a syntax error. 1655 */ 1656 1657 /* 1658 * Handle zero level expression. 1659 * This calls eval1() and handles error message and nextcmd. 1660 * Return OK or FAIL. 1661 */ 1662 static int 1663 eval0(arg, retvar, nextcmd, evaluate) 1664 char_u *arg; 1665 VAR retvar; 1666 char_u **nextcmd; 1667 int evaluate; 1668 { 1669 int ret; 1670 char_u *p; 1671 1672 p = skipwhite(arg); 1673 ret = eval1(&p, retvar, evaluate); 1674 if (ret == FAIL || !ends_excmd(*p)) 1675 { 1676 if (ret != FAIL) 1677 clear_var(retvar); 1678 /* 1679 * Report the invalid expression unless the expression evaluation has 1680 * been cancelled due to an aborting error, an interrupt, or an 1681 * exception. 1682 */ 1683 if (!aborting()) 1684 EMSG2(_(e_invexpr2), arg); 1685 ret = FAIL; 1686 } 1687 if (nextcmd != NULL) 1688 *nextcmd = check_nextcmd(p); 1689 1690 return ret; 1691 } 1692 1693 /* 1694 * Handle top level expression: 1695 * expr1 ? expr0 : expr0 1696 * 1697 * "arg" must point to the first non-white of the expression. 1698 * "arg" is advanced to the next non-white after the recognized expression. 1699 * 1700 * Return OK or FAIL. 1701 */ 1702 static int 1703 eval1(arg, retvar, evaluate) 1704 char_u **arg; 1705 VAR retvar; 1706 int evaluate; 1707 { 1708 int result; 1709 var var2; 1710 1711 /* 1712 * Get the first variable. 1713 */ 1714 if (eval2(arg, retvar, evaluate) == FAIL) 1715 return FAIL; 1716 1717 if ((*arg)[0] == '?') 1718 { 1719 result = FALSE; 1720 if (evaluate) 1721 { 1722 if (get_var_number(retvar) != 0) 1723 result = TRUE; 1724 clear_var(retvar); 1725 } 1726 1727 /* 1728 * Get the second variable. 1729 */ 1730 *arg = skipwhite(*arg + 1); 1731 if (eval1(arg, retvar, evaluate && result) == FAIL) /* recursive! */ 1732 return FAIL; 1733 1734 /* 1735 * Check for the ":". 1736 */ 1737 if ((*arg)[0] != ':') 1738 { 1739 EMSG(_("E109: Missing ':' after '?'")); 1740 if (evaluate && result) 1741 clear_var(retvar); 1742 return FAIL; 1743 } 1744 1745 /* 1746 * Get the third variable. 1747 */ 1748 *arg = skipwhite(*arg + 1); 1749 if (eval1(arg, &var2, evaluate && !result) == FAIL) /* recursive! */ 1750 { 1751 if (evaluate && result) 1752 clear_var(retvar); 1753 return FAIL; 1754 } 1755 if (evaluate && !result) 1756 *retvar = var2; 1757 } 1758 1759 return OK; 1760 } 1761 1762 /* 1763 * Handle first level expression: 1764 * expr2 || expr2 || expr2 logical OR 1765 * 1766 * "arg" must point to the first non-white of the expression. 1767 * "arg" is advanced to the next non-white after the recognized expression. 1768 * 1769 * Return OK or FAIL. 1770 */ 1771 static int 1772 eval2(arg, retvar, evaluate) 1773 char_u **arg; 1774 VAR retvar; 1775 int evaluate; 1776 { 1777 var var2; 1778 long result; 1779 int first; 1780 1781 /* 1782 * Get the first variable. 1783 */ 1784 if (eval3(arg, retvar, evaluate) == FAIL) 1785 return FAIL; 1786 1787 /* 1788 * Repeat until there is no following "||". 1789 */ 1790 first = TRUE; 1791 result = FALSE; 1792 while ((*arg)[0] == '|' && (*arg)[1] == '|') 1793 { 1794 if (evaluate && first) 1795 { 1796 if (get_var_number(retvar) != 0) 1797 result = TRUE; 1798 clear_var(retvar); 1799 first = FALSE; 1800 } 1801 1802 /* 1803 * Get the second variable. 1804 */ 1805 *arg = skipwhite(*arg + 2); 1806 if (eval3(arg, &var2, evaluate && !result) == FAIL) 1807 return FAIL; 1808 1809 /* 1810 * Compute the result. 1811 */ 1812 if (evaluate && !result) 1813 { 1814 if (get_var_number(&var2) != 0) 1815 result = TRUE; 1816 clear_var(&var2); 1817 } 1818 if (evaluate) 1819 { 1820 retvar->var_type = VAR_NUMBER; 1821 retvar->var_val.var_number = result; 1822 } 1823 } 1824 1825 return OK; 1826 } 1827 1828 /* 1829 * Handle second level expression: 1830 * expr3 && expr3 && expr3 logical AND 1831 * 1832 * "arg" must point to the first non-white of the expression. 1833 * "arg" is advanced to the next non-white after the recognized expression. 1834 * 1835 * Return OK or FAIL. 1836 */ 1837 static int 1838 eval3(arg, retvar, evaluate) 1839 char_u **arg; 1840 VAR retvar; 1841 int evaluate; 1842 { 1843 var var2; 1844 long result; 1845 int first; 1846 1847 /* 1848 * Get the first variable. 1849 */ 1850 if (eval4(arg, retvar, evaluate) == FAIL) 1851 return FAIL; 1852 1853 /* 1854 * Repeat until there is no following "&&". 1855 */ 1856 first = TRUE; 1857 result = TRUE; 1858 while ((*arg)[0] == '&' && (*arg)[1] == '&') 1859 { 1860 if (evaluate && first) 1861 { 1862 if (get_var_number(retvar) == 0) 1863 result = FALSE; 1864 clear_var(retvar); 1865 first = FALSE; 1866 } 1867 1868 /* 1869 * Get the second variable. 1870 */ 1871 *arg = skipwhite(*arg + 2); 1872 if (eval4(arg, &var2, evaluate && result) == FAIL) 1873 return FAIL; 1874 1875 /* 1876 * Compute the result. 1877 */ 1878 if (evaluate && result) 1879 { 1880 if (get_var_number(&var2) == 0) 1881 result = FALSE; 1882 clear_var(&var2); 1883 } 1884 if (evaluate) 1885 { 1886 retvar->var_type = VAR_NUMBER; 1887 retvar->var_val.var_number = result; 1888 } 1889 } 1890 1891 return OK; 1892 } 1893 1894 /* 1895 * Handle third level expression: 1896 * var1 == var2 1897 * var1 =~ var2 1898 * var1 != var2 1899 * var1 !~ var2 1900 * var1 > var2 1901 * var1 >= var2 1902 * var1 < var2 1903 * var1 <= var2 1904 * 1905 * "arg" must point to the first non-white of the expression. 1906 * "arg" is advanced to the next non-white after the recognized expression. 1907 * 1908 * Return OK or FAIL. 1909 */ 1910 static int 1911 eval4(arg, retvar, evaluate) 1912 char_u **arg; 1913 VAR retvar; 1914 int evaluate; 1915 { 1916 var var2; 1917 char_u *p; 1918 int i; 1919 exptype_T type = TYPE_UNKNOWN; 1920 int len = 2; 1921 long n1, n2; 1922 char_u *s1, *s2; 1923 char_u buf1[NUMBUFLEN], buf2[NUMBUFLEN]; 1924 regmatch_T regmatch; 1925 int ic; 1926 char_u *save_cpo; 1927 1928 /* 1929 * Get the first variable. 1930 */ 1931 if (eval5(arg, retvar, evaluate) == FAIL) 1932 return FAIL; 1933 1934 p = *arg; 1935 switch (p[0]) 1936 { 1937 case '=': if (p[1] == '=') 1938 type = TYPE_EQUAL; 1939 else if (p[1] == '~') 1940 type = TYPE_MATCH; 1941 break; 1942 case '!': if (p[1] == '=') 1943 type = TYPE_NEQUAL; 1944 else if (p[1] == '~') 1945 type = TYPE_NOMATCH; 1946 break; 1947 case '>': if (p[1] != '=') 1948 { 1949 type = TYPE_GREATER; 1950 len = 1; 1951 } 1952 else 1953 type = TYPE_GEQUAL; 1954 break; 1955 case '<': if (p[1] != '=') 1956 { 1957 type = TYPE_SMALLER; 1958 len = 1; 1959 } 1960 else 1961 type = TYPE_SEQUAL; 1962 break; 1963 } 1964 1965 /* 1966 * If there is a comparitive operator, use it. 1967 */ 1968 if (type != TYPE_UNKNOWN) 1969 { 1970 /* extra question mark appended: ignore case */ 1971 if (p[len] == '?') 1972 { 1973 ic = TRUE; 1974 ++len; 1975 } 1976 /* extra '#' appended: match case */ 1977 else if (p[len] == '#') 1978 { 1979 ic = FALSE; 1980 ++len; 1981 } 1982 /* nothing appened: use 'ignorecase' */ 1983 else 1984 ic = p_ic; 1985 1986 /* 1987 * Get the second variable. 1988 */ 1989 *arg = skipwhite(p + len); 1990 if (eval5(arg, &var2, evaluate) == FAIL) 1991 { 1992 clear_var(retvar); 1993 return FAIL; 1994 } 1995 1996 if (evaluate) 1997 { 1998 /* 1999 * If one of the two variables is a number, compare as a number. 2000 * When using "=~" or "!~", always compare as string. 2001 */ 2002 if ((retvar->var_type == VAR_NUMBER || var2.var_type == VAR_NUMBER) 2003 && type != TYPE_MATCH && type != TYPE_NOMATCH) 2004 { 2005 n1 = get_var_number(retvar); 2006 n2 = get_var_number(&var2); 2007 switch (type) 2008 { 2009 case TYPE_EQUAL: n1 = (n1 == n2); break; 2010 case TYPE_NEQUAL: n1 = (n1 != n2); break; 2011 case TYPE_GREATER: n1 = (n1 > n2); break; 2012 case TYPE_GEQUAL: n1 = (n1 >= n2); break; 2013 case TYPE_SMALLER: n1 = (n1 < n2); break; 2014 case TYPE_SEQUAL: n1 = (n1 <= n2); break; 2015 case TYPE_UNKNOWN: 2016 case TYPE_MATCH: 2017 case TYPE_NOMATCH: break; /* avoid gcc warning */ 2018 } 2019 } 2020 else 2021 { 2022 s1 = get_var_string_buf(retvar, buf1); 2023 s2 = get_var_string_buf(&var2, buf2); 2024 if (type != TYPE_MATCH && type != TYPE_NOMATCH) 2025 i = ic ? MB_STRICMP(s1, s2) : STRCMP(s1, s2); 2026 else 2027 i = 0; 2028 n1 = FALSE; 2029 switch (type) 2030 { 2031 case TYPE_EQUAL: n1 = (i == 0); break; 2032 case TYPE_NEQUAL: n1 = (i != 0); break; 2033 case TYPE_GREATER: n1 = (i > 0); break; 2034 case TYPE_GEQUAL: n1 = (i >= 0); break; 2035 case TYPE_SMALLER: n1 = (i < 0); break; 2036 case TYPE_SEQUAL: n1 = (i <= 0); break; 2037 2038 case TYPE_MATCH: 2039 case TYPE_NOMATCH: 2040 /* avoid 'l' flag in 'cpoptions' */ 2041 save_cpo = p_cpo; 2042 p_cpo = (char_u *)""; 2043 regmatch.regprog = vim_regcomp(s2, 2044 RE_MAGIC + RE_STRING); 2045 regmatch.rm_ic = ic; 2046 if (regmatch.regprog != NULL) 2047 { 2048 n1 = vim_regexec_nl(®match, s1, (colnr_T)0); 2049 vim_free(regmatch.regprog); 2050 if (type == TYPE_NOMATCH) 2051 n1 = !n1; 2052 } 2053 p_cpo = save_cpo; 2054 break; 2055 2056 case TYPE_UNKNOWN: break; /* avoid gcc warning */ 2057 } 2058 } 2059 clear_var(retvar); 2060 clear_var(&var2); 2061 retvar->var_type = VAR_NUMBER; 2062 retvar->var_val.var_number = n1; 2063 } 2064 } 2065 2066 return OK; 2067 } 2068 2069 /* 2070 * Handle fourth level expression: 2071 * + number addition 2072 * - number subtraction 2073 * . string concatenation 2074 * 2075 * "arg" must point to the first non-white of the expression. 2076 * "arg" is advanced to the next non-white after the recognized expression. 2077 * 2078 * Return OK or FAIL. 2079 */ 2080 static int 2081 eval5(arg, retvar, evaluate) 2082 char_u **arg; 2083 VAR retvar; 2084 int evaluate; 2085 { 2086 var var2; 2087 int op; 2088 long n1, n2; 2089 char_u *s1, *s2; 2090 char_u buf1[NUMBUFLEN], buf2[NUMBUFLEN]; 2091 char_u *p; 2092 2093 /* 2094 * Get the first variable. 2095 */ 2096 if (eval6(arg, retvar, evaluate) == FAIL) 2097 return FAIL; 2098 2099 /* 2100 * Repeat computing, until no '+', '-' or '.' is following. 2101 */ 2102 for (;;) 2103 { 2104 op = **arg; 2105 if (op != '+' && op != '-' && op != '.') 2106 break; 2107 2108 /* 2109 * Get the second variable. 2110 */ 2111 *arg = skipwhite(*arg + 1); 2112 if (eval6(arg, &var2, evaluate) == FAIL) 2113 { 2114 clear_var(retvar); 2115 return FAIL; 2116 } 2117 2118 if (evaluate) 2119 { 2120 /* 2121 * Compute the result. 2122 */ 2123 if (op == '.') 2124 { 2125 s1 = get_var_string_buf(retvar, buf1); 2126 s2 = get_var_string_buf(&var2, buf2); 2127 op = (int)STRLEN(s1); 2128 p = alloc((unsigned)(op + STRLEN(s2) + 1)); 2129 if (p != NULL) 2130 { 2131 STRCPY(p, s1); 2132 STRCPY(p + op, s2); 2133 } 2134 clear_var(retvar); 2135 retvar->var_type = VAR_STRING; 2136 retvar->var_val.var_string = p; 2137 } 2138 else 2139 { 2140 n1 = get_var_number(retvar); 2141 n2 = get_var_number(&var2); 2142 clear_var(retvar); 2143 if (op == '+') 2144 n1 = n1 + n2; 2145 else 2146 n1 = n1 - n2; 2147 retvar->var_type = VAR_NUMBER; 2148 retvar->var_val.var_number = n1; 2149 } 2150 clear_var(&var2); 2151 } 2152 } 2153 return OK; 2154 } 2155 2156 /* 2157 * Handle fifth level expression: 2158 * * number multiplication 2159 * / number division 2160 * % number modulo 2161 * 2162 * "arg" must point to the first non-white of the expression. 2163 * "arg" is advanced to the next non-white after the recognized expression. 2164 * 2165 * Return OK or FAIL. 2166 */ 2167 static int 2168 eval6(arg, retvar, evaluate) 2169 char_u **arg; 2170 VAR retvar; 2171 int evaluate; 2172 { 2173 var var2; 2174 int op; 2175 long n1, n2; 2176 2177 /* 2178 * Get the first variable. 2179 */ 2180 if (eval7(arg, retvar, evaluate) == FAIL) 2181 return FAIL; 2182 2183 /* 2184 * Repeat computing, until no '*', '/' or '%' is following. 2185 */ 2186 for (;;) 2187 { 2188 op = **arg; 2189 if (op != '*' && op != '/' && op != '%') 2190 break; 2191 2192 if (evaluate) 2193 { 2194 n1 = get_var_number(retvar); 2195 clear_var(retvar); 2196 } 2197 else 2198 n1 = 0; 2199 2200 /* 2201 * Get the second variable. 2202 */ 2203 *arg = skipwhite(*arg + 1); 2204 if (eval7(arg, &var2, evaluate) == FAIL) 2205 return FAIL; 2206 2207 if (evaluate) 2208 { 2209 n2 = get_var_number(&var2); 2210 clear_var(&var2); 2211 2212 /* 2213 * Compute the result. 2214 */ 2215 if (op == '*') 2216 n1 = n1 * n2; 2217 else if (op == '/') 2218 { 2219 if (n2 == 0) /* give an error message? */ 2220 n1 = 0x7fffffffL; 2221 else 2222 n1 = n1 / n2; 2223 } 2224 else 2225 { 2226 if (n2 == 0) /* give an error message? */ 2227 n1 = 0; 2228 else 2229 n1 = n1 % n2; 2230 } 2231 retvar->var_type = VAR_NUMBER; 2232 retvar->var_val.var_number = n1; 2233 } 2234 } 2235 2236 return OK; 2237 } 2238 2239 /* 2240 * Handle sixth level expression: 2241 * number number constant 2242 * "string" string contstant 2243 * 'string' literal string contstant 2244 * &option-name option value 2245 * @r register contents 2246 * identifier variable value 2247 * function() function call 2248 * $VAR environment variable 2249 * (expression) nested expression 2250 * 2251 * Also handle: 2252 * ! in front logical NOT 2253 * - in front unary minus 2254 * + in front unary plus (ignored) 2255 * trailing [] subscript in String 2256 * 2257 * "arg" must point to the first non-white of the expression. 2258 * "arg" is advanced to the next non-white after the recognized expression. 2259 * 2260 * Return OK or FAIL. 2261 */ 2262 static int 2263 eval7(arg, retvar, evaluate) 2264 char_u **arg; 2265 VAR retvar; 2266 int evaluate; 2267 { 2268 var var2; 2269 long n; 2270 int len; 2271 char_u *s; 2272 int val; 2273 char_u *start_leader, *end_leader; 2274 int ret = OK; 2275 char_u *alias; 2276 2277 /* 2278 * Initialise variable so that clear_var() can't mistake this for a string 2279 * and free a string that isn't there. 2280 */ 2281 retvar->var_type = VAR_UNKNOWN; 2282 2283 /* 2284 * Skip '!' and '-' characters. They are handled later. 2285 */ 2286 start_leader = *arg; 2287 while (**arg == '!' || **arg == '-' || **arg == '+') 2288 *arg = skipwhite(*arg + 1); 2289 end_leader = *arg; 2290 2291 switch (**arg) 2292 { 2293 /* 2294 * Number constant. 2295 */ 2296 case '0': 2297 case '1': 2298 case '2': 2299 case '3': 2300 case '4': 2301 case '5': 2302 case '6': 2303 case '7': 2304 case '8': 2305 case '9': 2306 vim_str2nr(*arg, NULL, &len, TRUE, TRUE, &n, NULL); 2307 *arg += len; 2308 if (evaluate) 2309 { 2310 retvar->var_type = VAR_NUMBER; 2311 retvar->var_val.var_number = n; 2312 } 2313 break; 2314 2315 /* 2316 * String constant: "string". 2317 */ 2318 case '"': ret = get_string_var(arg, retvar, evaluate); 2319 break; 2320 2321 /* 2322 * Literal string constant: 'string'. 2323 */ 2324 case '\'': ret = get_lit_string_var(arg, retvar, evaluate); 2325 break; 2326 2327 /* 2328 * Option value: &name 2329 */ 2330 case '&': ret = get_option_var(arg, retvar, evaluate); 2331 break; 2332 2333 /* 2334 * Environment variable: $VAR. 2335 */ 2336 case '$': ret = get_env_var(arg, retvar, evaluate); 2337 break; 2338 2339 /* 2340 * Register contents: @r. 2341 */ 2342 case '@': ++*arg; 2343 if (evaluate) 2344 { 2345 retvar->var_type = VAR_STRING; 2346 retvar->var_val.var_string = get_reg_contents(**arg, FALSE); 2347 } 2348 if (**arg != NUL) 2349 ++*arg; 2350 break; 2351 2352 /* 2353 * nested expression: (expression). 2354 */ 2355 case '(': *arg = skipwhite(*arg + 1); 2356 ret = eval1(arg, retvar, evaluate); /* recursive! */ 2357 if (**arg == ')') 2358 ++*arg; 2359 else if (ret == OK) 2360 { 2361 EMSG(_("E110: Missing ')'")); 2362 clear_var(retvar); 2363 ret = FAIL; 2364 } 2365 break; 2366 2367 /* 2368 * Must be a variable or function name then. 2369 */ 2370 default: s = *arg; 2371 len = get_func_len(arg, &alias, evaluate); 2372 if (alias != NULL) 2373 s = alias; 2374 2375 if (len == 0) 2376 ret = FAIL; 2377 else 2378 { 2379 if (**arg == '(') /* recursive! */ 2380 { 2381 ret = get_func_var(s, len, retvar, arg, 2382 curwin->w_cursor.lnum, curwin->w_cursor.lnum, 2383 &len, evaluate); 2384 /* Stop the expression evaluation when immediately 2385 * aborting on error, or when an interrupt occurred or 2386 * an exception was thrown but not caught. */ 2387 if (aborting()) 2388 { 2389 if (ret == OK) 2390 clear_var(retvar); 2391 ret = FAIL; 2392 } 2393 } 2394 else if (evaluate) 2395 ret = get_var_var(s, len, retvar); 2396 } 2397 2398 if (alias != NULL) 2399 vim_free(alias); 2400 2401 break; 2402 } 2403 *arg = skipwhite(*arg); 2404 2405 /* 2406 * Handle expr[expr] subscript. 2407 */ 2408 if (**arg == '[' && ret == OK) 2409 { 2410 /* 2411 * Get the variable from inside the []. 2412 */ 2413 *arg = skipwhite(*arg + 1); 2414 if (eval1(arg, &var2, evaluate) == FAIL) /* recursive! */ 2415 { 2416 clear_var(retvar); 2417 return FAIL; 2418 } 2419 2420 /* Check for the ']'. */ 2421 if (**arg != ']') 2422 { 2423 EMSG(_("E111: Missing ']'")); 2424 clear_var(retvar); 2425 clear_var(&var2); 2426 return FAIL; 2427 } 2428 2429 if (evaluate) 2430 { 2431 n = get_var_number(&var2); 2432 clear_var(&var2); 2433 2434 /* 2435 * The resulting variable is a string of a single character. 2436 * If the index is too big or negative, the result is empty. 2437 */ 2438 s = get_var_string(retvar); 2439 if (n >= (long)STRLEN(s) || n < 0) 2440 s = NULL; 2441 else 2442 s = vim_strnsave(s + n, 1); 2443 clear_var(retvar); 2444 retvar->var_type = VAR_STRING; 2445 retvar->var_val.var_string = s; 2446 } 2447 *arg = skipwhite(*arg + 1); /* skip the ']' */ 2448 } 2449 2450 /* 2451 * Apply logical NOT and unary '-', from right to left, ignore '+'. 2452 */ 2453 if (ret == OK && evaluate && end_leader > start_leader) 2454 { 2455 val = get_var_number(retvar); 2456 while (end_leader > start_leader) 2457 { 2458 --end_leader; 2459 if (*end_leader == '!') 2460 val = !val; 2461 else if (*end_leader == '-') 2462 val = -val; 2463 } 2464 clear_var(retvar); 2465 retvar->var_type = VAR_NUMBER; 2466 retvar->var_val.var_number = val; 2467 } 2468 2469 return ret; 2470 } 2471 2472 /* 2473 * Get an option value. 2474 * "arg" points to the '&' or '+' before the option name. 2475 * "arg" is advanced to character after the option name. 2476 * Return OK or FAIL. 2477 */ 2478 static int 2479 get_option_var(arg, retvar, evaluate) 2480 char_u **arg; 2481 VAR retvar; /* when NULL, only check if option exists */ 2482 int evaluate; 2483 { 2484 char_u *option_end; 2485 long numval; 2486 char_u *stringval; 2487 int opt_type; 2488 int c; 2489 int working = (**arg == '+'); /* has("+option") */ 2490 int ret = OK; 2491 int opt_flags; 2492 2493 /* 2494 * Isolate the option name and find its value. 2495 */ 2496 option_end = find_option_end(arg, &opt_flags); 2497 if (option_end == NULL) 2498 { 2499 if (retvar != NULL) 2500 EMSG2(_("E112: Option name missing: %s"), *arg); 2501 return FAIL; 2502 } 2503 2504 if (!evaluate) 2505 { 2506 *arg = option_end; 2507 return OK; 2508 } 2509 2510 c = *option_end; 2511 *option_end = NUL; 2512 opt_type = get_option_value(*arg, &numval, 2513 retvar == NULL ? NULL : &stringval, opt_flags); 2514 2515 if (opt_type == -3) /* invalid name */ 2516 { 2517 if (retvar != NULL) 2518 EMSG2(_("E113: Unknown option: %s"), *arg); 2519 ret = FAIL; 2520 } 2521 else if (retvar != NULL) 2522 { 2523 if (opt_type == -2) /* hidden string option */ 2524 { 2525 retvar->var_type = VAR_STRING; 2526 retvar->var_val.var_string = NULL; 2527 } 2528 else if (opt_type == -1) /* hidden number option */ 2529 { 2530 retvar->var_type = VAR_NUMBER; 2531 retvar->var_val.var_number = 0; 2532 } 2533 else if (opt_type == 1) /* number option */ 2534 { 2535 retvar->var_type = VAR_NUMBER; 2536 retvar->var_val.var_number = numval; 2537 } 2538 else /* string option */ 2539 { 2540 retvar->var_type = VAR_STRING; 2541 retvar->var_val.var_string = stringval; 2542 } 2543 } 2544 else if (working && (opt_type == -2 || opt_type == -1)) 2545 ret = FAIL; 2546 2547 *option_end = c; /* put back for error messages */ 2548 *arg = option_end; 2549 2550 return ret; 2551 } 2552 2553 /* 2554 * Allocate a variable for a string constant. 2555 * Return OK or FAIL. 2556 */ 2557 static int 2558 get_string_var(arg, retvar, evaluate) 2559 char_u **arg; 2560 VAR retvar; 2561 int evaluate; 2562 { 2563 char_u *p; 2564 char_u *name; 2565 int i; 2566 int extra = 0; 2567 2568 /* 2569 * Find the end of the string, skipping backslashed characters. 2570 */ 2571 for (p = *arg + 1; *p && *p != '"'; ++p) 2572 { 2573 if (*p == '\\' && p[1] != NUL) 2574 { 2575 ++p; 2576 /* A "\<x>" form occupies at least 4 characters, and produces up 2577 * to 6 characters: reserve space for 2 extra */ 2578 if (*p == '<') 2579 extra += 2; 2580 } 2581 #ifdef FEAT_MBYTE 2582 if (has_mbyte) 2583 p += (*mb_ptr2len_check)(p) - 1; 2584 #endif 2585 } 2586 2587 if (*p != '"') 2588 { 2589 EMSG2(_("E114: Missing quote: %s"), *arg); 2590 return FAIL; 2591 } 2592 2593 /* If only parsing, set *arg and return here */ 2594 if (!evaluate) 2595 { 2596 *arg = p + 1; 2597 return OK; 2598 } 2599 2600 /* 2601 * Copy the string into allocated memory, handling backslashed 2602 * characters. 2603 */ 2604 name = alloc((unsigned)(p - *arg + extra)); 2605 if (name == NULL) 2606 return FAIL; 2607 2608 i = 0; 2609 for (p = *arg + 1; *p && *p != '"'; ++p) 2610 { 2611 if (*p == '\\') 2612 { 2613 switch (*++p) 2614 { 2615 case 'b': name[i++] = BS; break; 2616 case 'e': name[i++] = ESC; break; 2617 case 'f': name[i++] = FF; break; 2618 case 'n': name[i++] = NL; break; 2619 case 'r': name[i++] = CAR; break; 2620 case 't': name[i++] = TAB; break; 2621 2622 case 'X': /* hex: "\x1", "\x12" */ 2623 case 'x': 2624 case 'u': /* Unicode: "\u0023" */ 2625 case 'U': 2626 if (vim_isxdigit(p[1])) 2627 { 2628 int n, nr; 2629 int c = toupper(*p); 2630 2631 if (c == 'X') 2632 n = 2; 2633 else 2634 n = 4; 2635 nr = 0; 2636 while (--n >= 0 && vim_isxdigit(p[1])) 2637 { 2638 ++p; 2639 nr = (nr << 4) + hex2nr(*p); 2640 } 2641 #ifdef FEAT_MBYTE 2642 /* For "\u" store the number according to 2643 * 'encoding'. */ 2644 if (c != 'X') 2645 i += (*mb_char2bytes)(nr, name + i); 2646 else 2647 #endif 2648 name[i++] = nr; 2649 } 2650 else 2651 name[i++] = *p; 2652 break; 2653 2654 /* octal: "\1", "\12", "\123" */ 2655 case '0': 2656 case '1': 2657 case '2': 2658 case '3': 2659 case '4': 2660 case '5': 2661 case '6': 2662 case '7': name[i] = *p - '0'; 2663 if (p[1] >= '0' && p[1] <= '7') 2664 { 2665 ++p; 2666 name[i] = (name[i] << 3) + *p - '0'; 2667 if (p[1] >= '0' && p[1] <= '7') 2668 { 2669 ++p; 2670 name[i] = (name[i] << 3) + *p - '0'; 2671 } 2672 } 2673 ++i; 2674 break; 2675 2676 /* Special key, e.g.: "\<C-W>" */ 2677 case '<': extra = trans_special(&p, name + i, TRUE); 2678 if (extra != 0) 2679 { 2680 i += extra; 2681 --p; 2682 break; 2683 } 2684 /* FALLTHROUGH */ 2685 2686 default: name[i++] = *p; 2687 break; 2688 } 2689 } 2690 else 2691 name[i++] = *p; 2692 2693 #ifdef FEAT_MBYTE 2694 /* For a multi-byte character copy the bytes after the first one. */ 2695 if (has_mbyte) 2696 { 2697 int l = (*mb_ptr2len_check)(p); 2698 2699 while (--l > 0) 2700 name[i++] = *++p; 2701 } 2702 #endif 2703 } 2704 name[i] = NUL; 2705 *arg = p + 1; 2706 2707 retvar->var_type = VAR_STRING; 2708 retvar->var_val.var_string = name; 2709 2710 return OK; 2711 } 2712 2713 /* 2714 * Allocate a variable for an backtick-string constant. 2715 * Return OK or FAIL. 2716 */ 2717 static int 2718 get_lit_string_var(arg, retvar, evaluate) 2719 char_u **arg; 2720 VAR retvar; 2721 int evaluate; 2722 { 2723 char_u *p; 2724 char_u *name; 2725 2726 /* 2727 * Find the end of the string. 2728 */ 2729 p = vim_strchr(*arg + 1, '\''); 2730 if (p == NULL) 2731 { 2732 EMSG2(_("E115: Missing quote: %s"), *arg); 2733 return FAIL; 2734 } 2735 2736 if (evaluate) 2737 { 2738 /* 2739 * Copy the string into allocated memory. 2740 */ 2741 name = vim_strnsave(*arg + 1, (int)(p - (*arg + 1))); 2742 if (name == NULL) 2743 return FAIL; 2744 2745 retvar->var_type = VAR_STRING; 2746 retvar->var_val.var_string = name; 2747 } 2748 2749 *arg = p + 1; 2750 2751 return OK; 2752 } 2753 2754 /* 2755 * Get the value of an environment variable. 2756 * "arg" is pointing to the '$'. It is advanced to after the name. 2757 * If the environment variable was not set, silently assume it is empty. 2758 * Always return OK. 2759 */ 2760 static int 2761 get_env_var(arg, retvar, evaluate) 2762 char_u **arg; 2763 VAR retvar; 2764 int evaluate; 2765 { 2766 char_u *string = NULL; 2767 int len; 2768 int cc; 2769 char_u *name; 2770 2771 ++*arg; 2772 name = *arg; 2773 len = get_env_len(arg); 2774 if (evaluate) 2775 { 2776 if (len != 0) 2777 { 2778 cc = name[len]; 2779 name[len] = NUL; 2780 /* first try mch_getenv(), fast for normal environment vars */ 2781 string = mch_getenv(name); 2782 if (string != NULL && *string != NUL) 2783 string = vim_strsave(string); 2784 else 2785 { 2786 /* next try expanding things like $VIM and ${HOME} */ 2787 string = expand_env_save(name - 1); 2788 if (string != NULL && *string == '$') 2789 { 2790 vim_free(string); 2791 string = NULL; 2792 } 2793 } 2794 name[len] = cc; 2795 } 2796 retvar->var_type = VAR_STRING; 2797 retvar->var_val.var_string = string; 2798 } 2799 2800 return OK; 2801 } 2802 2803 /* 2804 * Array with names and number of arguments of all internal functions 2805 * MUST BE KEPT SORTED IN strcmp() ORDER FOR BINARY SEARCH! 2806 */ 2807 static struct fst 2808 { 2809 char *f_name; /* function name */ 2810 char f_min_argc; /* minimal number of arguments */ 2811 char f_max_argc; /* maximal number of arguments */ 2812 void (*f_func) __ARGS((VAR args, VAR rvar)); /* impl. function */ 2813 } functions[] = 2814 { 2815 {"append", 2, 2, f_append}, 2816 {"argc", 0, 0, f_argc}, 2817 {"argidx", 0, 0, f_argidx}, 2818 {"argv", 1, 1, f_argv}, 2819 {"browse", 4, 4, f_browse}, 2820 {"browsedir", 2, 2, f_browsedir}, 2821 {"bufexists", 1, 1, f_bufexists}, 2822 {"buffer_exists", 1, 1, f_bufexists}, /* obsolete */ 2823 {"buffer_name", 1, 1, f_bufname}, /* obsolete */ 2824 {"buffer_number", 1, 1, f_bufnr}, /* obsolete */ 2825 {"buflisted", 1, 1, f_buflisted}, 2826 {"bufloaded", 1, 1, f_bufloaded}, 2827 {"bufname", 1, 1, f_bufname}, 2828 {"bufnr", 1, 1, f_bufnr}, 2829 {"bufwinnr", 1, 1, f_bufwinnr}, 2830 {"byte2line", 1, 1, f_byte2line}, 2831 {"byteidx", 2, 2, f_byteidx}, 2832 {"char2nr", 1, 1, f_char2nr}, 2833 {"cindent", 1, 1, f_cindent}, 2834 {"col", 1, 1, f_col}, 2835 {"confirm", 1, 4, f_confirm}, 2836 {"cscope_connection",0,3, f_cscope_connection}, 2837 {"cursor", 2, 2, f_cursor}, 2838 {"delete", 1, 1, f_delete}, 2839 {"did_filetype", 0, 0, f_did_filetype}, 2840 {"escape", 2, 2, f_escape}, 2841 {"eventhandler", 0, 0, f_eventhandler}, 2842 {"executable", 1, 1, f_executable}, 2843 {"exists", 1, 1, f_exists}, 2844 {"expand", 1, 2, f_expand}, 2845 {"file_readable", 1, 1, f_filereadable}, /* obsolete */ 2846 {"filereadable", 1, 1, f_filereadable}, 2847 {"filewritable", 1, 1, f_filewritable}, 2848 {"finddir", 1, 3, f_finddir}, 2849 {"findfile", 1, 3, f_findfile}, 2850 {"fnamemodify", 2, 2, f_fnamemodify}, 2851 {"foldclosed", 1, 1, f_foldclosed}, 2852 {"foldclosedend", 1, 1, f_foldclosedend}, 2853 {"foldlevel", 1, 1, f_foldlevel}, 2854 {"foldtext", 0, 0, f_foldtext}, 2855 {"foldtextresult", 1, 1, f_foldtextresult}, 2856 {"foreground", 0, 0, f_foreground}, 2857 {"getbufvar", 2, 2, f_getbufvar}, 2858 {"getchar", 0, 1, f_getchar}, 2859 {"getcharmod", 0, 0, f_getcharmod}, 2860 {"getcmdline", 0, 0, f_getcmdline}, 2861 {"getcmdpos", 0, 0, f_getcmdpos}, 2862 {"getcwd", 0, 0, f_getcwd}, 2863 {"getfperm", 1, 1, f_getfperm}, 2864 {"getfsize", 1, 1, f_getfsize}, 2865 {"getftime", 1, 1, f_getftime}, 2866 {"getftype", 1, 1, f_getftype}, 2867 {"getline", 1, 1, f_getline}, 2868 {"getreg", 0, 1, f_getreg}, 2869 {"getregtype", 0, 1, f_getregtype}, 2870 {"getwinposx", 0, 0, f_getwinposx}, 2871 {"getwinposy", 0, 0, f_getwinposy}, 2872 {"getwinvar", 2, 2, f_getwinvar}, 2873 {"glob", 1, 1, f_glob}, 2874 {"globpath", 2, 2, f_globpath}, 2875 {"has", 1, 1, f_has}, 2876 {"hasmapto", 1, 2, f_hasmapto}, 2877 {"highlightID", 1, 1, f_hlID}, /* obsolete */ 2878 {"highlight_exists",1, 1, f_hlexists}, /* obsolete */ 2879 {"histadd", 2, 2, f_histadd}, 2880 {"histdel", 1, 2, f_histdel}, 2881 {"histget", 1, 2, f_histget}, 2882 {"histnr", 1, 1, f_histnr}, 2883 {"hlID", 1, 1, f_hlID}, 2884 {"hlexists", 1, 1, f_hlexists}, 2885 {"hostname", 0, 0, f_hostname}, 2886 {"iconv", 3, 3, f_iconv}, 2887 {"indent", 1, 1, f_indent}, 2888 {"input", 1, 2, f_input}, 2889 {"inputdialog", 1, 3, f_inputdialog}, 2890 {"inputrestore", 0, 0, f_inputrestore}, 2891 {"inputsave", 0, 0, f_inputsave}, 2892 {"inputsecret", 1, 2, f_inputsecret}, 2893 {"isdirectory", 1, 1, f_isdirectory}, 2894 {"last_buffer_nr", 0, 0, f_last_buffer_nr},/* obsolete */ 2895 {"libcall", 3, 3, f_libcall}, 2896 {"libcallnr", 3, 3, f_libcallnr}, 2897 {"line", 1, 1, f_line}, 2898 {"line2byte", 1, 1, f_line2byte}, 2899 {"lispindent", 1, 1, f_lispindent}, 2900 {"localtime", 0, 0, f_localtime}, 2901 {"maparg", 1, 2, f_maparg}, 2902 {"mapcheck", 1, 2, f_mapcheck}, 2903 {"match", 2, 4, f_match}, 2904 {"matchend", 2, 4, f_matchend}, 2905 {"matchstr", 2, 4, f_matchstr}, 2906 {"mode", 0, 0, f_mode}, 2907 {"nextnonblank", 1, 1, f_nextnonblank}, 2908 {"nr2char", 1, 1, f_nr2char}, 2909 {"prevnonblank", 1, 1, f_prevnonblank}, 2910 {"remote_expr", 2, 3, f_remote_expr}, 2911 {"remote_foreground", 1, 1, f_remote_foreground}, 2912 {"remote_peek", 1, 2, f_remote_peek}, 2913 {"remote_read", 1, 1, f_remote_read}, 2914 {"remote_send", 2, 3, f_remote_send}, 2915 {"rename", 2, 2, f_rename}, 2916 {"repeat", 2, 2, f_repeat}, 2917 {"resolve", 1, 1, f_resolve}, 2918 {"search", 1, 2, f_search}, 2919 {"searchpair", 3, 5, f_searchpair}, 2920 {"server2client", 2, 2, f_server2client}, 2921 {"serverlist", 0, 0, f_serverlist}, 2922 {"setbufvar", 3, 3, f_setbufvar}, 2923 {"setcmdpos", 1, 1, f_setcmdpos}, 2924 {"setline", 2, 2, f_setline}, 2925 {"setreg", 2, 3, f_setreg}, 2926 {"setwinvar", 3, 3, f_setwinvar}, 2927 {"simplify", 1, 1, f_simplify}, 2928 #ifdef HAVE_STRFTIME 2929 {"strftime", 1, 2, f_strftime}, 2930 #endif 2931 {"stridx", 2, 2, f_stridx}, 2932 {"strlen", 1, 1, f_strlen}, 2933 {"strpart", 2, 3, f_strpart}, 2934 {"strridx", 2, 2, f_strridx}, 2935 {"strtrans", 1, 1, f_strtrans}, 2936 {"submatch", 1, 1, f_submatch}, 2937 {"substitute", 4, 4, f_substitute}, 2938 {"synID", 3, 3, f_synID}, 2939 {"synIDattr", 2, 3, f_synIDattr}, 2940 {"synIDtrans", 1, 1, f_synIDtrans}, 2941 {"system", 1, 2, f_system}, 2942 {"tempname", 0, 0, f_tempname}, 2943 {"tolower", 1, 1, f_tolower}, 2944 {"toupper", 1, 1, f_toupper}, 2945 {"tr", 3, 3, f_tr}, 2946 {"type", 1, 1, f_type}, 2947 {"virtcol", 1, 1, f_virtcol}, 2948 {"visualmode", 0, 1, f_visualmode}, 2949 {"winbufnr", 1, 1, f_winbufnr}, 2950 {"wincol", 0, 0, f_wincol}, 2951 {"winheight", 1, 1, f_winheight}, 2952 {"winline", 0, 0, f_winline}, 2953 {"winnr", 0, 1, f_winnr}, 2954 {"winrestcmd", 0, 0, f_winrestcmd}, 2955 {"winwidth", 1, 1, f_winwidth}, 2956 }; 2957 2958 #if defined(FEAT_CMDL_COMPL) || defined(PROTO) 2959 2960 /* 2961 * Function given to ExpandGeneric() to obtain the list of internal 2962 * or user defined function names. 2963 */ 2964 char_u * 2965 get_function_name(xp, idx) 2966 expand_T *xp; 2967 int idx; 2968 { 2969 static int intidx = -1; 2970 char_u *name; 2971 2972 if (idx == 0) 2973 intidx = -1; 2974 if (intidx < 0) 2975 { 2976 name = get_user_func_name(xp, idx); 2977 if (name != NULL) 2978 return name; 2979 } 2980 if (++intidx < (int)(sizeof(functions) / sizeof(struct fst))) 2981 { 2982 STRCPY(IObuff, functions[intidx].f_name); 2983 STRCAT(IObuff, "("); 2984 if (functions[intidx].f_max_argc == 0) 2985 STRCAT(IObuff, ")"); 2986 return IObuff; 2987 } 2988 2989 return NULL; 2990 } 2991 2992 /* 2993 * Function given to ExpandGeneric() to obtain the list of internal or 2994 * user defined variable or function names. 2995 */ 2996 /*ARGSUSED*/ 2997 char_u * 2998 get_expr_name(xp, idx) 2999 expand_T *xp; 3000 int idx; 3001 { 3002 static int intidx = -1; 3003 char_u *name; 3004 3005 if (idx == 0) 3006 intidx = -1; 3007 if (intidx < 0) 3008 { 3009 name = get_function_name(xp, idx); 3010 if (name != NULL) 3011 return name; 3012 } 3013 return get_user_var_name(xp, ++intidx); 3014 } 3015 3016 #endif /* FEAT_CMDL_COMPL */ 3017 3018 /* 3019 * Find internal function in table above. 3020 * Return index, or -1 if not found 3021 */ 3022 static int 3023 find_internal_func(name) 3024 char_u *name; /* name of the function */ 3025 { 3026 int first = 0; 3027 int last = (int)(sizeof(functions) / sizeof(struct fst)) - 1; 3028 int cmp; 3029 int x; 3030 3031 /* 3032 * Find the function name in the table. Binary search. 3033 */ 3034 while (first <= last) 3035 { 3036 x = first + ((unsigned)(last - first) >> 1); 3037 cmp = STRCMP(name, functions[x].f_name); 3038 if (cmp < 0) 3039 last = x - 1; 3040 else if (cmp > 0) 3041 first = x + 1; 3042 else 3043 return x; 3044 } 3045 return -1; 3046 } 3047 3048 /* 3049 * Allocate a variable for the result of a function. 3050 * Return OK or FAIL. 3051 */ 3052 static int 3053 get_func_var(name, len, retvar, arg, firstline, lastline, doesrange, evaluate) 3054 char_u *name; /* name of the function */ 3055 int len; /* length of "name" */ 3056 VAR retvar; 3057 char_u **arg; /* argument, pointing to the '(' */ 3058 linenr_T firstline; /* first line of range */ 3059 linenr_T lastline; /* last line of range */ 3060 int *doesrange; /* return: function handled range */ 3061 int evaluate; 3062 { 3063 char_u *argp; 3064 int ret = OK; 3065 #define MAX_FUNC_ARGS 20 3066 var argvars[MAX_FUNC_ARGS]; /* vars for arguments */ 3067 int argcount = 0; /* number of arguments found */ 3068 3069 /* 3070 * Get the arguments. 3071 */ 3072 argp = *arg; 3073 while (argcount < MAX_FUNC_ARGS) 3074 { 3075 argp = skipwhite(argp + 1); /* skip the '(' or ',' */ 3076 if (*argp == ')' || *argp == ',' || *argp == NUL) 3077 break; 3078 argvars[argcount].var_name = NULL; /* the name is not stored */ 3079 if (eval1(&argp, &argvars[argcount], evaluate) == FAIL) 3080 { 3081 ret = FAIL; 3082 break; 3083 } 3084 ++argcount; 3085 if (*argp != ',') 3086 break; 3087 } 3088 if (*argp == ')') 3089 ++argp; 3090 else 3091 ret = FAIL; 3092 3093 if (ret == OK) 3094 ret = call_func(name, len, retvar, argcount, argvars, 3095 firstline, lastline, doesrange, evaluate); 3096 else if (!aborting()) 3097 EMSG2(_("E116: Invalid arguments for function %s"), name); 3098 3099 while (--argcount >= 0) 3100 clear_var(&argvars[argcount]); 3101 3102 *arg = skipwhite(argp); 3103 return ret; 3104 } 3105 3106 3107 /* 3108 * Call a function with its resolved parameters 3109 * Return OK or FAIL. 3110 */ 3111 static int 3112 call_func(name, len, retvar, argcount, argvars, firstline, lastline, 3113 doesrange, evaluate) 3114 char_u *name; /* name of the function */ 3115 int len; /* length of "name" */ 3116 VAR retvar; /* return value goes here */ 3117 int argcount; /* number of "argvars" */ 3118 VAR argvars; /* vars for arguments */ 3119 linenr_T firstline; /* first line of range */ 3120 linenr_T lastline; /* last line of range */ 3121 int *doesrange; /* return: function handled range */ 3122 int evaluate; 3123 { 3124 int ret = FAIL; 3125 static char *errors[] = 3126 {N_("E117: Unknown function: %s"), 3127 N_("E118: Too many arguments for function: %s"), 3128 N_("E119: Not enough arguments for function: %s"), 3129 N_("E120: Using <SID> not in a script context: %s"), 3130 }; 3131 #define ERROR_UNKNOWN 0 3132 #define ERROR_TOOMANY 1 3133 #define ERROR_TOOFEW 2 3134 #define ERROR_SCRIPT 3 3135 #define ERROR_NONE 4 3136 #define ERROR_OTHER 5 3137 int error = ERROR_NONE; 3138 int i; 3139 int llen; 3140 ufunc_T *fp; 3141 int cc; 3142 #define FLEN_FIXED 40 3143 char_u fname_buf[FLEN_FIXED + 1]; 3144 char_u *fname; 3145 3146 /* 3147 * In a script change <SID>name() and s:name() to K_SNR 123_name(). 3148 * Change <SNR>123_name() to K_SNR 123_name(). 3149 * Use fname_buf[] when it fits, otherwise allocate memory (slow). 3150 */ 3151 cc = name[len]; 3152 name[len] = NUL; 3153 llen = eval_fname_script(name); 3154 if (llen > 0) 3155 { 3156 fname_buf[0] = K_SPECIAL; 3157 fname_buf[1] = KS_EXTRA; 3158 fname_buf[2] = (int)KE_SNR; 3159 i = 3; 3160 if (eval_fname_sid(name)) /* "<SID>" or "s:" */ 3161 { 3162 if (current_SID <= 0) 3163 error = ERROR_SCRIPT; 3164 else 3165 { 3166 sprintf((char *)fname_buf + 3, "%ld_", (long)current_SID); 3167 i = (int)STRLEN(fname_buf); 3168 } 3169 } 3170 if (i + STRLEN(name + llen) < FLEN_FIXED) 3171 { 3172 STRCPY(fname_buf + i, name + llen); 3173 fname = fname_buf; 3174 } 3175 else 3176 { 3177 fname = alloc((unsigned)(i + STRLEN(name + llen) + 1)); 3178 if (fname == NULL) 3179 error = ERROR_OTHER; 3180 else 3181 { 3182 mch_memmove(fname, fname_buf, (size_t)i); 3183 STRCPY(fname + i, name + llen); 3184 } 3185 } 3186 } 3187 else 3188 fname = name; 3189 3190 *doesrange = FALSE; 3191 3192 3193 /* execute the function if no errors detected and executing */ 3194 if (evaluate && error == ERROR_NONE) 3195 { 3196 retvar->var_type = VAR_NUMBER; /* default is number retvar */ 3197 error = ERROR_UNKNOWN; 3198 3199 if (!ASCII_ISLOWER(fname[0])) 3200 { 3201 /* 3202 * User defined function. 3203 */ 3204 fp = find_func(fname); 3205 #ifdef FEAT_AUTOCMD 3206 if (fp == NULL && apply_autocmds(EVENT_FUNCUNDEFINED, 3207 fname, fname, TRUE, NULL) 3208 #ifdef FEAT_EVAL 3209 && !aborting() 3210 #endif 3211 ) 3212 { 3213 /* executed an autocommand, search for function again */ 3214 fp = find_func(fname); 3215 } 3216 #endif 3217 if (fp != NULL) 3218 { 3219 if (fp->flags & FC_RANGE) 3220 *doesrange = TRUE; 3221 if (argcount < fp->args.ga_len) 3222 error = ERROR_TOOFEW; 3223 else if (!fp->varargs && argcount > fp->args.ga_len) 3224 error = ERROR_TOOMANY; 3225 else 3226 { 3227 /* 3228 * Call the user function. 3229 * Save and restore search patterns, script variables and 3230 * redo buffer. 3231 */ 3232 save_search_patterns(); 3233 saveRedobuff(); 3234 ++fp->calls; 3235 call_user_func(fp, argcount, argvars, retvar, 3236 firstline, lastline); 3237 --fp->calls; 3238 restoreRedobuff(); 3239 restore_search_patterns(); 3240 error = ERROR_NONE; 3241 } 3242 } 3243 } 3244 else 3245 { 3246 /* 3247 * Find the function name in the table, call its implementation. 3248 */ 3249 i = find_internal_func(fname); 3250 if (i >= 0) 3251 { 3252 if (argcount < functions[i].f_min_argc) 3253 error = ERROR_TOOFEW; 3254 else if (argcount > functions[i].f_max_argc) 3255 error = ERROR_TOOMANY; 3256 else 3257 { 3258 argvars[argcount].var_type = VAR_UNKNOWN; 3259 functions[i].f_func(argvars, retvar); 3260 error = ERROR_NONE; 3261 } 3262 } 3263 } 3264 /* 3265 * The function call (or "FuncUndefined" autocommand sequence) might 3266 * have been aborted by an error, an interrupt, or an explicitly thrown 3267 * exception that has not been caught so far. This situation can be 3268 * tested for by calling aborting(). For an error in an internal 3269 * function or for the "E132" error in call_user_func(), however, the 3270 * throw point at which the "force_abort" flag (temporarily reset by 3271 * emsg()) is normally updated has not been reached yet. We need to 3272 * update that flag first to make aborting() reliable. 3273 */ 3274 update_force_abort(); 3275 } 3276 if (error == ERROR_NONE) 3277 ret = OK; 3278 3279 /* 3280 * Report an error unless the argument evaluation or function call has been 3281 * cancelled due to an aborting error, an interrupt, or an exception. 3282 */ 3283 if (error < ERROR_NONE && !aborting()) 3284 EMSG2((char_u *)_(errors[error]), name); 3285 3286 name[len] = cc; 3287 if (fname != name && fname != fname_buf) 3288 vim_free(fname); 3289 3290 return ret; 3291 } 3292 3293 /********************************************* 3294 * Implementation of the built-in functions 3295 */ 3296 3297 /* 3298 * "append(lnum, string)" function 3299 */ 3300 static void 3301 f_append(argvars, retvar) 3302 VAR argvars; 3303 VAR retvar; 3304 { 3305 long lnum; 3306 3307 lnum = get_var_lnum(argvars); 3308 retvar->var_val.var_number = 1; /* Default: Failed */ 3309 3310 if (lnum >= 0 3311 && lnum <= curbuf->b_ml.ml_line_count 3312 && u_save(lnum, lnum + 1) == OK) 3313 { 3314 ml_append(lnum, get_var_string(&argvars[1]), (colnr_T)0, FALSE); 3315 if (curwin->w_cursor.lnum > lnum) 3316 ++curwin->w_cursor.lnum; 3317 appended_lines_mark(lnum, 1L); 3318 retvar->var_val.var_number = 0; 3319 } 3320 } 3321 3322 /* 3323 * "argc()" function 3324 */ 3325 /* ARGSUSED */ 3326 static void 3327 f_argc(argvars, retvar) 3328 VAR argvars; 3329 VAR retvar; 3330 { 3331 retvar->var_val.var_number = ARGCOUNT; 3332 } 3333 3334 /* 3335 * "argidx()" function 3336 */ 3337 /* ARGSUSED */ 3338 static void 3339 f_argidx(argvars, retvar) 3340 VAR argvars; 3341 VAR retvar; 3342 { 3343 retvar->var_val.var_number = curwin->w_arg_idx; 3344 } 3345 3346 /* 3347 * "argv(nr)" function 3348 */ 3349 static void 3350 f_argv(argvars, retvar) 3351 VAR argvars; 3352 VAR retvar; 3353 { 3354 int idx; 3355 3356 idx = get_var_number(&argvars[0]); 3357 if (idx >= 0 && idx < ARGCOUNT) 3358 retvar->var_val.var_string = vim_strsave(alist_name(&ARGLIST[idx])); 3359 else 3360 retvar->var_val.var_string = NULL; 3361 retvar->var_type = VAR_STRING; 3362 } 3363 3364 /* 3365 * "browse(save, title, initdir, default)" function 3366 */ 3367 /* ARGSUSED */ 3368 static void 3369 f_browse(argvars, retvar) 3370 VAR argvars; 3371 VAR retvar; 3372 { 3373 #ifdef FEAT_BROWSE 3374 int save; 3375 char_u *title; 3376 char_u *initdir; 3377 char_u *defname; 3378 char_u buf[NUMBUFLEN]; 3379 char_u buf2[NUMBUFLEN]; 3380 3381 save = get_var_number(&argvars[0]); 3382 title = get_var_string(&argvars[1]); 3383 initdir = get_var_string_buf(&argvars[2], buf); 3384 defname = get_var_string_buf(&argvars[3], buf2); 3385 3386 retvar->var_val.var_string = 3387 do_browse(save ? BROWSE_SAVE : 0, 3388 title, defname, NULL, initdir, NULL, curbuf); 3389 #else 3390 retvar->var_val.var_string = NULL; 3391 #endif 3392 retvar->var_type = VAR_STRING; 3393 } 3394 3395 /* 3396 * "browsedir(title, initdir)" function 3397 */ 3398 /* ARGSUSED */ 3399 static void 3400 f_browsedir(argvars, retvar) 3401 VAR argvars; 3402 VAR retvar; 3403 { 3404 #ifdef FEAT_BROWSE 3405 char_u *title; 3406 char_u *initdir; 3407 char_u buf[NUMBUFLEN]; 3408 3409 title = get_var_string(&argvars[0]); 3410 initdir = get_var_string_buf(&argvars[1], buf); 3411 3412 retvar->var_val.var_string = do_browse(BROWSE_DIR, 3413 title, NULL, NULL, initdir, NULL, curbuf); 3414 #else 3415 retvar->var_val.var_string = NULL; 3416 #endif 3417 retvar->var_type = VAR_STRING; 3418 } 3419 3420 /* 3421 * Find a buffer by number or exact name. 3422 */ 3423 static buf_T * 3424 find_buffer(avar) 3425 VAR avar; 3426 { 3427 buf_T *buf = NULL; 3428 char_u *name; 3429 3430 if (avar->var_type == VAR_NUMBER) 3431 buf = buflist_findnr((int)avar->var_val.var_number); 3432 else if (avar->var_val.var_string != NULL) 3433 { 3434 /* First make the name into a full path name */ 3435 name = FullName_save(avar->var_val.var_string, 3436 #ifdef UNIX 3437 TRUE /* force expansion, get rid of symbolic links */ 3438 #else 3439 FALSE 3440 #endif 3441 ); 3442 if (name != NULL) 3443 { 3444 buf = buflist_findname(name); 3445 vim_free(name); 3446 } 3447 if (buf == NULL) 3448 { 3449 /* No full path name match, try a match with a URL or a "nofile" 3450 * buffer, these don't use the full path. */ 3451 for (buf = firstbuf; buf != NULL; buf = buf->b_next) 3452 if (buf->b_fname != NULL 3453 && (path_with_url(buf->b_fname) 3454 #ifdef FEAT_QUICKFIX 3455 || bt_nofile(buf) 3456 #endif 3457 ) 3458 && STRCMP(buf->b_fname, avar->var_val.var_string) == 0) 3459 break; 3460 } 3461 } 3462 return buf; 3463 } 3464 3465 /* 3466 * "bufexists(expr)" function 3467 */ 3468 static void 3469 f_bufexists(argvars, retvar) 3470 VAR argvars; 3471 VAR retvar; 3472 { 3473 retvar->var_val.var_number = (find_buffer(&argvars[0]) != NULL); 3474 } 3475 3476 /* 3477 * "buflisted(expr)" function 3478 */ 3479 static void 3480 f_buflisted(argvars, retvar) 3481 VAR argvars; 3482 VAR retvar; 3483 { 3484 buf_T *buf; 3485 3486 buf = find_buffer(&argvars[0]); 3487 retvar->var_val.var_number = (buf != NULL && buf->b_p_bl); 3488 } 3489 3490 /* 3491 * "bufloaded(expr)" function 3492 */ 3493 static void 3494 f_bufloaded(argvars, retvar) 3495 VAR argvars; 3496 VAR retvar; 3497 { 3498 buf_T *buf; 3499 3500 buf = find_buffer(&argvars[0]); 3501 retvar->var_val.var_number = (buf != NULL && buf->b_ml.ml_mfp != NULL); 3502 } 3503 3504 /* 3505 * Get buffer by number or pattern. 3506 */ 3507 static buf_T * 3508 get_buf_var(avar) 3509 VAR avar; 3510 { 3511 char_u *name = avar->var_val.var_string; 3512 int save_magic; 3513 char_u *save_cpo; 3514 buf_T *buf; 3515 3516 if (avar->var_type == VAR_NUMBER) 3517 return buflist_findnr((int)avar->var_val.var_number); 3518 if (name == NULL || *name == NUL) 3519 return curbuf; 3520 if (name[0] == '$' && name[1] == NUL) 3521 return lastbuf; 3522 3523 /* Ignore 'magic' and 'cpoptions' here to make scripts portable */ 3524 save_magic = p_magic; 3525 p_magic = TRUE; 3526 save_cpo = p_cpo; 3527 p_cpo = (char_u *)""; 3528 3529 buf = buflist_findnr(buflist_findpat(name, name + STRLEN(name), 3530 TRUE, FALSE)); 3531 3532 p_magic = save_magic; 3533 p_cpo = save_cpo; 3534 3535 /* If not found, try expanding the name, like done for bufexists(). */ 3536 if (buf == NULL) 3537 buf = find_buffer(avar); 3538 3539 return buf; 3540 } 3541 3542 /* 3543 * "bufname(expr)" function 3544 */ 3545 static void 3546 f_bufname(argvars, retvar) 3547 VAR argvars; 3548 VAR retvar; 3549 { 3550 buf_T *buf; 3551 3552 ++emsg_off; 3553 buf = get_buf_var(&argvars[0]); 3554 retvar->var_type = VAR_STRING; 3555 if (buf != NULL && buf->b_fname != NULL) 3556 retvar->var_val.var_string = vim_strsave(buf->b_fname); 3557 else 3558 retvar->var_val.var_string = NULL; 3559 --emsg_off; 3560 } 3561 3562 /* 3563 * "bufnr(expr)" function 3564 */ 3565 static void 3566 f_bufnr(argvars, retvar) 3567 VAR argvars; 3568 VAR retvar; 3569 { 3570 buf_T *buf; 3571 3572 ++emsg_off; 3573 buf = get_buf_var(&argvars[0]); 3574 if (buf != NULL) 3575 retvar->var_val.var_number = buf->b_fnum; 3576 else 3577 retvar->var_val.var_number = -1; 3578 --emsg_off; 3579 } 3580 3581 /* 3582 * "bufwinnr(nr)" function 3583 */ 3584 static void 3585 f_bufwinnr(argvars, retvar) 3586 VAR argvars; 3587 VAR retvar; 3588 { 3589 #ifdef FEAT_WINDOWS 3590 win_T *wp; 3591 int winnr = 0; 3592 #endif 3593 buf_T *buf; 3594 3595 ++emsg_off; 3596 buf = get_buf_var(&argvars[0]); 3597 #ifdef FEAT_WINDOWS 3598 for (wp = firstwin; wp; wp = wp->w_next) 3599 { 3600 ++winnr; 3601 if (wp->w_buffer == buf) 3602 break; 3603 } 3604 retvar->var_val.var_number = (wp != NULL ? winnr : -1); 3605 #else 3606 retvar->var_val.var_number = (curwin->w_buffer == buf ? 1 : -1); 3607 #endif 3608 --emsg_off; 3609 } 3610 3611 /* 3612 * "byte2line(byte)" function 3613 */ 3614 /*ARGSUSED*/ 3615 static void 3616 f_byte2line(argvars, retvar) 3617 VAR argvars; 3618 VAR retvar; 3619 { 3620 #ifndef FEAT_BYTEOFF 3621 retvar->var_val.var_number = -1; 3622 #else 3623 long boff = 0; 3624 3625 boff = get_var_number(&argvars[0]) - 1; 3626 if (boff < 0) 3627 retvar->var_val.var_number = -1; 3628 else 3629 retvar->var_val.var_number = ml_find_line_or_offset(curbuf, 3630 (linenr_T)0, &boff); 3631 #endif 3632 } 3633 3634 /* 3635 * "byteidx()" function 3636 */ 3637 /*ARGSUSED*/ 3638 static void 3639 f_byteidx(argvars, retvar) 3640 VAR argvars; 3641 VAR retvar; 3642 { 3643 #ifdef FEAT_MBYTE 3644 char_u *t; 3645 #endif 3646 char_u *str; 3647 long idx; 3648 3649 str = get_var_string(&argvars[0]); 3650 idx = get_var_number(&argvars[1]); 3651 retvar->var_val.var_number = -1; 3652 if (idx < 0) 3653 return; 3654 3655 #ifdef FEAT_MBYTE 3656 t = str; 3657 for ( ; idx > 0; idx--) 3658 { 3659 if (*t == NUL) /* EOL reached */ 3660 return; 3661 t += mb_ptr2len_check(t); 3662 } 3663 retvar->var_val.var_number = t - str; 3664 #else 3665 if (idx <= STRLEN(str)) 3666 retvar->var_val.var_number = idx; 3667 #endif 3668 } 3669 3670 /* 3671 * "char2nr(string)" function 3672 */ 3673 static void 3674 f_char2nr(argvars, retvar) 3675 VAR argvars; 3676 VAR retvar; 3677 { 3678 #ifdef FEAT_MBYTE 3679 if (has_mbyte) 3680 retvar->var_val.var_number = 3681 (*mb_ptr2char)(get_var_string(&argvars[0])); 3682 else 3683 #endif 3684 retvar->var_val.var_number = get_var_string(&argvars[0])[0]; 3685 } 3686 3687 /* 3688 * "cindent(lnum)" function 3689 */ 3690 static void 3691 f_cindent(argvars, retvar) 3692 VAR argvars; 3693 VAR retvar; 3694 { 3695 #ifdef FEAT_CINDENT 3696 pos_T pos; 3697 linenr_T lnum; 3698 3699 pos = curwin->w_cursor; 3700 lnum = get_var_lnum(argvars); 3701 if (lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count) 3702 { 3703 curwin->w_cursor.lnum = lnum; 3704 retvar->var_val.var_number = get_c_indent(); 3705 curwin->w_cursor = pos; 3706 } 3707 else 3708 #endif 3709 retvar->var_val.var_number = -1; 3710 } 3711 3712 /* 3713 * "col(string)" function 3714 */ 3715 static void 3716 f_col(argvars, retvar) 3717 VAR argvars; 3718 VAR retvar; 3719 { 3720 colnr_T col = 0; 3721 pos_T *fp; 3722 3723 fp = var2fpos(&argvars[0], FALSE); 3724 if (fp != NULL) 3725 { 3726 if (fp->col == MAXCOL) 3727 { 3728 /* '> can be MAXCOL, get the length of the line then */ 3729 if (fp->lnum <= curbuf->b_ml.ml_line_count) 3730 col = STRLEN(ml_get(fp->lnum)) + 1; 3731 else 3732 col = MAXCOL; 3733 } 3734 else 3735 { 3736 col = fp->col + 1; 3737 #ifdef FEAT_VIRTUALEDIT 3738 /* col(".") when the cursor is on the NUL at the end of the line 3739 * because of "coladd" can be seen as an extra column. */ 3740 if (virtual_active() && fp == &curwin->w_cursor) 3741 { 3742 char_u *p = ml_get_cursor(); 3743 3744 if (curwin->w_cursor.coladd >= (colnr_T)chartabsize(p, 3745 curwin->w_virtcol - curwin->w_cursor.coladd)) 3746 { 3747 # ifdef FEAT_MBYTE 3748 int l; 3749 3750 if (*p != NUL && p[(l = (*mb_ptr2len_check)(p))] == NUL) 3751 col += l; 3752 # else 3753 if (*p != NUL && p[1] == NUL) 3754 ++col; 3755 # endif 3756 } 3757 } 3758 #endif 3759 } 3760 } 3761 retvar->var_val.var_number = col; 3762 } 3763 3764 /* 3765 * "confirm(message, buttons[, default [, type]])" function 3766 */ 3767 /*ARGSUSED*/ 3768 static void 3769 f_confirm(argvars, retvar) 3770 VAR argvars; 3771 VAR retvar; 3772 { 3773 #if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG) 3774 char_u *message; 3775 char_u *buttons = NULL; 3776 char_u buf[NUMBUFLEN]; 3777 char_u buf2[NUMBUFLEN]; 3778 int def = 1; 3779 int type = VIM_GENERIC; 3780 int c; 3781 3782 message = get_var_string(&argvars[0]); 3783 if (argvars[1].var_type != VAR_UNKNOWN) 3784 { 3785 buttons = get_var_string_buf(&argvars[1], buf); 3786 if (argvars[2].var_type != VAR_UNKNOWN) 3787 { 3788 def = get_var_number(&argvars[2]); 3789 if (argvars[3].var_type != VAR_UNKNOWN) 3790 { 3791 /* avoid that TOUPPER_ASC calls get_var_string_buf() twice */ 3792 c = *get_var_string_buf(&argvars[3], buf2); 3793 switch (TOUPPER_ASC(c)) 3794 { 3795 case 'E': type = VIM_ERROR; break; 3796 case 'Q': type = VIM_QUESTION; break; 3797 case 'I': type = VIM_INFO; break; 3798 case 'W': type = VIM_WARNING; break; 3799 case 'G': type = VIM_GENERIC; break; 3800 } 3801 } 3802 } 3803 } 3804 3805 if (buttons == NULL || *buttons == NUL) 3806 buttons = (char_u *)_("&Ok"); 3807 3808 retvar->var_val.var_number = do_dialog(type, NULL, message, buttons, 3809 def, NULL); 3810 #else 3811 retvar->var_val.var_number = 0; 3812 #endif 3813 } 3814 3815 3816 /* 3817 * "cscope_connection([{num} , {dbpath} [, {prepend}]])" function 3818 * 3819 * Checks the existence of a cscope connection. 3820 */ 3821 /*ARGSUSED*/ 3822 static void 3823 f_cscope_connection(argvars, retvar) 3824 VAR argvars; 3825 VAR retvar; 3826 { 3827 #ifdef FEAT_CSCOPE 3828 int num = 0; 3829 char_u *dbpath = NULL; 3830 char_u *prepend = NULL; 3831 char_u buf[NUMBUFLEN]; 3832 3833 if (argvars[0].var_type != VAR_UNKNOWN 3834 && argvars[1].var_type != VAR_UNKNOWN) 3835 { 3836 num = (int)get_var_number(&argvars[0]); 3837 dbpath = get_var_string(&argvars[1]); 3838 if (argvars[2].var_type != VAR_UNKNOWN) 3839 prepend = get_var_string_buf(&argvars[2], buf); 3840 } 3841 3842 retvar->var_val.var_number = cs_connection(num, dbpath, prepend); 3843 #else 3844 retvar->var_val.var_number = 0; 3845 #endif 3846 } 3847 3848 /* 3849 * "cursor(lnum, col)" function 3850 * 3851 * Moves the cursor to the specified line and column 3852 */ 3853 /*ARGSUSED*/ 3854 static void 3855 f_cursor(argvars, retvar) 3856 VAR argvars; 3857 VAR retvar; 3858 { 3859 long line, col; 3860 3861 line = get_var_lnum(argvars); 3862 if (line > 0) 3863 curwin->w_cursor.lnum = line; 3864 col = get_var_number(&argvars[1]); 3865 if (col > 0) 3866 curwin->w_cursor.col = col - 1; 3867 #ifdef FEAT_VIRTUALEDIT 3868 curwin->w_cursor.coladd = 0; 3869 #endif 3870 3871 /* Make sure the cursor is in a valid position. */ 3872 check_cursor(); 3873 #ifdef FEAT_MBYTE 3874 /* Correct cursor for multi-byte character. */ 3875 if (has_mbyte) 3876 mb_adjust_cursor(); 3877 #endif 3878 3879 curwin->w_set_curswant = TRUE; 3880 } 3881 3882 /* 3883 * "libcall()" function 3884 */ 3885 static void 3886 f_libcall(argvars, retvar) 3887 VAR argvars; 3888 VAR retvar; 3889 { 3890 libcall_common(argvars, retvar, VAR_STRING); 3891 } 3892 3893 /* 3894 * "libcallnr()" function 3895 */ 3896 static void 3897 f_libcallnr(argvars, retvar) 3898 VAR argvars; 3899 VAR retvar; 3900 { 3901 libcall_common(argvars, retvar, VAR_NUMBER); 3902 } 3903 3904 static void 3905 libcall_common(argvars, retvar, type) 3906 VAR argvars; 3907 VAR retvar; 3908 int type; 3909 { 3910 #ifdef FEAT_LIBCALL 3911 char_u *string_in; 3912 char_u **string_result; 3913 int nr_result; 3914 #endif 3915 3916 retvar->var_type = type; 3917 if (type == VAR_NUMBER) 3918 retvar->var_val.var_number = 0; 3919 else 3920 retvar->var_val.var_string = NULL; 3921 3922 if (check_restricted() || check_secure()) 3923 return; 3924 3925 #ifdef FEAT_LIBCALL 3926 /* The first two args must be strings, otherwise its meaningless */ 3927 if (argvars[0].var_type == VAR_STRING && argvars[1].var_type == VAR_STRING) 3928 { 3929 if (argvars[2].var_type == VAR_NUMBER) 3930 string_in = NULL; 3931 else 3932 string_in = argvars[2].var_val.var_string; 3933 if (type == VAR_NUMBER) 3934 string_result = NULL; 3935 else 3936 string_result = &retvar->var_val.var_string; 3937 if (mch_libcall(argvars[0].var_val.var_string, 3938 argvars[1].var_val.var_string, 3939 string_in, 3940 argvars[2].var_val.var_number, 3941 string_result, 3942 &nr_result) == OK 3943 && type == VAR_NUMBER) 3944 retvar->var_val.var_number = nr_result; 3945 } 3946 #endif 3947 } 3948 3949 /* 3950 * "delete()" function 3951 */ 3952 static void 3953 f_delete(argvars, retvar) 3954 VAR argvars; 3955 VAR retvar; 3956 { 3957 if (check_restricted() || check_secure()) 3958 retvar->var_val.var_number = -1; 3959 else 3960 retvar->var_val.var_number = mch_remove(get_var_string(&argvars[0])); 3961 } 3962 3963 /* 3964 * "did_filetype()" function 3965 */ 3966 /*ARGSUSED*/ 3967 static void 3968 f_did_filetype(argvars, retvar) 3969 VAR argvars; 3970 VAR retvar; 3971 { 3972 #ifdef FEAT_AUTOCMD 3973 retvar->var_val.var_number = did_filetype; 3974 #else 3975 retvar->var_val.var_number = 0; 3976 #endif 3977 } 3978 3979 /* 3980 * "escape({string}, {chars})" function 3981 */ 3982 static void 3983 f_escape(argvars, retvar) 3984 VAR argvars; 3985 VAR retvar; 3986 { 3987 char_u buf[NUMBUFLEN]; 3988 3989 retvar->var_val.var_string = 3990 vim_strsave_escaped(get_var_string(&argvars[0]), 3991 get_var_string_buf(&argvars[1], buf)); 3992 retvar->var_type = VAR_STRING; 3993 } 3994 3995 /* 3996 * "eventhandler()" function 3997 */ 3998 /*ARGSUSED*/ 3999 static void 4000 f_eventhandler(argvars, retvar) 4001 VAR argvars; 4002 VAR retvar; 4003 { 4004 retvar->var_val.var_number = vgetc_busy; 4005 } 4006 4007 /* 4008 * "executable()" function 4009 */ 4010 static void 4011 f_executable(argvars, retvar) 4012 VAR argvars; 4013 VAR retvar; 4014 { 4015 retvar->var_val.var_number = mch_can_exe(get_var_string(&argvars[0])); 4016 } 4017 4018 /* 4019 * "exists()" function 4020 */ 4021 static void 4022 f_exists(argvars, retvar) 4023 VAR argvars; 4024 VAR retvar; 4025 { 4026 char_u *p; 4027 char_u *name; 4028 int n = FALSE; 4029 int len = 0; 4030 4031 p = get_var_string(&argvars[0]); 4032 if (*p == '$') /* environment variable */ 4033 { 4034 /* first try "normal" environment variables (fast) */ 4035 if (mch_getenv(p + 1) != NULL) 4036 n = TRUE; 4037 else 4038 { 4039 /* try expanding things like $VIM and ${HOME} */ 4040 p = expand_env_save(p); 4041 if (p != NULL && *p != '$') 4042 n = TRUE; 4043 vim_free(p); 4044 } 4045 } 4046 else if (*p == '&' || *p == '+') /* option */ 4047 n = (get_option_var(&p, NULL, TRUE) == OK); 4048 else if (*p == '*') /* internal or user defined function */ 4049 { 4050 ++p; 4051 p = trans_function_name(&p, FALSE, TRUE); 4052 if (p != NULL) 4053 { 4054 if (ASCII_ISUPPER(*p) || p[0] == K_SPECIAL) 4055 n = (find_func(p) != NULL); 4056 else if (ASCII_ISLOWER(*p)) 4057 n = (find_internal_func(p) >= 0); 4058 vim_free(p); 4059 } 4060 } 4061 else if (*p == ':') 4062 { 4063 n = cmd_exists(p + 1); 4064 } 4065 else if (*p == '#') 4066 { 4067 #ifdef FEAT_AUTOCMD 4068 name = p + 1; 4069 p = vim_strchr(name, '#'); 4070 if (p != NULL) 4071 n = au_exists(name, p, p + 1); 4072 else 4073 n = au_exists(name, name + STRLEN(name), NULL); 4074 #endif 4075 } 4076 else /* internal variable */ 4077 { 4078 #ifdef FEAT_MAGIC_BRACES 4079 char_u *expr_start; 4080 char_u *expr_end; 4081 char_u *temp_string = NULL; 4082 char_u *s; 4083 #endif 4084 name = p; 4085 4086 #ifdef FEAT_MAGIC_BRACES 4087 /* Find the end of the name. */ 4088 s = find_name_end(name, &expr_start, &expr_end); 4089 if (expr_start != NULL) 4090 { 4091 temp_string = make_expanded_name(name, expr_start, expr_end, s); 4092 if (temp_string != NULL) 4093 { 4094 len = STRLEN(temp_string); 4095 name = temp_string; 4096 } 4097 } 4098 #endif 4099 if (len == 0) 4100 len = get_id_len(&p); 4101 if (len != 0) 4102 n = (get_var_var(name, len, NULL) == OK); 4103 4104 #ifdef FEAT_MAGIC_BRACES 4105 vim_free(temp_string); 4106 #endif 4107 } 4108 4109 retvar->var_val.var_number = n; 4110 } 4111 4112 /* 4113 * "expand()" function 4114 */ 4115 static void 4116 f_expand(argvars, retvar) 4117 VAR argvars; 4118 VAR retvar; 4119 { 4120 char_u *s; 4121 int len; 4122 char_u *errormsg; 4123 int flags = WILD_SILENT|WILD_USE_NL|WILD_LIST_NOTFOUND; 4124 expand_T xpc; 4125 4126 retvar->var_type = VAR_STRING; 4127 s = get_var_string(&argvars[0]); 4128 if (*s == '%' || *s == '#' || *s == '<') 4129 { 4130 ++emsg_off; 4131 retvar->var_val.var_string = eval_vars(s, &len, NULL, &errormsg, s); 4132 --emsg_off; 4133 } 4134 else 4135 { 4136 /* When the optional second argument is non-zero, don't remove matches 4137 * for 'suffixes' and 'wildignore' */ 4138 if (argvars[1].var_type != VAR_UNKNOWN && get_var_number(&argvars[1])) 4139 flags |= WILD_KEEP_ALL; 4140 ExpandInit(&xpc); 4141 xpc.xp_context = EXPAND_FILES; 4142 retvar->var_val.var_string = ExpandOne(&xpc, s, NULL, flags, WILD_ALL); 4143 ExpandCleanup(&xpc); 4144 } 4145 } 4146 4147 /* 4148 * "filereadable()" function 4149 */ 4150 static void 4151 f_filereadable(argvars, retvar) 4152 VAR argvars; 4153 VAR retvar; 4154 { 4155 FILE *fd; 4156 char_u *p; 4157 int n; 4158 4159 p = get_var_string(&argvars[0]); 4160 if (*p && !mch_isdir(p) && (fd = mch_fopen((char *)p, "r")) != NULL) 4161 { 4162 n = TRUE; 4163 fclose(fd); 4164 } 4165 else 4166 n = FALSE; 4167 4168 retvar->var_val.var_number = n; 4169 } 4170 4171 /* 4172 * return 0 for not writable, 1 for writable file, 2 for a dir which we have 4173 * rights to write into. 4174 */ 4175 static void 4176 f_filewritable(argvars, retvar) 4177 VAR argvars; 4178 VAR retvar; 4179 { 4180 char_u *p; 4181 int retval = 0; 4182 #if defined(UNIX) || defined(VMS) 4183 int perm = 0; 4184 #endif 4185 4186 p = get_var_string(&argvars[0]); 4187 #if defined(UNIX) || defined(VMS) 4188 perm = mch_getperm(p); 4189 #endif 4190 #ifndef MACOS_CLASSIC /* TODO: get either mch_writable or mch_access */ 4191 if ( 4192 # ifdef WIN3264 4193 mch_writable(p) && 4194 # else 4195 # if defined(UNIX) || defined(VMS) 4196 (perm & 0222) && 4197 # endif 4198 # endif 4199 mch_access((char *)p, W_OK) == 0 4200 ) 4201 #endif 4202 { 4203 ++retval; 4204 if (mch_isdir(p)) 4205 ++retval; 4206 } 4207 retvar->var_val.var_number = retval; 4208 } 4209 4210 /* 4211 * "finddir({fname}[, {path}[, {count}]])" function 4212 */ 4213 static void 4214 f_finddir(argvars, retvar) 4215 VAR argvars; 4216 VAR retvar; 4217 { 4218 f_findfilendir(argvars, retvar, TRUE); 4219 } 4220 4221 /* 4222 * "findfile({fname}[, {path}[, {count}]])" function 4223 */ 4224 static void 4225 f_findfile(argvars, retvar) 4226 VAR argvars; 4227 VAR retvar; 4228 { 4229 f_findfilendir(argvars, retvar, FALSE); 4230 } 4231 4232 static void 4233 f_findfilendir(argvars, retvar, dir) 4234 VAR argvars; 4235 VAR retvar; 4236 int dir; 4237 { 4238 #ifdef FEAT_SEARCHPATH 4239 char_u *fname; 4240 char_u *fresult = NULL; 4241 char_u *path = *curbuf->b_p_path == NUL ? p_path : curbuf->b_p_path; 4242 char_u *p; 4243 char_u pathbuf[NUMBUFLEN]; 4244 int count = 1; 4245 int first = TRUE; 4246 4247 fname = get_var_string(&argvars[0]); 4248 4249 if (argvars[1].var_type != VAR_UNKNOWN) 4250 { 4251 p = get_var_string_buf(&argvars[1], pathbuf); 4252 if (*p != NUL) 4253 path = p; 4254 4255 if (argvars[2].var_type != VAR_UNKNOWN) 4256 count = get_var_number(&argvars[2]); 4257 } 4258 4259 do 4260 { 4261 vim_free(fresult); 4262 fresult = find_file_in_path_option(first ? fname : NULL, 4263 first ? (int)STRLEN(fname) : 0, 4264 0, first, path, dir, NULL); 4265 first = FALSE; 4266 } while (--count > 0 && fresult != NULL); 4267 4268 retvar->var_val.var_string = fresult; 4269 #else 4270 retvar->var_val.var_string = NULL; 4271 #endif 4272 retvar->var_type = VAR_STRING; 4273 } 4274 4275 /* 4276 * "fnamemodify({fname}, {mods})" function 4277 */ 4278 static void 4279 f_fnamemodify(argvars, retvar) 4280 VAR argvars; 4281 VAR retvar; 4282 { 4283 char_u *fname; 4284 char_u *mods; 4285 int usedlen = 0; 4286 int len; 4287 char_u *fbuf = NULL; 4288 char_u buf[NUMBUFLEN]; 4289 4290 fname = get_var_string(&argvars[0]); 4291 mods = get_var_string_buf(&argvars[1], buf); 4292 len = (int)STRLEN(fname); 4293 4294 (void)modify_fname(mods, &usedlen, &fname, &fbuf, &len); 4295 4296 retvar->var_type = VAR_STRING; 4297 if (fname == NULL) 4298 retvar->var_val.var_string = NULL; 4299 else 4300 retvar->var_val.var_string = vim_strnsave(fname, len); 4301 vim_free(fbuf); 4302 } 4303 4304 /* 4305 * "foldclosed()" function 4306 */ 4307 static void 4308 f_foldclosed(argvars, retvar) 4309 VAR argvars; 4310 VAR retvar; 4311 { 4312 foldclosed_both(argvars, retvar, FALSE); 4313 } 4314 4315 /* 4316 * "foldclosedend()" function 4317 */ 4318 static void 4319 f_foldclosedend(argvars, retvar) 4320 VAR argvars; 4321 VAR retvar; 4322 { 4323 foldclosed_both(argvars, retvar, TRUE); 4324 } 4325 4326 /* 4327 * "foldclosed()" function 4328 */ 4329 static void 4330 foldclosed_both(argvars, retvar, end) 4331 VAR argvars; 4332 VAR retvar; 4333 int end; 4334 { 4335 #ifdef FEAT_FOLDING 4336 linenr_T lnum; 4337 linenr_T first, last; 4338 4339 lnum = get_var_lnum(argvars); 4340 if (lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count) 4341 { 4342 if (hasFoldingWin(curwin, lnum, &first, &last, FALSE, NULL)) 4343 { 4344 if (end) 4345 retvar->var_val.var_number = (varnumber_T)last; 4346 else 4347 retvar->var_val.var_number = (varnumber_T)first; 4348 return; 4349 } 4350 } 4351 #endif 4352 retvar->var_val.var_number = -1; 4353 } 4354 4355 /* 4356 * "foldlevel()" function 4357 */ 4358 static void 4359 f_foldlevel(argvars, retvar) 4360 VAR argvars; 4361 VAR retvar; 4362 { 4363 #ifdef FEAT_FOLDING 4364 linenr_T lnum; 4365 4366 lnum = get_var_lnum(argvars); 4367 if (lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count) 4368 retvar->var_val.var_number = foldLevel(lnum); 4369 else 4370 #endif 4371 retvar->var_val.var_number = 0; 4372 } 4373 4374 /* 4375 * "foldtext()" function 4376 */ 4377 /*ARGSUSED*/ 4378 static void 4379 f_foldtext(argvars, retvar) 4380 VAR argvars; 4381 VAR retvar; 4382 { 4383 #ifdef FEAT_FOLDING 4384 linenr_T lnum; 4385 char_u *s; 4386 char_u *r; 4387 int len; 4388 char *txt; 4389 #endif 4390 4391 retvar->var_type = VAR_STRING; 4392 retvar->var_val.var_string = NULL; 4393 #ifdef FEAT_FOLDING 4394 if ((linenr_T)vimvars[VV_FOLDSTART].val > 0 4395 && (linenr_T)vimvars[VV_FOLDEND].val <= curbuf->b_ml.ml_line_count 4396 && vimvars[VV_FOLDDASHES].val != NULL) 4397 { 4398 /* Find first non-empty line in the fold. */ 4399 lnum = (linenr_T)vimvars[VV_FOLDSTART].val; 4400 while (lnum < (linenr_T)vimvars[VV_FOLDEND].val) 4401 { 4402 if (!linewhite(lnum)) 4403 break; 4404 ++lnum; 4405 } 4406 4407 /* Find interesting text in this line. */ 4408 s = skipwhite(ml_get(lnum)); 4409 /* skip C comment-start */ 4410 if (s[0] == '/' && (s[1] == '*' || s[1] == '/')) 4411 s = skipwhite(s + 2); 4412 txt = _("+-%s%3ld lines: "); 4413 r = alloc((unsigned)(STRLEN(txt) 4414 + STRLEN(vimvars[VV_FOLDDASHES].val) /* for %s */ 4415 + 20 /* for %3ld */ 4416 + STRLEN(s))); /* concatenated */ 4417 if (r != NULL) 4418 { 4419 sprintf((char *)r, txt, vimvars[VV_FOLDDASHES].val, 4420 (long)((linenr_T)vimvars[VV_FOLDEND].val 4421 - (linenr_T)vimvars[VV_FOLDSTART].val + 1)); 4422 len = (int)STRLEN(r); 4423 STRCAT(r, s); 4424 /* remove 'foldmarker' and 'commentstring' */ 4425 foldtext_cleanup(r + len); 4426 retvar->var_val.var_string = r; 4427 } 4428 } 4429 #endif 4430 } 4431 4432 /* 4433 * "foldtextresult(lnum)" function 4434 */ 4435 /*ARGSUSED*/ 4436 static void 4437 f_foldtextresult(argvars, retvar) 4438 VAR argvars; 4439 VAR retvar; 4440 { 4441 #ifdef FEAT_FOLDING 4442 linenr_T lnum; 4443 char_u *text; 4444 char_u buf[51]; 4445 foldinfo_T foldinfo; 4446 int fold_count; 4447 #endif 4448 4449 retvar->var_type = VAR_STRING; 4450 retvar->var_val.var_string = NULL; 4451 #ifdef FEAT_FOLDING 4452 lnum = get_var_lnum(argvars); 4453 fold_count = foldedCount(curwin, lnum, &foldinfo); 4454 if (fold_count > 0) 4455 { 4456 text = get_foldtext(curwin, lnum, lnum + fold_count - 1, 4457 &foldinfo, buf); 4458 if (text == buf) 4459 text = vim_strsave(text); 4460 retvar->var_val.var_string = text; 4461 } 4462 #endif 4463 } 4464 4465 /* 4466 * "foreground()" function 4467 */ 4468 /*ARGSUSED*/ 4469 static void 4470 f_foreground(argvars, retvar) 4471 VAR argvars; 4472 VAR retvar; 4473 { 4474 retvar->var_val.var_number = 0; 4475 #ifdef FEAT_GUI 4476 if (gui.in_use) 4477 gui_mch_set_foreground(); 4478 #else 4479 # ifdef WIN32 4480 win32_set_foreground(); 4481 # endif 4482 #endif 4483 } 4484 4485 /* 4486 * "getchar()" function 4487 */ 4488 static void 4489 f_getchar(argvars, retvar) 4490 VAR argvars; 4491 VAR retvar; 4492 { 4493 varnumber_T n; 4494 4495 ++no_mapping; 4496 ++allow_keys; 4497 if (argvars[0].var_type == VAR_UNKNOWN) 4498 /* getchar(): blocking wait. */ 4499 n = safe_vgetc(); 4500 else if (get_var_number(&argvars[0]) == 1) 4501 /* getchar(1): only check if char avail */ 4502 n = vpeekc(); 4503 else if (vpeekc() == NUL) 4504 /* getchar(0) and no char avail: return zero */ 4505 n = 0; 4506 else 4507 /* getchar(0) and char avail: return char */ 4508 n = safe_vgetc(); 4509 --no_mapping; 4510 --allow_keys; 4511 4512 retvar->var_val.var_number = n; 4513 if (IS_SPECIAL(n) || mod_mask != 0) 4514 { 4515 char_u temp[10]; /* modifier: 3, mbyte-char: 6, NUL: 1 */ 4516 int i = 0; 4517 4518 /* Turn a special key into three bytes, plus modifier. */ 4519 if (mod_mask != 0) 4520 { 4521 temp[i++] = K_SPECIAL; 4522 temp[i++] = KS_MODIFIER; 4523 temp[i++] = mod_mask; 4524 } 4525 if (IS_SPECIAL(n)) 4526 { 4527 temp[i++] = K_SPECIAL; 4528 temp[i++] = K_SECOND(n); 4529 temp[i++] = K_THIRD(n); 4530 } 4531 #ifdef FEAT_MBYTE 4532 else if (has_mbyte) 4533 i += (*mb_char2bytes)(n, temp + i); 4534 #endif 4535 else 4536 temp[i++] = n; 4537 temp[i++] = NUL; 4538 retvar->var_type = VAR_STRING; 4539 retvar->var_val.var_string = vim_strsave(temp); 4540 } 4541 } 4542 4543 /* 4544 * "getcharmod()" function 4545 */ 4546 /*ARGSUSED*/ 4547 static void 4548 f_getcharmod(argvars, retvar) 4549 VAR argvars; 4550 VAR retvar; 4551 { 4552 retvar->var_val.var_number = mod_mask; 4553 } 4554 4555 /* 4556 * "getcmdline()" function 4557 */ 4558 /*ARGSUSED*/ 4559 static void 4560 f_getcmdline(argvars, retvar) 4561 VAR argvars; 4562 VAR retvar; 4563 { 4564 retvar->var_type = VAR_STRING; 4565 retvar->var_val.var_string = get_cmdline_str(); 4566 } 4567 4568 /* 4569 * "getcmdpos()" function 4570 */ 4571 /*ARGSUSED*/ 4572 static void 4573 f_getcmdpos(argvars, retvar) 4574 VAR argvars; 4575 VAR retvar; 4576 { 4577 retvar->var_val.var_number = get_cmdline_pos() + 1; 4578 } 4579 4580 /* 4581 * "getbufvar()" function 4582 */ 4583 static void 4584 f_getbufvar(argvars, retvar) 4585 VAR argvars; 4586 VAR retvar; 4587 { 4588 buf_T *buf; 4589 buf_T *save_curbuf; 4590 char_u *varname; 4591 VAR v; 4592 4593 ++emsg_off; 4594 buf = get_buf_var(&argvars[0]); 4595 varname = get_var_string(&argvars[1]); 4596 4597 retvar->var_type = VAR_STRING; 4598 retvar->var_val.var_string = NULL; 4599 4600 if (buf != NULL && varname != NULL) 4601 { 4602 if (*varname == '&') /* buffer-local-option */ 4603 { 4604 /* set curbuf to be our buf, temporarily */ 4605 save_curbuf = curbuf; 4606 curbuf = buf; 4607 4608 get_option_var(&varname, retvar, TRUE); 4609 4610 /* restore previous notion of curbuf */ 4611 curbuf = save_curbuf; 4612 } 4613 else 4614 { 4615 /* look up the variable */ 4616 v = find_var_in_ga(&buf->b_vars, varname); 4617 if (v != NULL) 4618 copy_var(v, retvar); 4619 } 4620 } 4621 4622 --emsg_off; 4623 } 4624 4625 /* 4626 * "getcwd()" function 4627 */ 4628 /*ARGSUSED*/ 4629 static void 4630 f_getcwd(argvars, retvar) 4631 VAR argvars; 4632 VAR retvar; 4633 { 4634 char_u cwd[MAXPATHL]; 4635 4636 retvar->var_type = VAR_STRING; 4637 if (mch_dirname(cwd, MAXPATHL) == FAIL) 4638 retvar->var_val.var_string = NULL; 4639 else 4640 { 4641 retvar->var_val.var_string = vim_strsave(cwd); 4642 #ifdef BACKSLASH_IN_FILENAME 4643 slash_adjust(retvar->var_val.var_string); 4644 #endif 4645 } 4646 } 4647 4648 /* 4649 * "getfperm({fname})" function 4650 */ 4651 static void 4652 f_getfperm(argvars, retvar) 4653 VAR argvars; 4654 VAR retvar; 4655 { 4656 char_u *fname; 4657 struct stat st; 4658 char_u *perm = NULL; 4659 char_u flags[] = "rwx"; 4660 int i; 4661 4662 fname = get_var_string(&argvars[0]); 4663 4664 retvar->var_type = VAR_STRING; 4665 if (mch_stat((char *)fname, &st) >= 0) 4666 { 4667 perm = vim_strsave((char_u *)"---------"); 4668 if (perm != NULL) 4669 { 4670 for (i = 0; i < 9; i++) 4671 { 4672 if (st.st_mode & (1 << (8 - i))) 4673 perm[i] = flags[i % 3]; 4674 } 4675 } 4676 } 4677 retvar->var_val.var_string = perm; 4678 } 4679 4680 /* 4681 * "getfsize({fname})" function 4682 */ 4683 static void 4684 f_getfsize(argvars, retvar) 4685 VAR argvars; 4686 VAR retvar; 4687 { 4688 char_u *fname; 4689 struct stat st; 4690 4691 fname = get_var_string(&argvars[0]); 4692 4693 retvar->var_type = VAR_NUMBER; 4694 4695 if (mch_stat((char *)fname, &st) >= 0) 4696 { 4697 if (mch_isdir(fname)) 4698 retvar->var_val.var_number = 0; 4699 else 4700 retvar->var_val.var_number = (varnumber_T)st.st_size; 4701 } 4702 else 4703 retvar->var_val.var_number = -1; 4704 } 4705 4706 /* 4707 * "getftime({fname})" function 4708 */ 4709 static void 4710 f_getftime(argvars, retvar) 4711 VAR argvars; 4712 VAR retvar; 4713 { 4714 char_u *fname; 4715 struct stat st; 4716 4717 fname = get_var_string(&argvars[0]); 4718 4719 if (mch_stat((char *)fname, &st) >= 0) 4720 retvar->var_val.var_number = (varnumber_T)st.st_mtime; 4721 else 4722 retvar->var_val.var_number = -1; 4723 } 4724 4725 /* 4726 * "getftype({fname})" function 4727 */ 4728 static void 4729 f_getftype(argvars, retvar) 4730 VAR argvars; 4731 VAR retvar; 4732 { 4733 char_u *fname; 4734 struct stat st; 4735 char_u *type = NULL; 4736 char *t; 4737 4738 fname = get_var_string(&argvars[0]); 4739 4740 retvar->var_type = VAR_STRING; 4741 if (mch_lstat((char *)fname, &st) >= 0) 4742 { 4743 #ifdef S_ISREG 4744 if (S_ISREG(st.st_mode)) 4745 t = "file"; 4746 else if (S_ISDIR(st.st_mode)) 4747 t = "dir"; 4748 # ifdef S_ISLNK 4749 else if (S_ISLNK(st.st_mode)) 4750 t = "link"; 4751 # endif 4752 # ifdef S_ISBLK 4753 else if (S_ISBLK(st.st_mode)) 4754 t = "bdev"; 4755 # endif 4756 # ifdef S_ISCHR 4757 else if (S_ISCHR(st.st_mode)) 4758 t = "cdev"; 4759 # endif 4760 # ifdef S_ISFIFO 4761 else if (S_ISFIFO(st.st_mode)) 4762 t = "fifo"; 4763 # endif 4764 # ifdef S_ISSOCK 4765 else if (S_ISSOCK(st.st_mode)) 4766 t = "fifo"; 4767 # endif 4768 else 4769 t = "other"; 4770 #else 4771 # ifdef S_IFMT 4772 switch (st.st_mode & S_IFMT) 4773 { 4774 case S_IFREG: t = "file"; break; 4775 case S_IFDIR: t = "dir"; break; 4776 # ifdef S_IFLNK 4777 case S_IFLNK: t = "link"; break; 4778 # endif 4779 # ifdef S_IFBLK 4780 case S_IFBLK: t = "bdev"; break; 4781 # endif 4782 # ifdef S_IFCHR 4783 case S_IFCHR: t = "cdev"; break; 4784 # endif 4785 # ifdef S_IFIFO 4786 case S_IFIFO: t = "fifo"; break; 4787 # endif 4788 # ifdef S_IFSOCK 4789 case S_IFSOCK: t = "socket"; break; 4790 # endif 4791 default: t = "other"; 4792 } 4793 # else 4794 if (mch_isdir(fname)) 4795 t = "dir"; 4796 else 4797 t = "file"; 4798 # endif 4799 #endif 4800 type = vim_strsave((char_u *)t); 4801 } 4802 retvar->var_val.var_string = type; 4803 } 4804 4805 /* 4806 * "getreg()" function 4807 */ 4808 static void 4809 f_getreg(argvars, retvar) 4810 VAR argvars; 4811 VAR retvar; 4812 { 4813 char_u *strregname; 4814 int regname; 4815 4816 if (argvars[0].var_type != VAR_UNKNOWN) 4817 strregname = get_var_string(&argvars[0]); 4818 else 4819 strregname = vimvars[VV_REG].val; 4820 regname = (strregname == NULL ? '"' : *strregname); 4821 if (regname == 0) 4822 regname = '"'; 4823 4824 retvar->var_type = VAR_STRING; 4825 retvar->var_val.var_string = get_reg_contents(regname, TRUE); 4826 } 4827 4828 /* 4829 * "getregtype()" function 4830 */ 4831 static void 4832 f_getregtype(argvars, retvar) 4833 VAR argvars; 4834 VAR retvar; 4835 { 4836 char_u *strregname; 4837 int regname; 4838 char_u buf[NUMBUFLEN + 2]; 4839 long reglen = 0; 4840 4841 if (argvars[0].var_type != VAR_UNKNOWN) 4842 strregname = get_var_string(&argvars[0]); 4843 else 4844 /* Default to v:register */ 4845 strregname = vimvars[VV_REG].val; 4846 4847 regname = (strregname == NULL ? '"' : *strregname); 4848 if (regname == 0) 4849 regname = '"'; 4850 4851 buf[0] = NUL; 4852 buf[1] = NUL; 4853 switch (get_reg_type(regname, ®len)) 4854 { 4855 case MLINE: buf[0] = 'V'; break; 4856 case MCHAR: buf[0] = 'v'; break; 4857 #ifdef FEAT_VISUAL 4858 case MBLOCK: 4859 buf[0] = Ctrl_V; 4860 sprintf((char *)buf + 1, "%ld", reglen + 1); 4861 break; 4862 #endif 4863 } 4864 retvar->var_type = VAR_STRING; 4865 retvar->var_val.var_string = vim_strsave(buf); 4866 } 4867 4868 /* 4869 * "getline(lnum)" function 4870 */ 4871 static void 4872 f_getline(argvars, retvar) 4873 VAR argvars; 4874 VAR retvar; 4875 { 4876 linenr_T lnum; 4877 char_u *p; 4878 4879 lnum = get_var_lnum(argvars); 4880 4881 if (lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count) 4882 p = ml_get(lnum); 4883 else 4884 p = (char_u *)""; 4885 4886 retvar->var_type = VAR_STRING; 4887 retvar->var_val.var_string = vim_strsave(p); 4888 } 4889 4890 /* 4891 * "getwinposx()" function 4892 */ 4893 /*ARGSUSED*/ 4894 static void 4895 f_getwinposx(argvars, retvar) 4896 VAR argvars; 4897 VAR retvar; 4898 { 4899 retvar->var_val.var_number = -1; 4900 #ifdef FEAT_GUI 4901 if (gui.in_use) 4902 { 4903 int x, y; 4904 4905 if (gui_mch_get_winpos(&x, &y) == OK) 4906 retvar->var_val.var_number = x; 4907 } 4908 #endif 4909 } 4910 4911 /* 4912 * "getwinposy()" function 4913 */ 4914 /*ARGSUSED*/ 4915 static void 4916 f_getwinposy(argvars, retvar) 4917 VAR argvars; 4918 VAR retvar; 4919 { 4920 retvar->var_val.var_number = -1; 4921 #ifdef FEAT_GUI 4922 if (gui.in_use) 4923 { 4924 int x, y; 4925 4926 if (gui_mch_get_winpos(&x, &y) == OK) 4927 retvar->var_val.var_number = y; 4928 } 4929 #endif 4930 } 4931 4932 /* 4933 * "getwinvar()" function 4934 */ 4935 static void 4936 f_getwinvar(argvars, retvar) 4937 VAR argvars; 4938 VAR retvar; 4939 { 4940 win_T *win, *oldcurwin; 4941 char_u *varname; 4942 VAR v; 4943 4944 ++emsg_off; 4945 win = find_win_by_nr(&argvars[0]); 4946 varname = get_var_string(&argvars[1]); 4947 4948 retvar->var_type = VAR_STRING; 4949 retvar->var_val.var_string = NULL; 4950 4951 if (win != NULL && varname != NULL) 4952 { 4953 if (*varname == '&') /* window-local-option */ 4954 { 4955 /* set curwin to be our win, temporarily */ 4956 oldcurwin = curwin; 4957 curwin = win; 4958 4959 get_option_var(&varname, retvar , 1); 4960 4961 /* restore previous notion of curwin */ 4962 curwin = oldcurwin; 4963 } 4964 else 4965 { 4966 /* look up the variable */ 4967 v = find_var_in_ga(&win->w_vars, varname); 4968 if (v != NULL) 4969 copy_var(v, retvar); 4970 } 4971 } 4972 4973 --emsg_off; 4974 } 4975 4976 /* 4977 * "glob()" function 4978 */ 4979 static void 4980 f_glob(argvars, retvar) 4981 VAR argvars; 4982 VAR retvar; 4983 { 4984 expand_T xpc; 4985 4986 ExpandInit(&xpc); 4987 xpc.xp_context = EXPAND_FILES; 4988 retvar->var_type = VAR_STRING; 4989 retvar->var_val.var_string = ExpandOne(&xpc, get_var_string(&argvars[0]), 4990 NULL, WILD_USE_NL|WILD_SILENT, WILD_ALL); 4991 ExpandCleanup(&xpc); 4992 } 4993 4994 /* 4995 * "globpath()" function 4996 */ 4997 static void 4998 f_globpath(argvars, retvar) 4999 VAR argvars; 5000 VAR retvar; 5001 { 5002 char_u buf1[NUMBUFLEN]; 5003 5004 retvar->var_type = VAR_STRING; 5005 retvar->var_val.var_string = globpath(get_var_string(&argvars[0]), 5006 get_var_string_buf(&argvars[1], buf1)); 5007 } 5008 5009 /* 5010 * "has()" function 5011 */ 5012 static void 5013 f_has(argvars, retvar) 5014 VAR argvars; 5015 VAR retvar; 5016 { 5017 int i; 5018 char_u *name; 5019 int n = FALSE; 5020 static char *(has_list[]) = 5021 { 5022 #ifdef AMIGA 5023 "amiga", 5024 # ifdef FEAT_ARP 5025 "arp", 5026 # endif 5027 #endif 5028 #ifdef __BEOS__ 5029 "beos", 5030 #endif 5031 #ifdef MSDOS 5032 # ifdef DJGPP 5033 "dos32", 5034 # else 5035 "dos16", 5036 # endif 5037 #endif 5038 #ifdef MACOS /* TODO: Should we add MACOS_CLASSIC, MACOS_X? (Dany) */ 5039 "mac", 5040 #endif 5041 #if defined(MACOS_X_UNIX) 5042 "macunix", 5043 #endif 5044 #ifdef OS2 5045 "os2", 5046 #endif 5047 #ifdef __QNX__ 5048 "qnx", 5049 #endif 5050 #ifdef RISCOS 5051 "riscos", 5052 #endif 5053 #ifdef UNIX 5054 "unix", 5055 #endif 5056 #ifdef VMS 5057 "vms", 5058 #endif 5059 #ifdef WIN16 5060 "win16", 5061 #endif 5062 #ifdef WIN32 5063 "win32", 5064 #endif 5065 #if defined(UNIX) && (defined(__CYGWIN32__) || defined(__CYGWIN__)) 5066 "win32unix", 5067 #endif 5068 #ifdef WIN64 5069 "win64", 5070 #endif 5071 #ifdef EBCDIC 5072 "ebcdic", 5073 #endif 5074 #ifndef CASE_INSENSITIVE_FILENAME 5075 "fname_case", 5076 #endif 5077 #ifdef FEAT_ARABIC 5078 "arabic", 5079 #endif 5080 #ifdef FEAT_AUTOCMD 5081 "autocmd", 5082 #endif 5083 #ifdef FEAT_BEVAL 5084 "balloon_eval", 5085 #endif 5086 #if defined(SOME_BUILTIN_TCAPS) || defined(ALL_BUILTIN_TCAPS) 5087 "builtin_terms", 5088 # ifdef ALL_BUILTIN_TCAPS 5089 "all_builtin_terms", 5090 # endif 5091 #endif 5092 #ifdef FEAT_BYTEOFF 5093 "byte_offset", 5094 #endif 5095 #ifdef FEAT_CINDENT 5096 "cindent", 5097 #endif 5098 #ifdef FEAT_CLIENTSERVER 5099 "clientserver", 5100 #endif 5101 #ifdef FEAT_CLIPBOARD 5102 "clipboard", 5103 #endif 5104 #ifdef FEAT_CMDL_COMPL 5105 "cmdline_compl", 5106 #endif 5107 #ifdef FEAT_CMDHIST 5108 "cmdline_hist", 5109 #endif 5110 #ifdef FEAT_COMMENTS 5111 "comments", 5112 #endif 5113 #ifdef FEAT_CRYPT 5114 "cryptv", 5115 #endif 5116 #ifdef FEAT_CSCOPE 5117 "cscope", 5118 #endif 5119 #ifdef DEBUG 5120 "debug", 5121 #endif 5122 #ifdef FEAT_CON_DIALOG 5123 "dialog_con", 5124 #endif 5125 #ifdef FEAT_GUI_DIALOG 5126 "dialog_gui", 5127 #endif 5128 #ifdef FEAT_DIFF 5129 "diff", 5130 #endif 5131 #ifdef FEAT_DIGRAPHS 5132 "digraphs", 5133 #endif 5134 #ifdef FEAT_DND 5135 "dnd", 5136 #endif 5137 #ifdef FEAT_EMACS_TAGS 5138 "emacs_tags", 5139 #endif 5140 "eval", /* always present, of course! */ 5141 #ifdef FEAT_EX_EXTRA 5142 "ex_extra", 5143 #endif 5144 #ifdef FEAT_SEARCH_EXTRA 5145 "extra_search", 5146 #endif 5147 #ifdef FEAT_FKMAP 5148 "farsi", 5149 #endif 5150 #ifdef FEAT_SEARCHPATH 5151 "file_in_path", 5152 #endif 5153 #ifdef FEAT_FIND_ID 5154 "find_in_path", 5155 #endif 5156 #ifdef FEAT_FOLDING 5157 "folding", 5158 #endif 5159 #ifdef FEAT_FOOTER 5160 "footer", 5161 #endif 5162 #if !defined(USE_SYSTEM) && defined(UNIX) 5163 "fork", 5164 #endif 5165 #ifdef FEAT_GETTEXT 5166 "gettext", 5167 #endif 5168 #ifdef FEAT_GUI 5169 "gui", 5170 #endif 5171 #ifdef FEAT_GUI_ATHENA 5172 # ifdef FEAT_GUI_NEXTAW 5173 "gui_neXtaw", 5174 # else 5175 "gui_athena", 5176 # endif 5177 #endif 5178 #ifdef FEAT_GUI_BEOS 5179 "gui_beos", 5180 #endif 5181 #ifdef FEAT_GUI_KDE 5182 "gui_kde", 5183 #endif 5184 #ifdef FEAT_GUI_GTK 5185 "gui_gtk", 5186 # ifdef HAVE_GTK2 5187 "gui_gtk2", 5188 # endif 5189 #endif 5190 #ifdef FEAT_GUI_MAC 5191 "gui_mac", 5192 #endif 5193 #ifdef FEAT_GUI_MOTIF 5194 "gui_motif", 5195 #endif 5196 #ifdef FEAT_GUI_PHOTON 5197 "gui_photon", 5198 #endif 5199 #ifdef FEAT_GUI_W16 5200 "gui_win16", 5201 #endif 5202 #ifdef FEAT_GUI_W32 5203 "gui_win32", 5204 #endif 5205 #ifdef FEAT_HANGULIN 5206 "hangul_input", 5207 #endif 5208 #if defined(HAVE_ICONV_H) && defined(USE_ICONV) 5209 "iconv", 5210 #endif 5211 #ifdef FEAT_INS_EXPAND 5212 "insert_expand", 5213 #endif 5214 #ifdef FEAT_JUMPLIST 5215 "jumplist", 5216 #endif 5217 #ifdef FEAT_KEYMAP 5218 "keymap", 5219 #endif 5220 #ifdef FEAT_LANGMAP 5221 "langmap", 5222 #endif 5223 #ifdef FEAT_LIBCALL 5224 "libcall", 5225 #endif 5226 #ifdef FEAT_LINEBREAK 5227 "linebreak", 5228 #endif 5229 #ifdef FEAT_LISP 5230 "lispindent", 5231 #endif 5232 #ifdef FEAT_LISTCMDS 5233 "listcmds", 5234 #endif 5235 #ifdef FEAT_LOCALMAP 5236 "localmap", 5237 #endif 5238 #ifdef FEAT_MENU 5239 "menu", 5240 #endif 5241 #ifdef FEAT_SESSION 5242 "mksession", 5243 #endif 5244 #ifdef FEAT_MODIFY_FNAME 5245 "modify_fname", 5246 #endif 5247 #ifdef FEAT_MOUSE 5248 "mouse", 5249 #endif 5250 #ifdef FEAT_MOUSESHAPE 5251 "mouseshape", 5252 #endif 5253 #if defined(UNIX) || defined(VMS) 5254 # ifdef FEAT_MOUSE_DEC 5255 "mouse_dec", 5256 # endif 5257 # ifdef FEAT_MOUSE_GPM 5258 "mouse_gpm", 5259 # endif 5260 # ifdef FEAT_MOUSE_JSB 5261 "mouse_jsbterm", 5262 # endif 5263 # ifdef FEAT_MOUSE_NET 5264 "mouse_netterm", 5265 # endif 5266 # ifdef FEAT_MOUSE_PTERM 5267 "mouse_pterm", 5268 # endif 5269 # ifdef FEAT_MOUSE_XTERM 5270 "mouse_xterm", 5271 # endif 5272 #endif 5273 #ifdef FEAT_MBYTE 5274 "multi_byte", 5275 #endif 5276 #ifdef FEAT_MBYTE_IME 5277 "multi_byte_ime", 5278 #endif 5279 #ifdef FEAT_MULTI_LANG 5280 "multi_lang", 5281 #endif 5282 #ifdef FEAT_MZSCHEME 5283 "mzscheme", 5284 #endif 5285 #ifdef FEAT_OLE 5286 "ole", 5287 #endif 5288 #ifdef FEAT_OSFILETYPE 5289 "osfiletype", 5290 #endif 5291 #ifdef FEAT_PATH_EXTRA 5292 "path_extra", 5293 #endif 5294 #ifdef FEAT_PERL 5295 #ifndef DYNAMIC_PERL 5296 "perl", 5297 #endif 5298 #endif 5299 #ifdef FEAT_PYTHON 5300 #ifndef DYNAMIC_PYTHON 5301 "python", 5302 #endif 5303 #endif 5304 #ifdef FEAT_POSTSCRIPT 5305 "postscript", 5306 #endif 5307 #ifdef FEAT_PRINTER 5308 "printer", 5309 #endif 5310 #ifdef FEAT_QUICKFIX 5311 "quickfix", 5312 #endif 5313 #ifdef FEAT_RIGHTLEFT 5314 "rightleft", 5315 #endif 5316 #if defined(FEAT_RUBY) && !defined(DYNAMIC_RUBY) 5317 "ruby", 5318 #endif 5319 #ifdef FEAT_SCROLLBIND 5320 "scrollbind", 5321 #endif 5322 #ifdef FEAT_CMDL_INFO 5323 "showcmd", 5324 "cmdline_info", 5325 #endif 5326 #ifdef FEAT_SIGNS 5327 "signs", 5328 #endif 5329 #ifdef FEAT_SMARTINDENT 5330 "smartindent", 5331 #endif 5332 #ifdef FEAT_SNIFF 5333 "sniff", 5334 #endif 5335 #ifdef FEAT_STL_OPT 5336 "statusline", 5337 #endif 5338 #ifdef FEAT_SUN_WORKSHOP 5339 "sun_workshop", 5340 #endif 5341 #ifdef FEAT_NETBEANS_INTG 5342 "netbeans_intg", 5343 #endif 5344 #ifdef FEAT_SYN_HL 5345 "syntax", 5346 #endif 5347 #if defined(USE_SYSTEM) || !defined(UNIX) 5348 "system", 5349 #endif 5350 #ifdef FEAT_TAG_BINS 5351 "tag_binary", 5352 #endif 5353 #ifdef FEAT_TAG_OLDSTATIC 5354 "tag_old_static", 5355 #endif 5356 #ifdef FEAT_TAG_ANYWHITE 5357 "tag_any_white", 5358 #endif 5359 #ifdef FEAT_TCL 5360 # ifndef DYNAMIC_TCL 5361 "tcl", 5362 # endif 5363 #endif 5364 #ifdef TERMINFO 5365 "terminfo", 5366 #endif 5367 #ifdef FEAT_TERMRESPONSE 5368 "termresponse", 5369 #endif 5370 #ifdef FEAT_TEXTOBJ 5371 "textobjects", 5372 #endif 5373 #ifdef HAVE_TGETENT 5374 "tgetent", 5375 #endif 5376 #ifdef FEAT_TITLE 5377 "title", 5378 #endif 5379 #ifdef FEAT_TOOLBAR 5380 "toolbar", 5381 #endif 5382 #ifdef FEAT_USR_CMDS 5383 "user-commands", /* was accidentally included in 5.4 */ 5384 "user_commands", 5385 #endif 5386 #ifdef FEAT_VIMINFO 5387 "viminfo", 5388 #endif 5389 #ifdef FEAT_VERTSPLIT 5390 "vertsplit", 5391 #endif 5392 #ifdef FEAT_VIRTUALEDIT 5393 "virtualedit", 5394 #endif 5395 #ifdef FEAT_VISUAL 5396 "visual", 5397 #endif 5398 #ifdef FEAT_VISUALEXTRA 5399 "visualextra", 5400 #endif 5401 #ifdef FEAT_VREPLACE 5402 "vreplace", 5403 #endif 5404 #ifdef FEAT_WILDIGN 5405 "wildignore", 5406 #endif 5407 #ifdef FEAT_WILDMENU 5408 "wildmenu", 5409 #endif 5410 #ifdef FEAT_WINDOWS 5411 "windows", 5412 #endif 5413 #ifdef FEAT_WAK 5414 "winaltkeys", 5415 #endif 5416 #ifdef FEAT_WRITEBACKUP 5417 "writebackup", 5418 #endif 5419 #ifdef FEAT_XIM 5420 "xim", 5421 #endif 5422 #ifdef FEAT_XFONTSET 5423 "xfontset", 5424 #endif 5425 #ifdef USE_XSMP 5426 "xsmp", 5427 #endif 5428 #ifdef USE_XSMP_INTERACT 5429 "xsmp_interact", 5430 #endif 5431 #ifdef FEAT_XCLIPBOARD 5432 "xterm_clipboard", 5433 #endif 5434 #ifdef FEAT_XTERM_SAVE 5435 "xterm_save", 5436 #endif 5437 #if defined(UNIX) && defined(FEAT_X11) 5438 "X11", 5439 #endif 5440 NULL 5441 }; 5442 5443 name = get_var_string(&argvars[0]); 5444 for (i = 0; has_list[i] != NULL; ++i) 5445 if (STRICMP(name, has_list[i]) == 0) 5446 { 5447 n = TRUE; 5448 break; 5449 } 5450 5451 if (n == FALSE) 5452 { 5453 if (STRNICMP(name, "patch", 5) == 0) 5454 n = has_patch(atoi((char *)name + 5)); 5455 else if (STRICMP(name, "vim_starting") == 0) 5456 n = (starting != 0); 5457 #ifdef DYNAMIC_TCL 5458 else if (STRICMP(name, "tcl") == 0) 5459 n = tcl_enabled(FALSE); 5460 #endif 5461 #if defined(USE_ICONV) && defined(DYNAMIC_ICONV) 5462 else if (STRICMP(name, "iconv") == 0) 5463 n = iconv_enabled(FALSE); 5464 #endif 5465 #ifdef DYNAMIC_RUBY 5466 else if (STRICMP(name, "ruby") == 0) 5467 n = ruby_enabled(FALSE); 5468 #endif 5469 #ifdef DYNAMIC_PYTHON 5470 else if (STRICMP(name, "python") == 0) 5471 n = python_enabled(FALSE); 5472 #endif 5473 #ifdef DYNAMIC_PERL 5474 else if (STRICMP(name, "perl") == 0) 5475 n = perl_enabled(FALSE); 5476 #endif 5477 #ifdef FEAT_GUI 5478 else if (STRICMP(name, "gui_running") == 0) 5479 n = (gui.in_use || gui.starting); 5480 # ifdef FEAT_GUI_W32 5481 else if (STRICMP(name, "gui_win32s") == 0) 5482 n = gui_is_win32s(); 5483 # endif 5484 # ifdef FEAT_BROWSE 5485 else if (STRICMP(name, "browse") == 0) 5486 n = gui.in_use; /* gui_mch_browse() works when GUI is running */ 5487 # endif 5488 #endif 5489 #ifdef FEAT_SYN_HL 5490 else if (STRICMP(name, "syntax_items") == 0) 5491 n = syntax_present(curbuf); 5492 #endif 5493 #if defined(WIN3264) 5494 else if (STRICMP(name, "win95") == 0) 5495 n = mch_windows95(); 5496 #endif 5497 } 5498 5499 retvar->var_val.var_number = n; 5500 } 5501 5502 /* 5503 * "hasmapto()" function 5504 */ 5505 static void 5506 f_hasmapto(argvars, retvar) 5507 VAR argvars; 5508 VAR retvar; 5509 { 5510 char_u *name; 5511 char_u *mode; 5512 char_u buf[NUMBUFLEN]; 5513 5514 name = get_var_string(&argvars[0]); 5515 if (argvars[1].var_type == VAR_UNKNOWN) 5516 mode = (char_u *)"nvo"; 5517 else 5518 mode = get_var_string_buf(&argvars[1], buf); 5519 5520 if (map_to_exists(name, mode)) 5521 retvar->var_val.var_number = TRUE; 5522 else 5523 retvar->var_val.var_number = FALSE; 5524 } 5525 5526 /* 5527 * "histadd()" function 5528 */ 5529 /*ARGSUSED*/ 5530 static void 5531 f_histadd(argvars, retvar) 5532 VAR argvars; 5533 VAR retvar; 5534 { 5535 #ifdef FEAT_CMDHIST 5536 int histype; 5537 char_u *str; 5538 char_u buf[NUMBUFLEN]; 5539 #endif 5540 5541 retvar->var_val.var_number = FALSE; 5542 if (check_restricted() || check_secure()) 5543 return; 5544 #ifdef FEAT_CMDHIST 5545 histype = get_histtype(get_var_string(&argvars[0])); 5546 if (histype >= 0) 5547 { 5548 str = get_var_string_buf(&argvars[1], buf); 5549 if (*str != NUL) 5550 { 5551 add_to_history(histype, str, FALSE, NUL); 5552 retvar->var_val.var_number = TRUE; 5553 return; 5554 } 5555 } 5556 #endif 5557 } 5558 5559 /* 5560 * "histdel()" function 5561 */ 5562 /*ARGSUSED*/ 5563 static void 5564 f_histdel(argvars, retvar) 5565 VAR argvars; 5566 VAR retvar; 5567 { 5568 #ifdef FEAT_CMDHIST 5569 int n; 5570 char_u buf[NUMBUFLEN]; 5571 5572 if (argvars[1].var_type == VAR_UNKNOWN) 5573 /* only one argument: clear entire history */ 5574 n = clr_history(get_histtype(get_var_string(&argvars[0]))); 5575 else if (argvars[1].var_type == VAR_NUMBER) 5576 /* index given: remove that entry */ 5577 n = del_history_idx(get_histtype(get_var_string(&argvars[0])), 5578 (int)get_var_number(&argvars[1])); 5579 else 5580 /* string given: remove all matching entries */ 5581 n = del_history_entry(get_histtype(get_var_string(&argvars[0])), 5582 get_var_string_buf(&argvars[1], buf)); 5583 retvar->var_val.var_number = n; 5584 #else 5585 retvar->var_val.var_number = 0; 5586 #endif 5587 } 5588 5589 /* 5590 * "histget()" function 5591 */ 5592 /*ARGSUSED*/ 5593 static void 5594 f_histget(argvars, retvar) 5595 VAR argvars; 5596 VAR retvar; 5597 { 5598 #ifdef FEAT_CMDHIST 5599 int type; 5600 int idx; 5601 5602 type = get_histtype(get_var_string(&argvars[0])); 5603 if (argvars[1].var_type == VAR_UNKNOWN) 5604 idx = get_history_idx(type); 5605 else 5606 idx = (int)get_var_number(&argvars[1]); 5607 retvar->var_val.var_string = vim_strsave(get_history_entry(type, idx)); 5608 #else 5609 retvar->var_val.var_string = NULL; 5610 #endif 5611 retvar->var_type = VAR_STRING; 5612 } 5613 5614 /* 5615 * "histnr()" function 5616 */ 5617 /*ARGSUSED*/ 5618 static void 5619 f_histnr(argvars, retvar) 5620 VAR argvars; 5621 VAR retvar; 5622 { 5623 int i; 5624 5625 #ifdef FEAT_CMDHIST 5626 i = get_histtype(get_var_string(&argvars[0])); 5627 if (i >= HIST_CMD && i < HIST_COUNT) 5628 i = get_history_idx(i); 5629 else 5630 #endif 5631 i = -1; 5632 retvar->var_val.var_number = i; 5633 } 5634 5635 /* 5636 * "highlight_exists()" function 5637 */ 5638 static void 5639 f_hlexists(argvars, retvar) 5640 VAR argvars; 5641 VAR retvar; 5642 { 5643 retvar->var_val.var_number = highlight_exists(get_var_string(&argvars[0])); 5644 } 5645 5646 /* 5647 * "highlightID(name)" function 5648 */ 5649 static void 5650 f_hlID(argvars, retvar) 5651 VAR argvars; 5652 VAR retvar; 5653 { 5654 retvar->var_val.var_number = syn_name2id(get_var_string(&argvars[0])); 5655 } 5656 5657 /* 5658 * "hostname()" function 5659 */ 5660 /*ARGSUSED*/ 5661 static void 5662 f_hostname(argvars, retvar) 5663 VAR argvars; 5664 VAR retvar; 5665 { 5666 char_u hostname[256]; 5667 5668 mch_get_host_name(hostname, 256); 5669 retvar->var_type = VAR_STRING; 5670 retvar->var_val.var_string = vim_strsave(hostname); 5671 } 5672 5673 /* 5674 * iconv() function 5675 */ 5676 /*ARGSUSED*/ 5677 static void 5678 f_iconv(argvars, retvar) 5679 VAR argvars; 5680 VAR retvar; 5681 { 5682 #ifdef FEAT_MBYTE 5683 char_u buf1[NUMBUFLEN]; 5684 char_u buf2[NUMBUFLEN]; 5685 char_u *from, *to, *str; 5686 vimconv_T vimconv; 5687 #endif 5688 5689 retvar->var_type = VAR_STRING; 5690 retvar->var_val.var_string = NULL; 5691 5692 #ifdef FEAT_MBYTE 5693 str = get_var_string(&argvars[0]); 5694 from = enc_canonize(enc_skip(get_var_string_buf(&argvars[1], buf1))); 5695 to = enc_canonize(enc_skip(get_var_string_buf(&argvars[2], buf2))); 5696 vimconv.vc_type = CONV_NONE; 5697 convert_setup(&vimconv, from, to); 5698 5699 /* If the encodings are equal, no conversion needed. */ 5700 if (vimconv.vc_type == CONV_NONE) 5701 retvar->var_val.var_string = vim_strsave(str); 5702 else 5703 retvar->var_val.var_string = string_convert(&vimconv, str, NULL); 5704 5705 convert_setup(&vimconv, NULL, NULL); 5706 vim_free(from); 5707 vim_free(to); 5708 #endif 5709 } 5710 5711 /* 5712 * "indent()" function 5713 */ 5714 static void 5715 f_indent(argvars, retvar) 5716 VAR argvars; 5717 VAR retvar; 5718 { 5719 linenr_T lnum; 5720 5721 lnum = get_var_lnum(argvars); 5722 if (lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count) 5723 retvar->var_val.var_number = get_indent_lnum(lnum); 5724 else 5725 retvar->var_val.var_number = -1; 5726 } 5727 5728 static int inputsecret_flag = 0; 5729 5730 /* 5731 * "input()" function 5732 * Also handles inputsecret() when inputsecret is set. 5733 */ 5734 static void 5735 f_input(argvars, retvar) 5736 VAR argvars; 5737 VAR retvar; 5738 { 5739 char_u *prompt = get_var_string(&argvars[0]); 5740 char_u *p = NULL; 5741 int c; 5742 char_u buf[NUMBUFLEN]; 5743 int cmd_silent_save = cmd_silent; 5744 5745 retvar->var_type = VAR_STRING; 5746 5747 #ifdef NO_CONSOLE_INPUT 5748 /* While starting up, there is no place to enter text. */ 5749 if (no_console_input()) 5750 { 5751 retvar->var_val.var_string = NULL; 5752 return; 5753 } 5754 #endif 5755 5756 cmd_silent = FALSE; /* Want to see the prompt. */ 5757 if (prompt != NULL) 5758 { 5759 /* Only the part of the message after the last NL is considered as 5760 * prompt for the command line */ 5761 p = vim_strrchr(prompt, '\n'); 5762 if (p == NULL) 5763 p = prompt; 5764 else 5765 { 5766 ++p; 5767 c = *p; 5768 *p = NUL; 5769 msg_start(); 5770 msg_clr_eos(); 5771 msg_puts_attr(prompt, echo_attr); 5772 msg_didout = FALSE; 5773 msg_starthere(); 5774 *p = c; 5775 } 5776 cmdline_row = msg_row; 5777 } 5778 5779 if (argvars[1].var_type != VAR_UNKNOWN) 5780 stuffReadbuffSpec(get_var_string_buf(&argvars[1], buf)); 5781 5782 retvar->var_val.var_string = 5783 getcmdline_prompt(inputsecret_flag ? NUL : '@', p, echo_attr); 5784 5785 /* since the user typed this, no need to wait for return */ 5786 need_wait_return = FALSE; 5787 msg_didout = FALSE; 5788 cmd_silent = cmd_silent_save; 5789 } 5790 5791 /* 5792 * "inputdialog()" function 5793 */ 5794 static void 5795 f_inputdialog(argvars, retvar) 5796 VAR argvars; 5797 VAR retvar; 5798 { 5799 #if defined(FEAT_GUI_TEXTDIALOG) 5800 /* Use a GUI dialog if the GUI is running and 'c' is not in 'guioptions' */ 5801 if (gui.in_use && vim_strchr(p_go, GO_CONDIALOG) == NULL) 5802 { 5803 char_u *message; 5804 char_u buf[NUMBUFLEN]; 5805 5806 message = get_var_string(&argvars[0]); 5807 if (argvars[1].var_type != VAR_UNKNOWN) 5808 { 5809 STRNCPY(IObuff, get_var_string_buf(&argvars[1], buf), IOSIZE); 5810 IObuff[IOSIZE - 1] = NUL; 5811 } 5812 else 5813 IObuff[0] = NUL; 5814 if (do_dialog(VIM_QUESTION, NULL, message, (char_u *)_("&OK\n&Cancel"), 5815 1, IObuff) == 1) 5816 retvar->var_val.var_string = vim_strsave(IObuff); 5817 else 5818 { 5819 if (argvars[1].var_type != VAR_UNKNOWN 5820 && argvars[2].var_type != VAR_UNKNOWN) 5821 retvar->var_val.var_string = vim_strsave( 5822 get_var_string_buf(&argvars[2], buf)); 5823 else 5824 retvar->var_val.var_string = NULL; 5825 } 5826 retvar->var_type = VAR_STRING; 5827 } 5828 else 5829 #endif 5830 f_input(argvars, retvar); 5831 } 5832 5833 static garray_T ga_userinput = {0, 0, sizeof(tasave_T), 4, NULL}; 5834 5835 /* 5836 * "inputrestore()" function 5837 */ 5838 /*ARGSUSED*/ 5839 static void 5840 f_inputrestore(argvars, retvar) 5841 VAR argvars; 5842 VAR retvar; 5843 { 5844 if (ga_userinput.ga_len > 0) 5845 { 5846 --ga_userinput.ga_len; 5847 ++ga_userinput.ga_room; 5848 restore_typeahead((tasave_T *)(ga_userinput.ga_data) 5849 + ga_userinput.ga_len); 5850 retvar->var_val.var_number = 0; /* OK */ 5851 } 5852 else if (p_verbose > 1) 5853 { 5854 msg((char_u *)_("called inputrestore() more often than inputsave()")); 5855 retvar->var_val.var_number = 1; /* Failed */ 5856 } 5857 } 5858 5859 /* 5860 * "inputsave()" function 5861 */ 5862 /*ARGSUSED*/ 5863 static void 5864 f_inputsave(argvars, retvar) 5865 VAR argvars; 5866 VAR retvar; 5867 { 5868 /* Add an entry to the stack of typehead storage. */ 5869 if (ga_grow(&ga_userinput, 1) == OK) 5870 { 5871 save_typeahead((tasave_T *)(ga_userinput.ga_data) 5872 + ga_userinput.ga_len); 5873 ++ga_userinput.ga_len; 5874 --ga_userinput.ga_room; 5875 retvar->var_val.var_number = 0; /* OK */ 5876 } 5877 else 5878 retvar->var_val.var_number = 1; /* Failed */ 5879 } 5880 5881 /* 5882 * "inputsecret()" function 5883 */ 5884 static void 5885 f_inputsecret(argvars, retvar) 5886 VAR argvars; 5887 VAR retvar; 5888 { 5889 ++cmdline_star; 5890 ++inputsecret_flag; 5891 f_input(argvars, retvar); 5892 --cmdline_star; 5893 --inputsecret_flag; 5894 } 5895 5896 /* 5897 * "isdirectory()" function 5898 */ 5899 static void 5900 f_isdirectory(argvars, retvar) 5901 VAR argvars; 5902 VAR retvar; 5903 { 5904 retvar->var_val.var_number = mch_isdir(get_var_string(&argvars[0])); 5905 } 5906 5907 /* 5908 * "last_buffer_nr()" function. 5909 */ 5910 /*ARGSUSED*/ 5911 static void 5912 f_last_buffer_nr(argvars, retvar) 5913 VAR argvars; 5914 VAR retvar; 5915 { 5916 int n = 0; 5917 buf_T *buf; 5918 5919 for (buf = firstbuf; buf != NULL; buf = buf->b_next) 5920 if (n < buf->b_fnum) 5921 n = buf->b_fnum; 5922 5923 retvar->var_val.var_number = n; 5924 } 5925 5926 /* 5927 * "line(string)" function 5928 */ 5929 static void 5930 f_line(argvars, retvar) 5931 VAR argvars; 5932 VAR retvar; 5933 { 5934 linenr_T lnum = 0; 5935 pos_T *fp; 5936 5937 fp = var2fpos(&argvars[0], TRUE); 5938 if (fp != NULL) 5939 lnum = fp->lnum; 5940 retvar->var_val.var_number = lnum; 5941 } 5942 5943 /* 5944 * "line2byte(lnum)" function 5945 */ 5946 /*ARGSUSED*/ 5947 static void 5948 f_line2byte(argvars, retvar) 5949 VAR argvars; 5950 VAR retvar; 5951 { 5952 #ifndef FEAT_BYTEOFF 5953 retvar->var_val.var_number = -1; 5954 #else 5955 linenr_T lnum; 5956 5957 lnum = get_var_lnum(argvars); 5958 if (lnum < 1 || lnum > curbuf->b_ml.ml_line_count + 1) 5959 retvar->var_val.var_number = -1; 5960 else 5961 retvar->var_val.var_number = ml_find_line_or_offset(curbuf, lnum, NULL); 5962 if (retvar->var_val.var_number >= 0) 5963 ++retvar->var_val.var_number; 5964 #endif 5965 } 5966 5967 /* 5968 * "lispindent(lnum)" function 5969 */ 5970 static void 5971 f_lispindent(argvars, retvar) 5972 VAR argvars; 5973 VAR retvar; 5974 { 5975 #ifdef FEAT_LISP 5976 pos_T pos; 5977 linenr_T lnum; 5978 5979 pos = curwin->w_cursor; 5980 lnum = get_var_lnum(argvars); 5981 if (lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count) 5982 { 5983 curwin->w_cursor.lnum = lnum; 5984 retvar->var_val.var_number = get_lisp_indent(); 5985 curwin->w_cursor = pos; 5986 } 5987 else 5988 #endif 5989 retvar->var_val.var_number = -1; 5990 } 5991 5992 /* 5993 * "localtime()" function 5994 */ 5995 /*ARGSUSED*/ 5996 static void 5997 f_localtime(argvars, retvar) 5998 VAR argvars; 5999 VAR retvar; 6000 { 6001 retvar->var_val.var_number = (varnumber_T)time(NULL); 6002 } 6003 6004 /* 6005 * "maparg()" function 6006 */ 6007 static void 6008 f_maparg(argvars, retvar) 6009 VAR argvars; 6010 VAR retvar; 6011 { 6012 get_maparg(argvars, retvar, TRUE); 6013 } 6014 6015 /* 6016 * "mapcheck()" function 6017 */ 6018 static void 6019 f_mapcheck(argvars, retvar) 6020 VAR argvars; 6021 VAR retvar; 6022 { 6023 get_maparg(argvars, retvar, FALSE); 6024 } 6025 6026 static void 6027 get_maparg(argvars, retvar, exact) 6028 VAR argvars; 6029 VAR retvar; 6030 int exact; 6031 { 6032 char_u *keys; 6033 char_u *which; 6034 char_u buf[NUMBUFLEN]; 6035 char_u *keys_buf = NULL; 6036 char_u *rhs; 6037 int mode; 6038 garray_T ga; 6039 6040 /* return empty string for failure */ 6041 retvar->var_type = VAR_STRING; 6042 retvar->var_val.var_string = NULL; 6043 6044 keys = get_var_string(&argvars[0]); 6045 if (*keys == NUL) 6046 return; 6047 6048 if (argvars[1].var_type != VAR_UNKNOWN) 6049 which = get_var_string_buf(&argvars[1], buf); 6050 else 6051 which = (char_u *)""; 6052 mode = get_map_mode(&which, 0); 6053 6054 keys = replace_termcodes(keys, &keys_buf, TRUE, TRUE); 6055 rhs = check_map(keys, mode, exact); 6056 vim_free(keys_buf); 6057 if (rhs != NULL) 6058 { 6059 ga_init(&ga); 6060 ga.ga_itemsize = 1; 6061 ga.ga_growsize = 40; 6062 6063 while (*rhs != NUL) 6064 ga_concat(&ga, str2special(&rhs, FALSE)); 6065 6066 ga_append(&ga, NUL); 6067 retvar->var_val.var_string = (char_u *)ga.ga_data; 6068 } 6069 } 6070 6071 /* 6072 * "match()" function 6073 */ 6074 static void 6075 f_match(argvars, retvar) 6076 VAR argvars; 6077 VAR retvar; 6078 { 6079 find_some_match(argvars, retvar, 1); 6080 } 6081 6082 /* 6083 * "matchend()" function 6084 */ 6085 static void 6086 f_matchend(argvars, retvar) 6087 VAR argvars; 6088 VAR retvar; 6089 { 6090 find_some_match(argvars, retvar, 0); 6091 } 6092 6093 /* 6094 * "matchstr()" function 6095 */ 6096 static void 6097 f_matchstr(argvars, retvar) 6098 VAR argvars; 6099 VAR retvar; 6100 { 6101 find_some_match(argvars, retvar, 2); 6102 } 6103 6104 static void 6105 find_some_match(argvars, retvar, type) 6106 VAR argvars; 6107 VAR retvar; 6108 int type; 6109 { 6110 char_u *str; 6111 char_u *expr; 6112 char_u *pat; 6113 regmatch_T regmatch; 6114 char_u patbuf[NUMBUFLEN]; 6115 char_u *save_cpo; 6116 long start = 0; 6117 long nth = 1; 6118 int match; 6119 6120 /* Make 'cpoptions' empty, the 'l' flag should not be used here. */ 6121 save_cpo = p_cpo; 6122 p_cpo = (char_u *)""; 6123 6124 expr = str = get_var_string(&argvars[0]); 6125 pat = get_var_string_buf(&argvars[1], patbuf); 6126 6127 if (type == 2) 6128 { 6129 retvar->var_type = VAR_STRING; 6130 retvar->var_val.var_string = NULL; 6131 } 6132 else 6133 retvar->var_val.var_number = -1; 6134 6135 if (argvars[2].var_type != VAR_UNKNOWN) 6136 { 6137 start = get_var_number(&argvars[2]); 6138 if (start < 0) 6139 start = 0; 6140 if (start > (long)STRLEN(str)) 6141 goto theend; 6142 str += start; 6143 6144 if (argvars[3].var_type != VAR_UNKNOWN) 6145 nth = get_var_number(&argvars[3]); 6146 } 6147 6148 regmatch.regprog = vim_regcomp(pat, RE_MAGIC + RE_STRING); 6149 if (regmatch.regprog != NULL) 6150 { 6151 regmatch.rm_ic = p_ic; 6152 6153 while (1) 6154 { 6155 match = vim_regexec_nl(®match, str, (colnr_T)0); 6156 if (!match || --nth <= 0) 6157 break; 6158 /* Advance to just after the match. */ 6159 #ifdef FEAT_MBYTE 6160 str = regmatch.startp[0] + mb_ptr2len_check(regmatch.startp[0]); 6161 #else 6162 str = regmatch.startp[0] + 1; 6163 #endif 6164 } 6165 6166 if (match) 6167 { 6168 if (type == 2) 6169 retvar->var_val.var_string = vim_strnsave(regmatch.startp[0], 6170 (int)(regmatch.endp[0] - regmatch.startp[0])); 6171 else 6172 { 6173 if (type != 0) 6174 retvar->var_val.var_number = 6175 (varnumber_T)(regmatch.startp[0] - str); 6176 else 6177 retvar->var_val.var_number = 6178 (varnumber_T)(regmatch.endp[0] - str); 6179 retvar->var_val.var_number += str - expr; 6180 } 6181 } 6182 vim_free(regmatch.regprog); 6183 } 6184 6185 theend: 6186 p_cpo = save_cpo; 6187 } 6188 6189 /* 6190 * "mode()" function 6191 */ 6192 /*ARGSUSED*/ 6193 static void 6194 f_mode(argvars, retvar) 6195 VAR argvars; 6196 VAR retvar; 6197 { 6198 char_u buf[2]; 6199 6200 #ifdef FEAT_VISUAL 6201 if (VIsual_active) 6202 { 6203 if (VIsual_select) 6204 buf[0] = VIsual_mode + 's' - 'v'; 6205 else 6206 buf[0] = VIsual_mode; 6207 } 6208 else 6209 #endif 6210 if (State == HITRETURN || State == ASKMORE || State == SETWSIZE) 6211 buf[0] = 'r'; 6212 else if (State & INSERT) 6213 { 6214 if (State & REPLACE_FLAG) 6215 buf[0] = 'R'; 6216 else 6217 buf[0] = 'i'; 6218 } 6219 else if (State & CMDLINE) 6220 buf[0] = 'c'; 6221 else 6222 buf[0] = 'n'; 6223 6224 buf[1] = NUL; 6225 retvar->var_val.var_string = vim_strsave(buf); 6226 retvar->var_type = VAR_STRING; 6227 } 6228 6229 /* 6230 * "nr2char()" function 6231 */ 6232 static void 6233 f_nr2char(argvars, retvar) 6234 VAR argvars; 6235 VAR retvar; 6236 { 6237 char_u buf[NUMBUFLEN]; 6238 6239 #ifdef FEAT_MBYTE 6240 if (has_mbyte) 6241 buf[(*mb_char2bytes)((int)get_var_number(&argvars[0]), buf)] = NUL; 6242 else 6243 #endif 6244 { 6245 buf[0] = (char_u)get_var_number(&argvars[0]); 6246 buf[1] = NUL; 6247 } 6248 retvar->var_type = VAR_STRING; 6249 retvar->var_val.var_string = vim_strsave(buf); 6250 } 6251 6252 /* 6253 * "rename({from}, {to})" function 6254 */ 6255 static void 6256 f_rename(argvars, retvar) 6257 VAR argvars; 6258 VAR retvar; 6259 { 6260 char_u buf[NUMBUFLEN]; 6261 6262 if (check_restricted() || check_secure()) 6263 retvar->var_val.var_number = -1; 6264 else 6265 retvar->var_val.var_number = vim_rename(get_var_string(&argvars[0]), 6266 get_var_string_buf(&argvars[1], buf)); 6267 } 6268 6269 /* 6270 * "resolve()" function 6271 */ 6272 static void 6273 f_resolve(argvars, retvar) 6274 VAR argvars; 6275 VAR retvar; 6276 { 6277 char_u *p; 6278 6279 p = get_var_string(&argvars[0]); 6280 #ifdef FEAT_SHORTCUT 6281 { 6282 char_u *v = NULL; 6283 6284 v = mch_resolve_shortcut(p); 6285 if (v != NULL) 6286 retvar->var_val.var_string = v; 6287 else 6288 retvar->var_val.var_string = vim_strsave(p); 6289 } 6290 #else 6291 # ifdef HAVE_READLINK 6292 { 6293 char_u buf[MAXPATHL + 1]; 6294 char_u *cpy; 6295 int len; 6296 char_u *remain = NULL; 6297 char_u *q; 6298 int is_relative_to_current = FALSE; 6299 int has_trailing_pathsep = FALSE; 6300 int limit = 100; 6301 6302 p = vim_strsave(p); 6303 6304 if (p[0] == '.' && (vim_ispathsep(p[1]) 6305 || (p[1] == '.' && (vim_ispathsep(p[2]))))) 6306 is_relative_to_current = TRUE; 6307 6308 len = STRLEN(p); 6309 if (len > 0 && vim_ispathsep(p[len-1])) 6310 has_trailing_pathsep = TRUE; 6311 6312 q = getnextcomp(p); 6313 if (*q != NUL) 6314 { 6315 /* Separate the first path component in "p", and keep the 6316 * remainder (beginning with the path separator). */ 6317 remain = vim_strsave(q - 1); 6318 q[-1] = NUL; 6319 } 6320 6321 for (;;) 6322 { 6323 for (;;) 6324 { 6325 len = readlink((char *)p, (char *)buf, MAXPATHL); 6326 if (len <= 0) 6327 break; 6328 buf[len] = NUL; 6329 6330 if (limit-- == 0) 6331 { 6332 vim_free(p); 6333 vim_free(remain); 6334 EMSG(_("E655: Too many symbolic links (cycle?)")); 6335 retvar->var_val.var_string = NULL; 6336 goto fail; 6337 } 6338 6339 /* Ensure that the result will have a trailing path separator 6340 * if the argument has one. */ 6341 if (remain == NULL && has_trailing_pathsep) 6342 add_pathsep(buf); 6343 6344 /* Separate the first path component in the link value and 6345 * concatenate the remainders. */ 6346 q = getnextcomp(vim_ispathsep(*buf) ? buf + 1 : buf); 6347 if (*q != NUL) 6348 { 6349 if (remain == NULL) 6350 remain = vim_strsave(q - 1); 6351 else 6352 { 6353 cpy = vim_strnsave(q-1, STRLEN(q-1)+STRLEN(remain)); 6354 if (cpy != NULL) 6355 { 6356 STRCAT(cpy, remain); 6357 vim_free(remain); 6358 remain = cpy; 6359 } 6360 } 6361 q[-1] = NUL; 6362 } 6363 6364 q = gettail(p); 6365 if (q > p && *q == NUL) 6366 { 6367 /* Ignore trailing path separator. */ 6368 q[-1] = NUL; 6369 q = gettail(p); 6370 } 6371 if (q > p && !mch_isFullName(buf)) 6372 { 6373 /* symlink is relative to directory of argument */ 6374 cpy = alloc((unsigned)(STRLEN(p) + STRLEN(buf) + 1)); 6375 if (cpy != NULL) 6376 { 6377 STRCPY(cpy, p); 6378 STRCPY(gettail(cpy), buf); 6379 vim_free(p); 6380 p = cpy; 6381 } 6382 } 6383 else 6384 { 6385 vim_free(p); 6386 p = vim_strsave(buf); 6387 } 6388 } 6389 6390 if (remain == NULL) 6391 break; 6392 6393 /* Append the first path component of "remain" to "p". */ 6394 q = getnextcomp(remain + 1); 6395 len = q - remain - (*q != NUL); 6396 cpy = vim_strnsave(p, STRLEN(p) + len); 6397 if (cpy != NULL) 6398 { 6399 STRNCAT(cpy, remain, len); 6400 vim_free(p); 6401 p = cpy; 6402 } 6403 /* Shorten "remain". */ 6404 if (*q != NUL) 6405 STRCPY(remain, q - 1); 6406 else 6407 { 6408 vim_free(remain); 6409 remain = NULL; 6410 } 6411 } 6412 6413 /* If the result is a relative path name, make it explicitly relative to 6414 * the current directory if and only if the argument had this form. */ 6415 if (!vim_ispathsep(*p)) 6416 { 6417 if (is_relative_to_current 6418 && *p != NUL 6419 && !(p[0] == '.' 6420 && (p[1] == NUL 6421 || vim_ispathsep(p[1]) 6422 || (p[1] == '.' 6423 && (p[2] == NUL 6424 || vim_ispathsep(p[2])))))) 6425 { 6426 /* Prepend "./". */ 6427 cpy = vim_strnsave((char_u *)"./", 2 + STRLEN(p)); 6428 if (cpy != NULL) 6429 { 6430 STRCAT(cpy, p); 6431 vim_free(p); 6432 p = cpy; 6433 } 6434 } 6435 else if (!is_relative_to_current) 6436 { 6437 /* Strip leading "./". */ 6438 q = p; 6439 while (q[0] == '.' && vim_ispathsep(q[1])) 6440 q += 2; 6441 if (q > p) 6442 mch_memmove(p, p + 2, STRLEN(p + 2) + (size_t)1); 6443 } 6444 } 6445 6446 /* Ensure that the result will have no trailing path separator 6447 * if the argument had none. But keep "/" or "//". */ 6448 if (!has_trailing_pathsep) 6449 { 6450 q = p + STRLEN(p); 6451 while ((q > p + 2 || (q == p + 2 && !vim_ispathsep(*p))) 6452 && vim_ispathsep(q[-1])) 6453 --q; 6454 *q = NUL; 6455 } 6456 6457 retvar->var_val.var_string = p; 6458 } 6459 # else 6460 retvar->var_val.var_string = vim_strsave(p); 6461 # endif 6462 #endif 6463 6464 simplify_filename(retvar->var_val.var_string); 6465 6466 #ifdef HAVE_READLINK 6467 fail: 6468 #endif 6469 retvar->var_type = VAR_STRING; 6470 } 6471 6472 /* 6473 * "simplify()" function 6474 */ 6475 static void 6476 f_simplify(argvars, retvar) 6477 VAR argvars; 6478 VAR retvar; 6479 { 6480 char_u *p; 6481 6482 p = get_var_string(&argvars[0]); 6483 retvar->var_val.var_string = vim_strsave(p); 6484 simplify_filename(retvar->var_val.var_string); /* simplify in place */ 6485 retvar->var_type = VAR_STRING; 6486 } 6487 6488 #define SP_NOMOVE 1 /* don't move cursor */ 6489 #define SP_REPEAT 2 /* repeat to find outer pair */ 6490 #define SP_RETCOUNT 4 /* return matchcount */ 6491 6492 /* 6493 * "search()" function 6494 */ 6495 static void 6496 f_search(argvars, retvar) 6497 VAR argvars; 6498 VAR retvar; 6499 { 6500 char_u *pat; 6501 pos_T pos; 6502 pos_T save_cursor; 6503 int save_p_ws = p_ws; 6504 int dir; 6505 int flags = 0; 6506 6507 retvar->var_val.var_number = 0; /* default: FAIL */ 6508 6509 pat = get_var_string(&argvars[0]); 6510 dir = get_search_arg(&argvars[1], &flags); /* may set p_ws */ 6511 if (dir == 0) 6512 goto theend; 6513 if ((flags & ~SP_NOMOVE) != 0) 6514 { 6515 EMSG2(_(e_invarg2), get_var_string(&argvars[1])); 6516 goto theend; 6517 } 6518 6519 pos = save_cursor = curwin->w_cursor; 6520 if (searchit(curwin, curbuf, &pos, dir, pat, 1L, 6521 SEARCH_KEEP, RE_SEARCH) != FAIL) 6522 { 6523 retvar->var_val.var_number = pos.lnum; 6524 curwin->w_cursor = pos; 6525 /* "/$" will put the cursor after the end of the line, may need to 6526 * correct that here */ 6527 check_cursor(); 6528 } 6529 6530 /* If 'n' flag is used: restore cursor position. */ 6531 if (flags & SP_NOMOVE) 6532 curwin->w_cursor = save_cursor; 6533 theend: 6534 p_ws = save_p_ws; 6535 } 6536 6537 /* 6538 * "searchpair()" function 6539 */ 6540 static void 6541 f_searchpair(argvars, retvar) 6542 VAR argvars; 6543 VAR retvar; 6544 { 6545 char_u *spat, *mpat, *epat; 6546 char_u *skip; 6547 char_u *pat, *pat2, *pat3; 6548 pos_T pos; 6549 pos_T firstpos; 6550 pos_T save_cursor; 6551 pos_T save_pos; 6552 int save_p_ws = p_ws; 6553 char_u *save_cpo; 6554 int dir; 6555 int flags = 0; 6556 char_u nbuf1[NUMBUFLEN]; 6557 char_u nbuf2[NUMBUFLEN]; 6558 char_u nbuf3[NUMBUFLEN]; 6559 int n; 6560 int r; 6561 int nest = 1; 6562 int err; 6563 6564 retvar->var_val.var_number = 0; /* default: FAIL */ 6565 6566 /* Make 'cpoptions' empty, the 'l' flag should not be used here. */ 6567 save_cpo = p_cpo; 6568 p_cpo = (char_u *)""; 6569 6570 /* Get the three pattern arguments: start, middle, end. */ 6571 spat = get_var_string(&argvars[0]); 6572 mpat = get_var_string_buf(&argvars[1], nbuf1); 6573 epat = get_var_string_buf(&argvars[2], nbuf2); 6574 6575 /* Make two search patterns: start/end (pat2, for in nested pairs) and 6576 * start/middle/end (pat3, for the top pair). */ 6577 pat2 = alloc((unsigned)(STRLEN(spat) + STRLEN(epat) + 15)); 6578 pat3 = alloc((unsigned)(STRLEN(spat) + STRLEN(mpat) + STRLEN(epat) + 23)); 6579 if (pat2 == NULL || pat3 == NULL) 6580 goto theend; 6581 sprintf((char *)pat2, "\\(%s\\m\\)\\|\\(%s\\m\\)", spat, epat); 6582 if (*mpat == NUL) 6583 STRCPY(pat3, pat2); 6584 else 6585 sprintf((char *)pat3, "\\(%s\\m\\)\\|\\(%s\\m\\)\\|\\(%s\\m\\)", 6586 spat, epat, mpat); 6587 6588 /* Handle the optional fourth argument: flags */ 6589 dir = get_search_arg(&argvars[3], &flags); /* may set p_ws */ 6590 if (dir == 0) 6591 goto theend; 6592 6593 /* Optional fifth argument: skip expresion */ 6594 if (argvars[3].var_type == VAR_UNKNOWN 6595 || argvars[4].var_type == VAR_UNKNOWN) 6596 skip = (char_u *)""; 6597 else 6598 skip = get_var_string_buf(&argvars[4], nbuf3); 6599 6600 save_cursor = curwin->w_cursor; 6601 pos = curwin->w_cursor; 6602 firstpos.lnum = 0; 6603 pat = pat3; 6604 for (;;) 6605 { 6606 n = searchit(curwin, curbuf, &pos, dir, pat, 1L, 6607 SEARCH_KEEP, RE_SEARCH); 6608 if (n == FAIL || (firstpos.lnum != 0 && equalpos(pos, firstpos))) 6609 /* didn't find it or found the first match again: FAIL */ 6610 break; 6611 6612 if (firstpos.lnum == 0) 6613 firstpos = pos; 6614 6615 /* If the skip pattern matches, ignore this match. */ 6616 if (*skip != NUL) 6617 { 6618 save_pos = curwin->w_cursor; 6619 curwin->w_cursor = pos; 6620 r = eval_to_bool(skip, &err, NULL, FALSE); 6621 curwin->w_cursor = save_pos; 6622 if (err) 6623 { 6624 /* Evaluating {skip} caused an error, break here. */ 6625 curwin->w_cursor = save_cursor; 6626 retvar->var_val.var_number = -1; 6627 break; 6628 } 6629 if (r) 6630 continue; 6631 } 6632 6633 if ((dir == BACKWARD && n == 3) || (dir == FORWARD && n == 2)) 6634 { 6635 /* Found end when searching backwards or start when searching 6636 * forward: nested pair. */ 6637 ++nest; 6638 pat = pat2; /* nested, don't search for middle */ 6639 } 6640 else 6641 { 6642 /* Found end when searching forward or start when searching 6643 * backward: end of (nested) pair; or found middle in outer pair. */ 6644 if (--nest == 1) 6645 pat = pat3; /* outer level, search for middle */ 6646 } 6647 6648 if (nest == 0) 6649 { 6650 /* Found the match: return matchcount or line number. */ 6651 if (flags & SP_RETCOUNT) 6652 ++retvar->var_val.var_number; 6653 else 6654 retvar->var_val.var_number = pos.lnum; 6655 curwin->w_cursor = pos; 6656 if (!(flags & SP_REPEAT)) 6657 break; 6658 nest = 1; /* search for next unmatched */ 6659 } 6660 } 6661 6662 /* If 'n' flag is used or search failed: restore cursor position. */ 6663 if ((flags & SP_NOMOVE) || retvar->var_val.var_number == 0) 6664 curwin->w_cursor = save_cursor; 6665 6666 theend: 6667 vim_free(pat2); 6668 vim_free(pat3); 6669 p_ws = save_p_ws; 6670 p_cpo = save_cpo; 6671 } 6672 6673 /* 6674 * Get flags for a search function. 6675 * Possibly sets "p_ws". 6676 * Returns BACKWARD, FORWARD or zero (for an error). 6677 */ 6678 static int 6679 get_search_arg(varp, flagsp) 6680 VAR varp; 6681 int *flagsp; 6682 { 6683 int dir = FORWARD; 6684 char_u *flags; 6685 char_u nbuf[NUMBUFLEN]; 6686 int mask; 6687 6688 if (varp->var_type != VAR_UNKNOWN) 6689 { 6690 flags = get_var_string_buf(varp, nbuf); 6691 while (*flags != NUL) 6692 { 6693 switch (*flags) 6694 { 6695 case 'b': dir = BACKWARD; break; 6696 case 'w': p_ws = TRUE; break; 6697 case 'W': p_ws = FALSE; break; 6698 default: mask = 0; 6699 if (flagsp != NULL) 6700 switch (*flags) 6701 { 6702 case 'n': mask = SP_NOMOVE; break; 6703 case 'r': mask = SP_REPEAT; break; 6704 case 'm': mask = SP_RETCOUNT; break; 6705 } 6706 if (mask == 0) 6707 { 6708 EMSG2(_(e_invarg2), flags); 6709 dir = 0; 6710 } 6711 else 6712 *flagsp |= mask; 6713 } 6714 if (dir == 0) 6715 break; 6716 ++flags; 6717 } 6718 } 6719 return dir; 6720 } 6721 6722 /* 6723 * "setbufvar()" function 6724 */ 6725 /*ARGSUSED*/ 6726 static void 6727 f_setbufvar(argvars, retvar) 6728 VAR argvars; 6729 VAR retvar; 6730 { 6731 buf_T *buf; 6732 #ifdef FEAT_AUTOCMD 6733 aco_save_T aco; 6734 #else 6735 buf_T *save_curbuf; 6736 #endif 6737 char_u *varname, *bufvarname; 6738 VAR varp; 6739 char_u nbuf[NUMBUFLEN]; 6740 6741 if (check_restricted() || check_secure()) 6742 return; 6743 ++emsg_off; 6744 buf = get_buf_var(&argvars[0]); 6745 varname = get_var_string(&argvars[1]); 6746 varp = &argvars[2]; 6747 6748 if (buf != NULL && varname != NULL && varp != NULL) 6749 { 6750 /* set curbuf to be our buf, temporarily */ 6751 #ifdef FEAT_AUTOCMD 6752 aucmd_prepbuf(&aco, buf); 6753 #else 6754 save_curbuf = curbuf; 6755 curbuf = buf; 6756 #endif 6757 6758 if (*varname == '&') 6759 { 6760 ++varname; 6761 set_option_value(varname, get_var_number(varp), 6762 get_var_string_buf(varp, nbuf), OPT_LOCAL); 6763 } 6764 else 6765 { 6766 bufvarname = alloc((unsigned)STRLEN(varname) + 3); 6767 if (bufvarname != NULL) 6768 { 6769 STRCPY(bufvarname, "b:"); 6770 STRCPY(bufvarname + 2, varname); 6771 set_var(bufvarname, varp); 6772 vim_free(bufvarname); 6773 } 6774 } 6775 6776 /* reset notion of buffer */ 6777 #ifdef FEAT_AUTOCMD 6778 aucmd_restbuf(&aco); 6779 #else 6780 curbuf = save_curbuf; 6781 #endif 6782 } 6783 --emsg_off; 6784 } 6785 6786 /* 6787 * "setcmdpos()" function 6788 */ 6789 static void 6790 f_setcmdpos(argvars, retvar) 6791 VAR argvars; 6792 VAR retvar; 6793 { 6794 retvar->var_val.var_number = set_cmdline_pos( 6795 (int)get_var_number(&argvars[0]) - 1); 6796 } 6797 6798 /* 6799 * "setline()" function 6800 */ 6801 static void 6802 f_setline(argvars, retvar) 6803 VAR argvars; 6804 VAR retvar; 6805 { 6806 linenr_T lnum; 6807 char_u *line; 6808 6809 lnum = get_var_lnum(argvars); 6810 line = get_var_string(&argvars[1]); 6811 retvar->var_val.var_number = 1; /* FAIL is default */ 6812 6813 if (lnum >= 1 6814 && lnum <= curbuf->b_ml.ml_line_count 6815 && u_savesub(lnum) == OK 6816 && ml_replace(lnum, line, TRUE) == OK) 6817 { 6818 changed_bytes(lnum, 0); 6819 check_cursor_col(); 6820 retvar->var_val.var_number = 0; 6821 } 6822 } 6823 6824 /* 6825 * "setreg()" function 6826 */ 6827 static void 6828 f_setreg(argvars, retvar) 6829 VAR argvars; 6830 VAR retvar; 6831 { 6832 int regname; 6833 char_u *strregname; 6834 char_u *stropt; 6835 int append; 6836 char_u yank_type; 6837 long block_len; 6838 6839 block_len = -1; 6840 yank_type = MAUTO; 6841 append = FALSE; 6842 6843 strregname = get_var_string(argvars); 6844 retvar->var_val.var_number = 1; /* FAIL is default */ 6845 6846 regname = (strregname == NULL ? '"' : *strregname); 6847 if (regname == 0 || regname == '@') 6848 regname = '"'; 6849 else if (regname == '=') 6850 return; 6851 6852 if (argvars[2].var_type != VAR_UNKNOWN) 6853 { 6854 for (stropt = get_var_string(&argvars[2]); *stropt != NUL; ++stropt) 6855 switch (*stropt) 6856 { 6857 case 'a': case 'A': /* append */ 6858 append = TRUE; 6859 break; 6860 case 'v': case 'c': /* character-wise selection */ 6861 yank_type = MCHAR; 6862 break; 6863 case 'V': case 'l': /* line-wise selection */ 6864 yank_type = MLINE; 6865 break; 6866 #ifdef FEAT_VISUAL 6867 case 'b': case Ctrl_V: /* block-wise selection */ 6868 yank_type = MBLOCK; 6869 if (VIM_ISDIGIT(stropt[1])) 6870 { 6871 ++stropt; 6872 block_len = getdigits(&stropt) - 1; 6873 --stropt; 6874 } 6875 break; 6876 #endif 6877 } 6878 } 6879 6880 write_reg_contents_ex(regname, get_var_string(&argvars[1]), -1, 6881 append, yank_type, block_len); 6882 retvar->var_val.var_number = 0; 6883 } 6884 6885 6886 /* 6887 * "setwinvar(expr)" function 6888 */ 6889 /*ARGSUSED*/ 6890 static void 6891 f_setwinvar(argvars, retvar) 6892 VAR argvars; 6893 VAR retvar; 6894 { 6895 win_T *win; 6896 #ifdef FEAT_WINDOWS 6897 win_T *save_curwin; 6898 #endif 6899 char_u *varname, *winvarname; 6900 VAR varp; 6901 char_u nbuf[NUMBUFLEN]; 6902 6903 if (check_restricted() || check_secure()) 6904 return; 6905 ++emsg_off; 6906 win = find_win_by_nr(&argvars[0]); 6907 varname = get_var_string(&argvars[1]); 6908 varp = &argvars[2]; 6909 6910 if (win != NULL && varname != NULL && varp != NULL) 6911 { 6912 #ifdef FEAT_WINDOWS 6913 /* set curwin to be our win, temporarily */ 6914 save_curwin = curwin; 6915 curwin = win; 6916 curbuf = curwin->w_buffer; 6917 #endif 6918 6919 if (*varname == '&') 6920 { 6921 ++varname; 6922 set_option_value(varname, get_var_number(varp), 6923 get_var_string_buf(varp, nbuf), OPT_LOCAL); 6924 } 6925 else 6926 { 6927 winvarname = alloc((unsigned)STRLEN(varname) + 3); 6928 if (winvarname != NULL) 6929 { 6930 STRCPY(winvarname, "w:"); 6931 STRCPY(winvarname + 2, varname); 6932 set_var(winvarname, varp); 6933 vim_free(winvarname); 6934 } 6935 } 6936 6937 #ifdef FEAT_WINDOWS 6938 /* Restore current window, if it's still valid (autocomands can make 6939 * it invalid). */ 6940 if (win_valid(save_curwin)) 6941 { 6942 curwin = save_curwin; 6943 curbuf = curwin->w_buffer; 6944 } 6945 #endif 6946 } 6947 --emsg_off; 6948 } 6949 6950 /* 6951 * "nextnonblank()" function 6952 */ 6953 static void 6954 f_nextnonblank(argvars, retvar) 6955 VAR argvars; 6956 VAR retvar; 6957 { 6958 linenr_T lnum; 6959 6960 for (lnum = get_var_lnum(argvars); ; ++lnum) 6961 { 6962 if (lnum > curbuf->b_ml.ml_line_count) 6963 { 6964 lnum = 0; 6965 break; 6966 } 6967 if (*skipwhite(ml_get(lnum)) != NUL) 6968 break; 6969 } 6970 retvar->var_val.var_number = lnum; 6971 } 6972 6973 /* 6974 * "prevnonblank()" function 6975 */ 6976 static void 6977 f_prevnonblank(argvars, retvar) 6978 VAR argvars; 6979 VAR retvar; 6980 { 6981 linenr_T lnum; 6982 6983 lnum = get_var_lnum(argvars); 6984 if (lnum < 1 || lnum > curbuf->b_ml.ml_line_count) 6985 lnum = 0; 6986 else 6987 while (lnum >= 1 && *skipwhite(ml_get(lnum)) == NUL) 6988 --lnum; 6989 retvar->var_val.var_number = lnum; 6990 } 6991 6992 #if defined(FEAT_CLIENTSERVER) && defined(FEAT_X11) 6993 static void make_connection __ARGS((void)); 6994 static int check_connection __ARGS((void)); 6995 6996 static void 6997 make_connection() 6998 { 6999 if (X_DISPLAY == NULL 7000 # ifdef FEAT_GUI 7001 && !gui.in_use 7002 # endif 7003 ) 7004 { 7005 x_force_connect = TRUE; 7006 setup_term_clip(); 7007 x_force_connect = FALSE; 7008 } 7009 } 7010 7011 static int 7012 check_connection() 7013 { 7014 make_connection(); 7015 if (X_DISPLAY == NULL) 7016 { 7017 EMSG(_("E240: No connection to Vim server")); 7018 return FAIL; 7019 } 7020 return OK; 7021 } 7022 #endif 7023 7024 /*ARGSUSED*/ 7025 static void 7026 f_serverlist(argvars, retvar) 7027 VAR argvars; 7028 VAR retvar; 7029 { 7030 char_u *r = NULL; 7031 7032 #ifdef FEAT_CLIENTSERVER 7033 # ifdef WIN32 7034 r = serverGetVimNames(); 7035 # else 7036 make_connection(); 7037 if (X_DISPLAY != NULL) 7038 r = serverGetVimNames(X_DISPLAY); 7039 # endif 7040 #endif 7041 retvar->var_type = VAR_STRING; 7042 retvar->var_val.var_string = r; 7043 } 7044 7045 /*ARGSUSED*/ 7046 static void 7047 f_remote_peek(argvars, retvar) 7048 VAR argvars; 7049 VAR retvar; 7050 { 7051 #ifdef FEAT_CLIENTSERVER 7052 var v; 7053 char_u *s = NULL; 7054 # ifdef WIN32 7055 int n = 0; 7056 # endif 7057 7058 if (check_restricted() || check_secure()) 7059 { 7060 retvar->var_val.var_number = -1; 7061 return; 7062 } 7063 # ifdef WIN32 7064 sscanf(get_var_string(&argvars[0]), "%x", &n); 7065 if (n == 0) 7066 retvar->var_val.var_number = -1; 7067 else 7068 { 7069 s = serverGetReply((HWND)n, FALSE, FALSE, FALSE); 7070 retvar->var_val.var_number = (s != NULL); 7071 } 7072 # else 7073 retvar->var_val.var_number = 0; 7074 if (check_connection() == FAIL) 7075 return; 7076 7077 retvar->var_val.var_number = serverPeekReply(X_DISPLAY, 7078 serverStrToWin(get_var_string(&argvars[0])), &s); 7079 # endif 7080 7081 if (argvars[1].var_type != VAR_UNKNOWN && retvar->var_val.var_number > 0) 7082 { 7083 v.var_type = VAR_STRING; 7084 v.var_val.var_string = vim_strsave(s); 7085 set_var(get_var_string(&argvars[1]), &v); 7086 } 7087 #else 7088 retvar->var_val.var_number = -1; 7089 #endif 7090 } 7091 7092 /*ARGSUSED*/ 7093 static void 7094 f_remote_read(argvars, retvar) 7095 VAR argvars; 7096 VAR retvar; 7097 { 7098 char_u *r = NULL; 7099 7100 #ifdef FEAT_CLIENTSERVER 7101 if (!check_restricted() && !check_secure()) 7102 { 7103 # ifdef WIN32 7104 /* The server's HWND is encoded in the 'id' parameter */ 7105 int n = 0; 7106 7107 sscanf(get_var_string(&argvars[0]), "%x", &n); 7108 if (n != 0) 7109 r = serverGetReply((HWND)n, FALSE, TRUE, TRUE); 7110 if (r == NULL) 7111 # else 7112 if (check_connection() == FAIL || serverReadReply(X_DISPLAY, 7113 serverStrToWin(get_var_string(&argvars[0])), &r, FALSE) < 0) 7114 # endif 7115 EMSG(_("E277: Unable to read a server reply")); 7116 } 7117 #endif 7118 retvar->var_type = VAR_STRING; 7119 retvar->var_val.var_string = r; 7120 } 7121 7122 /*ARGSUSED*/ 7123 static void 7124 f_server2client(argvars, retvar) 7125 VAR argvars; 7126 VAR retvar; 7127 { 7128 #ifdef FEAT_CLIENTSERVER 7129 char_u buf[NUMBUFLEN]; 7130 char_u *server = get_var_string(&argvars[0]); 7131 char_u *reply = get_var_string_buf(&argvars[1], buf); 7132 7133 retvar->var_val.var_number = -1; 7134 if (check_restricted() || check_secure()) 7135 return; 7136 # ifdef FEAT_X11 7137 if (check_connection() == FAIL) 7138 return; 7139 # endif 7140 7141 if (serverSendReply(server, reply) < 0) 7142 { 7143 EMSG(_("E258: Unable to send to client")); 7144 return; 7145 } 7146 retvar->var_val.var_number = 0; 7147 #else 7148 retvar->var_val.var_number = -1; 7149 #endif 7150 } 7151 7152 #ifdef FEAT_CLIENTSERVER 7153 static void remote_common __ARGS((VAR argvars, VAR retvar, int expr)); 7154 7155 static void 7156 remote_common(argvars, retvar, expr) 7157 VAR argvars; 7158 VAR retvar; 7159 int expr; 7160 { 7161 char_u *server_name; 7162 char_u *keys; 7163 char_u *r = NULL; 7164 char_u buf[NUMBUFLEN]; 7165 # ifdef WIN32 7166 HWND w; 7167 # else 7168 Window w; 7169 # endif 7170 7171 if (check_restricted() || check_secure()) 7172 return; 7173 7174 # ifdef FEAT_X11 7175 if (check_connection() == FAIL) 7176 return; 7177 # endif 7178 7179 server_name = get_var_string(&argvars[0]); 7180 keys = get_var_string_buf(&argvars[1], buf); 7181 # ifdef WIN32 7182 if (serverSendToVim(server_name, keys, &r, &w, expr, TRUE) < 0) 7183 # else 7184 if (serverSendToVim(X_DISPLAY, server_name, keys, &r, &w, expr, 0, TRUE) 7185 < 0) 7186 # endif 7187 { 7188 if (r != NULL) 7189 EMSG(r); /* sending worked but evaluation failed */ 7190 else 7191 EMSG2(_("E241: Unable to send to %s"), server_name); 7192 return; 7193 } 7194 7195 retvar->var_val.var_string = r; 7196 7197 if (argvars[2].var_type != VAR_UNKNOWN) 7198 { 7199 var v; 7200 char_u str[30]; 7201 7202 sprintf((char *)str, "0x%x", (unsigned int)w); 7203 v.var_type = VAR_STRING; 7204 v.var_val.var_string = vim_strsave(str); 7205 set_var(get_var_string(&argvars[2]), &v); 7206 } 7207 } 7208 #endif 7209 7210 /* 7211 * "remote_expr()" function 7212 */ 7213 /*ARGSUSED*/ 7214 static void 7215 f_remote_expr(argvars, retvar) 7216 VAR argvars; 7217 VAR retvar; 7218 { 7219 retvar->var_type = VAR_STRING; 7220 retvar->var_val.var_string = NULL; 7221 #ifdef FEAT_CLIENTSERVER 7222 remote_common(argvars, retvar, TRUE); 7223 #endif 7224 } 7225 7226 /* 7227 * "remote_send()" function 7228 */ 7229 /*ARGSUSED*/ 7230 static void 7231 f_remote_send(argvars, retvar) 7232 VAR argvars; 7233 VAR retvar; 7234 { 7235 retvar->var_type = VAR_STRING; 7236 retvar->var_val.var_string = NULL; 7237 #ifdef FEAT_CLIENTSERVER 7238 remote_common(argvars, retvar, FALSE); 7239 #endif 7240 } 7241 7242 /* 7243 * "remote_foreground()" function 7244 */ 7245 /*ARGSUSED*/ 7246 static void 7247 f_remote_foreground(argvars, retvar) 7248 VAR argvars; 7249 VAR retvar; 7250 { 7251 retvar->var_val.var_number = 0; 7252 #ifdef FEAT_CLIENTSERVER 7253 # ifdef WIN32 7254 /* On Win32 it's done in this application. */ 7255 serverForeground(get_var_string(&argvars[0])); 7256 # else 7257 /* Send a foreground() expression to the server. */ 7258 argvars[1].var_type = VAR_STRING; 7259 argvars[1].var_val.var_string = vim_strsave((char_u *)"foreground()"); 7260 argvars[2].var_type = VAR_UNKNOWN; 7261 remote_common(argvars, retvar, TRUE); 7262 vim_free(argvars[1].var_val.var_string); 7263 # endif 7264 #endif 7265 } 7266 7267 /* 7268 * "repeat()" function 7269 */ 7270 /*ARGSUSED*/ 7271 static void 7272 f_repeat(argvars, retvar) 7273 VAR argvars; 7274 VAR retvar; 7275 { 7276 char_u *p; 7277 int n; 7278 int slen; 7279 int len; 7280 char_u *r; 7281 int i; 7282 7283 p = get_var_string(&argvars[0]); 7284 n = get_var_number(&argvars[1]); 7285 7286 retvar->var_type = VAR_STRING; 7287 retvar->var_val.var_string = NULL; 7288 7289 slen = (int)STRLEN(p); 7290 len = slen * n; 7291 7292 if (len <= 0) 7293 return; 7294 7295 r = alloc(len + 1); 7296 if (r != NULL) 7297 { 7298 for (i = 0; i < n; i++) 7299 mch_memmove(r + i * slen, p, (size_t)slen); 7300 r[len] = NUL; 7301 } 7302 7303 retvar->var_val.var_string = r; 7304 } 7305 7306 #ifdef HAVE_STRFTIME 7307 /* 7308 * "strftime({format}[, {time}])" function 7309 */ 7310 static void 7311 f_strftime(argvars, retvar) 7312 VAR argvars; 7313 VAR retvar; 7314 { 7315 char_u result_buf[256]; 7316 struct tm *curtime; 7317 time_t seconds; 7318 char_u *p; 7319 7320 retvar->var_type = VAR_STRING; 7321 7322 p = get_var_string(&argvars[0]); 7323 if (argvars[1].var_type == VAR_UNKNOWN) 7324 seconds = time(NULL); 7325 else 7326 seconds = (time_t)get_var_number(&argvars[1]); 7327 curtime = localtime(&seconds); 7328 /* MSVC returns NULL for an invalid value of seconds. */ 7329 if (curtime == NULL) 7330 retvar->var_val.var_string = vim_strsave((char_u *)_("(Invalid)")); 7331 else 7332 { 7333 # ifdef FEAT_MBYTE 7334 vimconv_T conv; 7335 char_u *enc; 7336 7337 conv.vc_type = CONV_NONE; 7338 enc = enc_locale(); 7339 convert_setup(&conv, p_enc, enc); 7340 if (conv.vc_type != CONV_NONE) 7341 p = string_convert(&conv, p, NULL); 7342 # endif 7343 if (p != NULL) 7344 (void)strftime((char *)result_buf, sizeof(result_buf), 7345 (char *)p, curtime); 7346 else 7347 result_buf[0] = NUL; 7348 7349 # ifdef FEAT_MBYTE 7350 if (conv.vc_type != CONV_NONE) 7351 vim_free(p); 7352 convert_setup(&conv, enc, p_enc); 7353 if (conv.vc_type != CONV_NONE) 7354 retvar->var_val.var_string = 7355 string_convert(&conv, result_buf, NULL); 7356 else 7357 # endif 7358 retvar->var_val.var_string = vim_strsave(result_buf); 7359 7360 # ifdef FEAT_MBYTE 7361 /* Release conversion descriptors */ 7362 convert_setup(&conv, NULL, NULL); 7363 vim_free(enc); 7364 # endif 7365 } 7366 } 7367 #endif 7368 7369 /* 7370 * "stridx()" function 7371 */ 7372 static void 7373 f_stridx(argvars, retvar) 7374 VAR argvars; 7375 VAR retvar; 7376 { 7377 char_u buf[NUMBUFLEN]; 7378 char_u *needle; 7379 char_u *haystack; 7380 char_u *pos; 7381 7382 needle = get_var_string(&argvars[1]); 7383 haystack = get_var_string_buf(&argvars[0], buf); 7384 pos = (char_u *)strstr((char *)haystack, (char *)needle); 7385 7386 if (pos == NULL) 7387 retvar->var_val.var_number = -1; 7388 else 7389 retvar->var_val.var_number = (varnumber_T) (pos - haystack); 7390 } 7391 7392 /* 7393 * "strridx()" function 7394 */ 7395 static void 7396 f_strridx(argvars, retvar) 7397 VAR argvars; 7398 VAR retvar; 7399 { 7400 char_u buf[NUMBUFLEN]; 7401 char_u *needle; 7402 char_u *haystack; 7403 char_u *rest; 7404 char_u *lastmatch = NULL; 7405 7406 needle = get_var_string(&argvars[1]); 7407 haystack = get_var_string_buf(&argvars[0], buf); 7408 if (*needle == NUL) 7409 /* Empty string matches past the end. */ 7410 lastmatch = haystack + STRLEN(haystack); 7411 else 7412 for (rest = haystack; *rest != '\0'; ++rest) 7413 { 7414 rest = (char_u *)strstr((char *)rest, (char *)needle); 7415 if (rest == NULL) 7416 break; 7417 lastmatch = rest; 7418 } 7419 7420 if (lastmatch == NULL) 7421 retvar->var_val.var_number = -1; 7422 else 7423 retvar->var_val.var_number = (varnumber_T)(lastmatch - haystack); 7424 } 7425 7426 /* 7427 * "strlen()" function 7428 */ 7429 static void 7430 f_strlen(argvars, retvar) 7431 VAR argvars; 7432 VAR retvar; 7433 { 7434 retvar->var_val.var_number = (varnumber_T) (STRLEN(get_var_string(&argvars[0]))); 7435 } 7436 7437 /* 7438 * "strpart()" function 7439 */ 7440 static void 7441 f_strpart(argvars, retvar) 7442 VAR argvars; 7443 VAR retvar; 7444 { 7445 char_u *p; 7446 int n; 7447 int len; 7448 int slen; 7449 7450 p = get_var_string(&argvars[0]); 7451 slen = (int)STRLEN(p); 7452 7453 n = get_var_number(&argvars[1]); 7454 if (argvars[2].var_type != VAR_UNKNOWN) 7455 len = get_var_number(&argvars[2]); 7456 else 7457 len = slen - n; /* default len: all bytes that are available. */ 7458 7459 /* 7460 * Only return the overlap between the specified part and the actual 7461 * string. 7462 */ 7463 if (n < 0) 7464 { 7465 len += n; 7466 n = 0; 7467 } 7468 else if (n > slen) 7469 n = slen; 7470 if (len < 0) 7471 len = 0; 7472 else if (n + len > slen) 7473 len = slen - n; 7474 7475 retvar->var_type = VAR_STRING; 7476 retvar->var_val.var_string = vim_strnsave(p + n, len); 7477 } 7478 7479 /* 7480 * "strtrans()" function 7481 */ 7482 static void 7483 f_strtrans(argvars, retvar) 7484 VAR argvars; 7485 VAR retvar; 7486 { 7487 retvar->var_type = VAR_STRING; 7488 retvar->var_val.var_string = transstr(get_var_string(&argvars[0])); 7489 } 7490 7491 /* 7492 * "synID(line, col, trans)" function 7493 */ 7494 /*ARGSUSED*/ 7495 static void 7496 f_synID(argvars, retvar) 7497 VAR argvars; 7498 VAR retvar; 7499 { 7500 int id = 0; 7501 #ifdef FEAT_SYN_HL 7502 long line; 7503 long col; 7504 int trans; 7505 7506 line = get_var_lnum(argvars); 7507 col = get_var_number(&argvars[1]) - 1; 7508 trans = get_var_number(&argvars[2]); 7509 7510 if (line >= 1 && line <= curbuf->b_ml.ml_line_count 7511 && col >= 0 && col < (long)STRLEN(ml_get(line))) 7512 id = syn_get_id(line, col, trans); 7513 #endif 7514 7515 retvar->var_val.var_number = id; 7516 } 7517 7518 /* 7519 * "synIDattr(id, what [, mode])" function 7520 */ 7521 /*ARGSUSED*/ 7522 static void 7523 f_synIDattr(argvars, retvar) 7524 VAR argvars; 7525 VAR retvar; 7526 { 7527 char_u *p = NULL; 7528 #ifdef FEAT_SYN_HL 7529 int id; 7530 char_u *what; 7531 char_u *mode; 7532 char_u modebuf[NUMBUFLEN]; 7533 int modec; 7534 7535 id = get_var_number(&argvars[0]); 7536 what = get_var_string(&argvars[1]); 7537 if (argvars[2].var_type != VAR_UNKNOWN) 7538 { 7539 mode = get_var_string_buf(&argvars[2], modebuf); 7540 modec = TOLOWER_ASC(mode[0]); 7541 if (modec != 't' && modec != 'c' 7542 #ifdef FEAT_GUI 7543 && modec != 'g' 7544 #endif 7545 ) 7546 modec = 0; /* replace invalid with current */ 7547 } 7548 else 7549 { 7550 #ifdef FEAT_GUI 7551 if (gui.in_use) 7552 modec = 'g'; 7553 else 7554 #endif 7555 if (t_colors > 1) 7556 modec = 'c'; 7557 else 7558 modec = 't'; 7559 } 7560 7561 7562 switch (TOLOWER_ASC(what[0])) 7563 { 7564 case 'b': 7565 if (TOLOWER_ASC(what[1]) == 'g') /* bg[#] */ 7566 p = highlight_color(id, what, modec); 7567 else /* bold */ 7568 p = highlight_has_attr(id, HL_BOLD, modec); 7569 break; 7570 7571 case 'f': /* fg[#] */ 7572 p = highlight_color(id, what, modec); 7573 break; 7574 7575 case 'i': 7576 if (TOLOWER_ASC(what[1]) == 'n') /* inverse */ 7577 p = highlight_has_attr(id, HL_INVERSE, modec); 7578 else /* italic */ 7579 p = highlight_has_attr(id, HL_ITALIC, modec); 7580 break; 7581 7582 case 'n': /* name */ 7583 p = get_highlight_name(NULL, id - 1); 7584 break; 7585 7586 case 'r': /* reverse */ 7587 p = highlight_has_attr(id, HL_INVERSE, modec); 7588 break; 7589 7590 case 's': /* standout */ 7591 p = highlight_has_attr(id, HL_STANDOUT, modec); 7592 break; 7593 7594 case 'u': /* underline */ 7595 p = highlight_has_attr(id, HL_UNDERLINE, modec); 7596 break; 7597 } 7598 7599 if (p != NULL) 7600 p = vim_strsave(p); 7601 #endif 7602 retvar->var_type = VAR_STRING; 7603 retvar->var_val.var_string = p; 7604 } 7605 7606 /* 7607 * "synIDtrans(id)" function 7608 */ 7609 /*ARGSUSED*/ 7610 static void 7611 f_synIDtrans(argvars, retvar) 7612 VAR argvars; 7613 VAR retvar; 7614 { 7615 int id; 7616 7617 #ifdef FEAT_SYN_HL 7618 id = get_var_number(&argvars[0]); 7619 7620 if (id > 0) 7621 id = syn_get_final_id(id); 7622 else 7623 #endif 7624 id = 0; 7625 7626 retvar->var_val.var_number = id; 7627 } 7628 7629 /* 7630 * "system()" function 7631 */ 7632 static void 7633 f_system(argvars, retvar) 7634 VAR argvars; 7635 VAR retvar; 7636 { 7637 char_u *res = NULL; 7638 char_u *p; 7639 char_u *infile = NULL; 7640 char_u buf[NUMBUFLEN]; 7641 int err = FALSE; 7642 FILE *fd; 7643 7644 if (argvars[1].var_type != VAR_UNKNOWN) 7645 { 7646 /* 7647 * Write the string to a temp file, to be used for input of the shell 7648 * command. 7649 */ 7650 if ((infile = vim_tempname('i')) == NULL) 7651 { 7652 EMSG(_(e_notmp)); 7653 return; 7654 } 7655 7656 fd = mch_fopen((char *)infile, WRITEBIN); 7657 if (fd == NULL) 7658 { 7659 EMSG2(_(e_notopen), infile); 7660 goto done; 7661 } 7662 p = get_var_string_buf(&argvars[1], buf); 7663 if (fwrite(p, STRLEN(p), 1, fd) != 1) 7664 err = TRUE; 7665 if (fclose(fd) != 0) 7666 err = TRUE; 7667 if (err) 7668 { 7669 EMSG(_("E677: Error writing temp file")); 7670 goto done; 7671 } 7672 } 7673 7674 res = get_cmd_output(get_var_string(&argvars[0]), infile, SHELL_SILENT); 7675 7676 #ifdef USE_CR 7677 /* translate <CR> into <NL> */ 7678 if (res != NULL) 7679 { 7680 char_u *s; 7681 7682 for (s = res; *s; ++s) 7683 { 7684 if (*s == CAR) 7685 *s = NL; 7686 } 7687 } 7688 #else 7689 # ifdef USE_CRNL 7690 /* translate <CR><NL> into <NL> */ 7691 if (res != NULL) 7692 { 7693 char_u *s, *d; 7694 7695 d = res; 7696 for (s = res; *s; ++s) 7697 { 7698 if (s[0] == CAR && s[1] == NL) 7699 ++s; 7700 *d++ = *s; 7701 } 7702 *d = NUL; 7703 } 7704 # endif 7705 #endif 7706 7707 done: 7708 if (infile != NULL) 7709 { 7710 mch_remove(infile); 7711 vim_free(infile); 7712 } 7713 retvar->var_type = VAR_STRING; 7714 retvar->var_val.var_string = res; 7715 } 7716 7717 /* 7718 * "submatch()" function 7719 */ 7720 static void 7721 f_submatch(argvars, retvar) 7722 VAR argvars; 7723 VAR retvar; 7724 { 7725 retvar->var_type = VAR_STRING; 7726 retvar->var_val.var_string = reg_submatch((int)get_var_number(&argvars[0])); 7727 } 7728 7729 /* 7730 * "substitute()" function 7731 */ 7732 static void 7733 f_substitute(argvars, retvar) 7734 VAR argvars; 7735 VAR retvar; 7736 { 7737 char_u patbuf[NUMBUFLEN]; 7738 char_u subbuf[NUMBUFLEN]; 7739 char_u flagsbuf[NUMBUFLEN]; 7740 7741 retvar->var_type = VAR_STRING; 7742 retvar->var_val.var_string = do_string_sub( 7743 get_var_string(&argvars[0]), 7744 get_var_string_buf(&argvars[1], patbuf), 7745 get_var_string_buf(&argvars[2], subbuf), 7746 get_var_string_buf(&argvars[3], flagsbuf)); 7747 } 7748 7749 /* 7750 * "tempname()" function 7751 */ 7752 /*ARGSUSED*/ 7753 static void 7754 f_tempname(argvars, retvar) 7755 VAR argvars; 7756 VAR retvar; 7757 { 7758 static int x = 'A'; 7759 7760 retvar->var_type = VAR_STRING; 7761 retvar->var_val.var_string = vim_tempname(x); 7762 7763 /* Advance 'x' to use A-Z and 0-9, so that there are at least 34 different 7764 * names. Skip 'I' and 'O', they are used for shell redirection. */ 7765 do 7766 { 7767 if (x == 'Z') 7768 x = '0'; 7769 else if (x == '9') 7770 x = 'A'; 7771 else 7772 { 7773 #ifdef EBCDIC 7774 if (x == 'I') 7775 x = 'J'; 7776 else if (x == 'R') 7777 x = 'S'; 7778 else 7779 #endif 7780 ++x; 7781 } 7782 } while (x == 'I' || x == 'O'); 7783 } 7784 7785 /* 7786 * "tolower(string)" function 7787 */ 7788 static void 7789 f_tolower(argvars, retvar) 7790 VAR argvars; 7791 VAR retvar; 7792 { 7793 char_u *p; 7794 7795 p = vim_strsave(get_var_string(&argvars[0])); 7796 retvar->var_type = VAR_STRING; 7797 retvar->var_val.var_string = p; 7798 7799 if (p != NULL) 7800 while (*p != NUL) 7801 { 7802 #ifdef FEAT_MBYTE 7803 int l; 7804 7805 if (enc_utf8) 7806 { 7807 int c, lc; 7808 7809 c = utf_ptr2char(p); 7810 lc = utf_tolower(c); 7811 l = utf_ptr2len_check(p); 7812 /* TODO: reallocate string when byte count changes. */ 7813 if (utf_char2len(lc) == l) 7814 utf_char2bytes(lc, p); 7815 p += l; 7816 } 7817 else if (has_mbyte && (l = (*mb_ptr2len_check)(p)) > 1) 7818 p += l; /* skip multi-byte character */ 7819 else 7820 #endif 7821 { 7822 *p = TOLOWER_LOC(*p); /* note that tolower() can be a macro */ 7823 ++p; 7824 } 7825 } 7826 } 7827 7828 /* 7829 * "toupper(string)" function 7830 */ 7831 static void 7832 f_toupper(argvars, retvar) 7833 VAR argvars; 7834 VAR retvar; 7835 { 7836 char_u *p; 7837 7838 p = vim_strsave(get_var_string(&argvars[0])); 7839 retvar->var_type = VAR_STRING; 7840 retvar->var_val.var_string = p; 7841 7842 if (p != NULL) 7843 while (*p != NUL) 7844 { 7845 #ifdef FEAT_MBYTE 7846 int l; 7847 7848 if (enc_utf8) 7849 { 7850 int c, uc; 7851 7852 c = utf_ptr2char(p); 7853 uc = utf_toupper(c); 7854 l = utf_ptr2len_check(p); 7855 /* TODO: reallocate string when byte count changes. */ 7856 if (utf_char2len(uc) == l) 7857 utf_char2bytes(uc, p); 7858 p += l; 7859 } 7860 else if (has_mbyte && (l = (*mb_ptr2len_check)(p)) > 1) 7861 p += l; /* skip multi-byte character */ 7862 else 7863 #endif 7864 { 7865 *p = TOUPPER_LOC(*p); /* note that toupper() can be a macro */ 7866 p++; 7867 } 7868 } 7869 } 7870 7871 /* 7872 * "tr(string, fromstr, tostr)" function 7873 */ 7874 static void 7875 f_tr(argvars, retvar) 7876 VAR argvars; 7877 VAR retvar; 7878 { 7879 char_u *instr; 7880 char_u *fromstr; 7881 char_u *tostr; 7882 char_u *p; 7883 #ifdef FEAT_MBYTE 7884 int inlen; 7885 int fromlen; 7886 int tolen; 7887 int idx; 7888 char_u *cpstr; 7889 int cplen; 7890 int first = TRUE; 7891 #endif 7892 char_u buf[NUMBUFLEN]; 7893 char_u buf2[NUMBUFLEN]; 7894 garray_T ga; 7895 7896 instr = get_var_string(&argvars[0]); 7897 fromstr = get_var_string_buf(&argvars[1], buf); 7898 tostr = get_var_string_buf(&argvars[2], buf2); 7899 7900 /* Default return value: empty string. */ 7901 retvar->var_type = VAR_STRING; 7902 retvar->var_val.var_string = NULL; 7903 ga_init2(&ga, (int)sizeof(char), 80); 7904 7905 #ifdef FEAT_MBYTE 7906 if (!has_mbyte) 7907 #endif 7908 /* not multi-byte: fromstr and tostr must be the same length */ 7909 if (STRLEN(fromstr) != STRLEN(tostr)) 7910 { 7911 #ifdef FEAT_MBYTE 7912 error: 7913 #endif 7914 EMSG2(_(e_invarg2), fromstr); 7915 ga_clear(&ga); 7916 return; 7917 } 7918 7919 /* fromstr and tostr have to contain the same number of chars */ 7920 while (*instr != NUL) 7921 { 7922 #ifdef FEAT_MBYTE 7923 if (has_mbyte) 7924 { 7925 inlen = mb_ptr2len_check(instr); 7926 cpstr = instr; 7927 cplen = inlen; 7928 idx = 0; 7929 for (p = fromstr; *p != NUL; p += fromlen) 7930 { 7931 fromlen = mb_ptr2len_check(p); 7932 if (fromlen == inlen && STRNCMP(instr, p, inlen) == 0) 7933 { 7934 for (p = tostr; *p != NUL; p += tolen) 7935 { 7936 tolen = mb_ptr2len_check(p); 7937 if (idx-- == 0) 7938 { 7939 cplen = tolen; 7940 cpstr = p; 7941 break; 7942 } 7943 } 7944 if (*p == NUL) /* tostr is shorter than fromstr */ 7945 goto error; 7946 break; 7947 } 7948 ++idx; 7949 } 7950 7951 if (first && cpstr == instr) 7952 { 7953 /* Check that fromstr and tostr have the same number of 7954 * (multi-byte) characters. Done only once when a character 7955 * of instr doesn't appear in fromstr. */ 7956 first = FALSE; 7957 for (p = tostr; *p != NUL; p += tolen) 7958 { 7959 tolen = mb_ptr2len_check(p); 7960 --idx; 7961 } 7962 if (idx != 0) 7963 goto error; 7964 } 7965 7966 ga_grow(&ga, cplen); 7967 mch_memmove((char *)ga.ga_data + ga.ga_len, cpstr, (size_t)cplen); 7968 ga.ga_len += cplen; 7969 ga.ga_room -= cplen; 7970 7971 instr += inlen; 7972 } 7973 else 7974 #endif 7975 { 7976 /* When not using multi-byte chars we can do it faster. */ 7977 p = vim_strchr(fromstr, *instr); 7978 if (p != NULL) 7979 ga_append(&ga, tostr[p - fromstr]); 7980 else 7981 ga_append(&ga, *instr); 7982 ++instr; 7983 } 7984 } 7985 7986 retvar->var_val.var_string = ga.ga_data; 7987 } 7988 7989 /* 7990 * "type(expr)" function 7991 */ 7992 static void 7993 f_type(argvars, retvar) 7994 VAR argvars; 7995 VAR retvar; 7996 { 7997 if (argvars[0].var_type == VAR_NUMBER) 7998 retvar->var_val.var_number = 0; 7999 else 8000 retvar->var_val.var_number = 1; 8001 } 8002 8003 /* 8004 * "virtcol(string)" function 8005 */ 8006 static void 8007 f_virtcol(argvars, retvar) 8008 VAR argvars; 8009 VAR retvar; 8010 { 8011 colnr_T vcol = 0; 8012 pos_T *fp; 8013 8014 fp = var2fpos(&argvars[0], FALSE); 8015 if (fp != NULL && fp->lnum <= curbuf->b_ml.ml_line_count) 8016 { 8017 getvvcol(curwin, fp, NULL, NULL, &vcol); 8018 ++vcol; 8019 } 8020 8021 retvar->var_val.var_number = vcol; 8022 } 8023 8024 /* 8025 * "visualmode()" function 8026 */ 8027 /*ARGSUSED*/ 8028 static void 8029 f_visualmode(argvars, retvar) 8030 VAR argvars; 8031 VAR retvar; 8032 { 8033 #ifdef FEAT_VISUAL 8034 char_u str[2]; 8035 8036 retvar->var_type = VAR_STRING; 8037 str[0] = curbuf->b_visual_mode_eval; 8038 str[1] = NUL; 8039 retvar->var_val.var_string = vim_strsave(str); 8040 8041 /* A non-zero number or non-empty string argument: reset mode. */ 8042 if ((argvars[0].var_type == VAR_NUMBER 8043 && argvars[0].var_val.var_number != 0) 8044 || (argvars[0].var_type == VAR_STRING 8045 && *get_var_string(&argvars[0]) != NUL)) 8046 curbuf->b_visual_mode_eval = NUL; 8047 #else 8048 retvar->var_val.var_number = 0; /* return anything, it won't work anyway */ 8049 #endif 8050 } 8051 8052 /* 8053 * "winbufnr(nr)" function 8054 */ 8055 static void 8056 f_winbufnr(argvars, retvar) 8057 VAR argvars; 8058 VAR retvar; 8059 { 8060 win_T *wp; 8061 8062 wp = find_win_by_nr(&argvars[0]); 8063 if (wp == NULL) 8064 retvar->var_val.var_number = -1; 8065 else 8066 retvar->var_val.var_number = wp->w_buffer->b_fnum; 8067 } 8068 8069 /* 8070 * "wincol()" function 8071 */ 8072 /*ARGSUSED*/ 8073 static void 8074 f_wincol(argvars, retvar) 8075 VAR argvars; 8076 VAR retvar; 8077 { 8078 validate_cursor(); 8079 retvar->var_val.var_number = curwin->w_wcol + 1; 8080 } 8081 8082 /* 8083 * "winheight(nr)" function 8084 */ 8085 static void 8086 f_winheight(argvars, retvar) 8087 VAR argvars; 8088 VAR retvar; 8089 { 8090 win_T *wp; 8091 8092 wp = find_win_by_nr(&argvars[0]); 8093 if (wp == NULL) 8094 retvar->var_val.var_number = -1; 8095 else 8096 retvar->var_val.var_number = wp->w_height; 8097 } 8098 8099 /* 8100 * "winline()" function 8101 */ 8102 /*ARGSUSED*/ 8103 static void 8104 f_winline(argvars, retvar) 8105 VAR argvars; 8106 VAR retvar; 8107 { 8108 validate_cursor(); 8109 retvar->var_val.var_number = curwin->w_wrow + 1; 8110 } 8111 8112 /* 8113 * "winnr()" function 8114 */ 8115 /* ARGSUSED */ 8116 static void 8117 f_winnr(argvars, retvar) 8118 VAR argvars; 8119 VAR retvar; 8120 { 8121 int nr = 1; 8122 #ifdef FEAT_WINDOWS 8123 win_T *wp; 8124 win_T *twin = curwin; 8125 char_u *arg; 8126 8127 if (argvars[0].var_type != VAR_UNKNOWN) 8128 { 8129 arg = get_var_string(&argvars[0]); 8130 if (STRCMP(arg, "$") == 0) 8131 twin = lastwin; 8132 else if (STRCMP(arg, "#") == 0) 8133 { 8134 twin = prevwin; 8135 if (prevwin == NULL) 8136 nr = 0; 8137 } 8138 else 8139 { 8140 EMSG2(_(e_invexpr2), arg); 8141 nr = 0; 8142 } 8143 } 8144 8145 if (nr > 0) 8146 for (wp = firstwin; wp != twin; wp = wp->w_next) 8147 ++nr; 8148 #endif 8149 retvar->var_val.var_number = nr; 8150 } 8151 8152 /* 8153 * "winrestcmd()" function 8154 */ 8155 /* ARGSUSED */ 8156 static void 8157 f_winrestcmd(argvars, retvar) 8158 VAR argvars; 8159 VAR retvar; 8160 { 8161 #ifdef FEAT_WINDOWS 8162 win_T *wp; 8163 int winnr = 1; 8164 garray_T ga; 8165 char_u buf[50]; 8166 8167 ga_init2(&ga, (int)sizeof(char), 70); 8168 for (wp = firstwin; wp != NULL; wp = wp->w_next) 8169 { 8170 sprintf((char *)buf, "%dresize %d|", winnr, wp->w_height); 8171 ga_concat(&ga, buf); 8172 # ifdef FEAT_VERTSPLIT 8173 sprintf((char *)buf, "vert %dresize %d|", winnr, wp->w_width); 8174 ga_concat(&ga, buf); 8175 # endif 8176 ++winnr; 8177 } 8178 ga_append(&ga, NUL); 8179 8180 retvar->var_val.var_string = ga.ga_data; 8181 #else 8182 retvar->var_val.var_string = NULL; 8183 #endif 8184 retvar->var_type = VAR_STRING; 8185 } 8186 8187 /* 8188 * "winwidth(nr)" function 8189 */ 8190 static void 8191 f_winwidth(argvars, retvar) 8192 VAR argvars; 8193 VAR retvar; 8194 { 8195 win_T *wp; 8196 8197 wp = find_win_by_nr(&argvars[0]); 8198 if (wp == NULL) 8199 retvar->var_val.var_number = -1; 8200 else 8201 #ifdef FEAT_VERTSPLIT 8202 retvar->var_val.var_number = wp->w_width; 8203 #else 8204 retvar->var_val.var_number = Columns; 8205 #endif 8206 } 8207 8208 static win_T * 8209 find_win_by_nr(vp) 8210 VAR vp; 8211 { 8212 #ifdef FEAT_WINDOWS 8213 win_T *wp; 8214 #endif 8215 int nr; 8216 8217 nr = get_var_number(vp); 8218 8219 #ifdef FEAT_WINDOWS 8220 if (nr == 0) 8221 return curwin; 8222 8223 for (wp = firstwin; wp != NULL; wp = wp->w_next) 8224 if (--nr <= 0) 8225 break; 8226 return wp; 8227 #else 8228 if (nr == 0 || nr == 1) 8229 return curwin; 8230 return NULL; 8231 #endif 8232 } 8233 8234 /* 8235 * Translate a String variable into a position. 8236 */ 8237 static pos_T * 8238 var2fpos(varp, lnum) 8239 VAR varp; 8240 int lnum; /* TRUE when $ is last line */ 8241 { 8242 char_u *name; 8243 static pos_T pos; 8244 pos_T *pp; 8245 8246 name = get_var_string(varp); 8247 if (name[0] == '.') /* cursor */ 8248 return &curwin->w_cursor; 8249 if (name[0] == '\'') /* mark */ 8250 { 8251 pp = getmark(name[1], FALSE); 8252 if (pp == NULL || pp == (pos_T *)-1 || pp->lnum <= 0) 8253 return NULL; 8254 return pp; 8255 } 8256 if (name[0] == '$') /* last column or line */ 8257 { 8258 if (lnum) 8259 { 8260 pos.lnum = curbuf->b_ml.ml_line_count; 8261 pos.col = 0; 8262 } 8263 else 8264 { 8265 pos.lnum = curwin->w_cursor.lnum; 8266 pos.col = (colnr_T)STRLEN(ml_get_curline()); 8267 } 8268 return &pos; 8269 } 8270 return NULL; 8271 } 8272 8273 /* 8274 * Get the length of an environment variable name. 8275 * Advance "arg" to the first character after the name. 8276 * Return 0 for error. 8277 */ 8278 static int 8279 get_env_len(arg) 8280 char_u **arg; 8281 { 8282 char_u *p; 8283 int len; 8284 8285 for (p = *arg; vim_isIDc(*p); ++p) 8286 ; 8287 if (p == *arg) /* no name found */ 8288 return 0; 8289 8290 len = (int)(p - *arg); 8291 *arg = p; 8292 return len; 8293 } 8294 8295 /* 8296 * Get the length of the name of a function or internal variable. 8297 * "arg" is advanced to the first non-white character after the name. 8298 * Return 0 if something is wrong. 8299 */ 8300 static int 8301 get_id_len(arg) 8302 char_u **arg; 8303 { 8304 char_u *p; 8305 int len; 8306 8307 /* Find the end of the name. */ 8308 for (p = *arg; eval_isnamec(*p); ++p) 8309 ; 8310 if (p == *arg) /* no name found */ 8311 return 0; 8312 8313 len = (int)(p - *arg); 8314 *arg = skipwhite(p); 8315 8316 return len; 8317 } 8318 8319 /* 8320 * Get the length of the name of a function. 8321 * "arg" is advanced to the first non-white character after the name. 8322 * Return 0 if something is wrong. 8323 * If the name contains 'magic' {}'s, expand them and return the 8324 * expanded name in an allocated string via 'alias' - caller must free. 8325 */ 8326 static int 8327 get_func_len(arg, alias, evaluate) 8328 char_u **arg; 8329 char_u **alias; 8330 int evaluate; 8331 { 8332 int len; 8333 #ifdef FEAT_MAGIC_BRACES 8334 char_u *p; 8335 char_u *expr_start; 8336 char_u *expr_end; 8337 #endif 8338 8339 *alias = NULL; /* default to no alias */ 8340 8341 if ((*arg)[0] == K_SPECIAL && (*arg)[1] == KS_EXTRA 8342 && (*arg)[2] == (int)KE_SNR) 8343 { 8344 /* hard coded <SNR>, already translated */ 8345 *arg += 3; 8346 return get_id_len(arg) + 3; 8347 } 8348 len = eval_fname_script(*arg); 8349 if (len > 0) 8350 { 8351 /* literal "<SID>", "s:" or "<SNR>" */ 8352 *arg += len; 8353 } 8354 8355 #ifdef FEAT_MAGIC_BRACES 8356 /* 8357 * Find the end of the name; 8358 */ 8359 p = find_name_end(*arg, &expr_start, &expr_end); 8360 /* check for {} construction */ 8361 if (expr_start != NULL) 8362 { 8363 char_u *temp_string; 8364 8365 if (!evaluate) 8366 { 8367 len += (int)(p - *arg); 8368 *arg = skipwhite(p); 8369 return len; 8370 } 8371 8372 /* 8373 * Include any <SID> etc in the expanded string: 8374 * Thus the -len here. 8375 */ 8376 temp_string = make_expanded_name(*arg - len, expr_start, expr_end, p); 8377 if (temp_string == NULL) 8378 return 0; 8379 *alias = temp_string; 8380 *arg = skipwhite(p); 8381 return (int)STRLEN(temp_string); 8382 } 8383 #endif 8384 8385 len += get_id_len(arg); 8386 if (len == 0) 8387 EMSG2(_(e_invexpr2), *arg); 8388 8389 return len; 8390 } 8391 8392 static char_u * 8393 find_name_end(arg, expr_start, expr_end) 8394 char_u *arg; 8395 char_u **expr_start; 8396 char_u **expr_end; 8397 { 8398 int nesting = 0; 8399 char_u *p; 8400 8401 *expr_start = NULL; 8402 *expr_end = NULL; 8403 8404 for (p = arg; (*p != NUL && (eval_isnamec(*p) || nesting != 0)); ++p) 8405 { 8406 #ifdef FEAT_MAGIC_BRACES 8407 if (*p == '{') 8408 { 8409 nesting++; 8410 if (*expr_start == NULL) 8411 *expr_start = p; 8412 } 8413 else if (*p == '}') 8414 { 8415 nesting--; 8416 if (nesting == 0 && *expr_end == NULL) 8417 *expr_end = p; 8418 } 8419 #endif 8420 } 8421 8422 return p; 8423 } 8424 8425 /* 8426 * Return TRUE if character "c" can be used in a variable or function name. 8427 */ 8428 static int 8429 eval_isnamec(c) 8430 int c; 8431 { 8432 return (ASCII_ISALNUM(c) || c == '_' || c == ':' 8433 #ifdef FEAT_MAGIC_BRACES 8434 || c == '{' || c == '}' 8435 #endif 8436 ); 8437 } 8438 8439 /* 8440 * Find a v: variable. 8441 * Return it's index, or -1 if not found. 8442 */ 8443 static int 8444 find_vim_var(name, len) 8445 char_u *name; 8446 int len; /* length of "name" */ 8447 { 8448 char_u *vname; 8449 int vlen; 8450 int i; 8451 8452 /* 8453 * Ignore "v:" for old built-in variables, require it for new ones. 8454 */ 8455 if (name[0] == 'v' && name[1] == ':') 8456 { 8457 vname = name + 2; 8458 vlen = len - 2; 8459 } 8460 else 8461 { 8462 vname = name; 8463 vlen = len; 8464 } 8465 for (i = 0; i < VV_LEN; ++i) 8466 if (vlen == vimvars[i].len && STRCMP(vname, vimvars[i].name) == 0 8467 && ((vimvars[i].flags & VV_COMPAT) || vname != name)) 8468 return i; 8469 return -1; 8470 } 8471 8472 /* 8473 * Set number v: variable to "val". 8474 */ 8475 void 8476 set_vim_var_nr(idx, val) 8477 int idx; 8478 long val; 8479 { 8480 vimvars[idx].val = (char_u *)val; 8481 } 8482 8483 /* 8484 * Get number v: variable value; 8485 */ 8486 long 8487 get_vim_var_nr(idx) 8488 int idx; 8489 { 8490 return (long)vimvars[idx].val; 8491 } 8492 8493 /* 8494 * Set v:count, v:count1 and v:prevcount. 8495 */ 8496 void 8497 set_vcount(count, count1) 8498 long count; 8499 long count1; 8500 { 8501 vimvars[VV_PREVCOUNT].val = vimvars[VV_COUNT].val; 8502 vimvars[VV_COUNT].val = (char_u *)count; 8503 vimvars[VV_COUNT1].val = (char_u *)count1; 8504 } 8505 8506 /* 8507 * Set string v: variable to a copy of "val". 8508 */ 8509 void 8510 set_vim_var_string(idx, val, len) 8511 int idx; 8512 char_u *val; 8513 int len; /* length of "val" to use or -1 (whole string) */ 8514 { 8515 vim_free(vimvars[idx].val); 8516 if (val == NULL) 8517 vimvars[idx].val = NULL; 8518 else if (len == -1) 8519 vimvars[idx].val = vim_strsave(val); 8520 else 8521 vimvars[idx].val = vim_strnsave(val, len); 8522 } 8523 8524 /* 8525 * Set v:register if needed. 8526 */ 8527 void 8528 set_reg_var(c) 8529 int c; 8530 { 8531 char_u regname; 8532 8533 if (c == 0 || c == ' ') 8534 regname = '"'; 8535 else 8536 regname = c; 8537 /* Avoid free/alloc when the value is already right. */ 8538 if (vimvars[VV_REG].val == NULL || vimvars[VV_REG].val[0] != c) 8539 set_vim_var_string(VV_REG, ®name, 1); 8540 } 8541 8542 /* 8543 * Get or set v:exception. If "oldval" == NULL, return the current value. 8544 * Otherwise, restore the value to "oldval" and return NULL. 8545 * Must always be called in pairs to save and restore v:exception! Does not 8546 * take care of memory allocations. 8547 */ 8548 char_u * 8549 v_exception(oldval) 8550 char_u *oldval; 8551 { 8552 if (oldval == NULL) 8553 return vimvars[VV_EXCEPTION].val; 8554 8555 vimvars[VV_EXCEPTION].val = oldval; 8556 return NULL; 8557 } 8558 8559 /* 8560 * Get or set v:throwpoint. If "oldval" == NULL, return the current value. 8561 * Otherwise, restore the value to "oldval" and return NULL. 8562 * Must always be called in pairs to save and restore v:throwpoint! Does not 8563 * take care of memory allocations. 8564 */ 8565 char_u * 8566 v_throwpoint(oldval) 8567 char_u *oldval; 8568 { 8569 if (oldval == NULL) 8570 return vimvars[VV_THROWPOINT].val; 8571 8572 vimvars[VV_THROWPOINT].val = oldval; 8573 return NULL; 8574 } 8575 8576 #if defined(FEAT_AUTOCMD) || defined(PROTO) 8577 /* 8578 * Set v:cmdarg. 8579 * If "eap" != NULL, use "eap" to generate the value and return the old value. 8580 * If "oldarg" != NULL, restore the value to "oldarg" and return NULL. 8581 * Must always be called in pairs! 8582 */ 8583 char_u * 8584 set_cmdarg(eap, oldarg) 8585 exarg_T *eap; 8586 char_u *oldarg; 8587 { 8588 char_u *oldval; 8589 char_u *newval; 8590 unsigned len; 8591 8592 oldval = vimvars[VV_CMDARG].val; 8593 if (eap == NULL) 8594 { 8595 vim_free(oldval); 8596 vimvars[VV_CMDARG].val = oldarg; 8597 return NULL; 8598 } 8599 8600 if (eap->force_bin == FORCE_BIN) 8601 len = 6; 8602 else if (eap->force_bin == FORCE_NOBIN) 8603 len = 8; 8604 else 8605 len = 0; 8606 if (eap->force_ff != 0) 8607 len += (unsigned)STRLEN(eap->cmd + eap->force_ff) + 6; 8608 # ifdef FEAT_MBYTE 8609 if (eap->force_enc != 0) 8610 len += (unsigned)STRLEN(eap->cmd + eap->force_enc) + 7; 8611 # endif 8612 8613 newval = alloc(len + 1); 8614 if (newval == NULL) 8615 return NULL; 8616 8617 if (eap->force_bin == FORCE_BIN) 8618 sprintf((char *)newval, " ++bin"); 8619 else if (eap->force_bin == FORCE_NOBIN) 8620 sprintf((char *)newval, " ++nobin"); 8621 else 8622 *newval = NUL; 8623 if (eap->force_ff != 0) 8624 sprintf((char *)newval + STRLEN(newval), " ++ff=%s", 8625 eap->cmd + eap->force_ff); 8626 # ifdef FEAT_MBYTE 8627 if (eap->force_enc != 0) 8628 sprintf((char *)newval + STRLEN(newval), " ++enc=%s", 8629 eap->cmd + eap->force_enc); 8630 # endif 8631 vimvars[VV_CMDARG].val = newval; 8632 return oldval; 8633 } 8634 #endif 8635 8636 /* 8637 * Get the value of internal variable "name". 8638 * Return OK or FAIL. 8639 */ 8640 static int 8641 get_var_var(name, len, retvar) 8642 char_u *name; 8643 int len; /* length of "name" */ 8644 VAR retvar; /* NULL when only checking existence */ 8645 { 8646 int ret = OK; 8647 int type = VAR_UNKNOWN; 8648 long number = 1; 8649 char_u *string = NULL; 8650 VAR v; 8651 int cc; 8652 int i; 8653 8654 /* truncate the name, so that we can use strcmp() */ 8655 cc = name[len]; 8656 name[len] = NUL; 8657 8658 /* 8659 * Check for "b:changedtick". 8660 */ 8661 if (STRCMP(name, "b:changedtick") == 0) 8662 { 8663 type = VAR_NUMBER; 8664 number = curbuf->b_changedtick; 8665 } 8666 8667 /* 8668 * Check for built-in v: variables. 8669 */ 8670 else if ((i = find_vim_var(name, len)) >= 0) 8671 { 8672 type = vimvars[i].type; 8673 number = (long)vimvars[i].val; 8674 string = vimvars[i].val; 8675 } 8676 8677 /* 8678 * Check for user-defined variables. 8679 */ 8680 else 8681 { 8682 v = find_var(name, FALSE); 8683 if (v != NULL) 8684 { 8685 type = v->var_type; 8686 number = v->var_val.var_number; 8687 string = v->var_val.var_string; 8688 } 8689 } 8690 8691 if (type == VAR_UNKNOWN) 8692 { 8693 if (retvar != NULL) 8694 EMSG2(_("E121: Undefined variable: %s"), name); 8695 ret = FAIL; 8696 } 8697 else if (retvar != NULL) 8698 { 8699 retvar->var_type = type; 8700 if (type == VAR_NUMBER) 8701 retvar->var_val.var_number = number; 8702 else if (type == VAR_STRING) 8703 { 8704 if (string != NULL) 8705 string = vim_strsave(string); 8706 retvar->var_val.var_string = string; 8707 } 8708 } 8709 8710 name[len] = cc; 8711 8712 return ret; 8713 } 8714 8715 /* 8716 * Allocate memory for a variable, and make it emtpy (0 or NULL value). 8717 */ 8718 static VAR 8719 alloc_var() 8720 { 8721 return (VAR)alloc_clear((unsigned)sizeof(var)); 8722 } 8723 8724 /* 8725 * Allocate memory for a variable, and assign a string to it. 8726 * The string "s" must have been allocated, it is consumed. 8727 * Return NULL for out of memory, the variable otherwise. 8728 */ 8729 static VAR 8730 alloc_string_var(s) 8731 char_u *s; 8732 { 8733 VAR retvar; 8734 8735 retvar = alloc_var(); 8736 if (retvar != NULL) 8737 { 8738 retvar->var_type = VAR_STRING; 8739 retvar->var_val.var_string = s; 8740 } 8741 else 8742 vim_free(s); 8743 return retvar; 8744 } 8745 8746 /* 8747 * Free the memory for a variable. 8748 */ 8749 static void 8750 free_var(varp) 8751 VAR varp; 8752 { 8753 if (varp != NULL) 8754 { 8755 if (varp->var_type == VAR_STRING) 8756 vim_free(varp->var_val.var_string); 8757 vim_free(varp->var_name); 8758 vim_free(varp); 8759 } 8760 } 8761 8762 /* 8763 * Free the memory for a variable value and set the value to NULL or 0. 8764 */ 8765 static void 8766 clear_var(varp) 8767 VAR varp; 8768 { 8769 if (varp != NULL) 8770 { 8771 if (varp->var_type == VAR_STRING) 8772 { 8773 vim_free(varp->var_val.var_string); 8774 varp->var_val.var_string = NULL; 8775 } 8776 else 8777 varp->var_val.var_number = 0; 8778 } 8779 } 8780 8781 /* 8782 * Get the number value of a variable. 8783 * If it is a String variable, uses vim_str2nr(). 8784 */ 8785 static long 8786 get_var_number(varp) 8787 VAR varp; 8788 { 8789 long n; 8790 8791 if (varp->var_type == VAR_NUMBER) 8792 return (long)(varp->var_val.var_number); 8793 else if (varp->var_type == VAR_UNKNOWN || varp->var_val.var_string == NULL) 8794 return 0L; 8795 else 8796 { 8797 vim_str2nr(varp->var_val.var_string, NULL, NULL, TRUE, TRUE, &n, NULL); 8798 return n; 8799 } 8800 } 8801 8802 /* 8803 * Get the lnum from the first argument. Also accepts ".", "$", etc. 8804 */ 8805 static linenr_T 8806 get_var_lnum(argvars) 8807 VAR argvars; 8808 { 8809 var retvar; 8810 linenr_T lnum; 8811 8812 lnum = get_var_number(&argvars[0]); 8813 if (lnum == 0) /* no valid number, try using line() */ 8814 { 8815 retvar.var_type = VAR_NUMBER; 8816 f_line(argvars, &retvar); 8817 lnum = retvar.var_val.var_number; 8818 clear_var(&retvar); 8819 } 8820 return lnum; 8821 } 8822 8823 /* 8824 * Get the string value of a variable. 8825 * If it is a Number variable, the number is converted into a string. 8826 * get_var_string() uses a single, static buffer. YOU CAN ONLY USE IT ONCE! 8827 * get_var_string_buf() uses a given buffer. 8828 * If the String variable has never been set, return an empty string. 8829 * Never returns NULL; 8830 */ 8831 static char_u * 8832 get_var_string(varp) 8833 VAR varp; 8834 { 8835 static char_u mybuf[NUMBUFLEN]; 8836 8837 return get_var_string_buf(varp, mybuf); 8838 } 8839 8840 static char_u * 8841 get_var_string_buf(varp, buf) 8842 VAR varp; 8843 char_u *buf; 8844 { 8845 if (varp->var_type == VAR_NUMBER) 8846 { 8847 sprintf((char *)buf, "%ld", (long)varp->var_val.var_number); 8848 return buf; 8849 } 8850 else if (varp->var_val.var_string == NULL) 8851 return (char_u *)""; 8852 else 8853 return varp->var_val.var_string; 8854 } 8855 8856 /* 8857 * Find variable "name" in the list of variables. 8858 * Return a pointer to it if found, NULL if not found. 8859 */ 8860 static VAR 8861 find_var(name, writing) 8862 char_u *name; 8863 int writing; 8864 { 8865 int i; 8866 char_u *varname; 8867 garray_T *gap; 8868 8869 /* Check for function arguments "a:" */ 8870 if (name[0] == 'a' && name[1] == ':') 8871 { 8872 if (writing) 8873 { 8874 EMSG2(_(e_readonlyvar), name); 8875 return NULL; 8876 } 8877 name += 2; 8878 if (current_funccal == NULL) 8879 return NULL; 8880 if (VIM_ISDIGIT(*name)) 8881 { 8882 i = atol((char *)name); 8883 if (i == 0) /* a:0 */ 8884 return ¤t_funccal->a0_var; 8885 i += current_funccal->func->args.ga_len; 8886 if (i > current_funccal->argcount) /* a:999 */ 8887 return NULL; 8888 return &(current_funccal->argvars[i - 1]); /* a:1, a:2, etc. */ 8889 } 8890 if (STRCMP(name, "firstline") == 0) 8891 return &(current_funccal->firstline); 8892 if (STRCMP(name, "lastline") == 0) 8893 return &(current_funccal->lastline); 8894 for (i = 0; i < current_funccal->func->args.ga_len; ++i) 8895 if (STRCMP(name, ((char_u **) 8896 (current_funccal->func->args.ga_data))[i]) == 0) 8897 return &(current_funccal->argvars[i]); /* a:name */ 8898 return NULL; 8899 } 8900 8901 gap = find_var_ga(name, &varname); 8902 if (gap == NULL) 8903 return NULL; 8904 return find_var_in_ga(gap, varname); 8905 } 8906 8907 static VAR 8908 find_var_in_ga(gap, varname) 8909 garray_T *gap; 8910 char_u *varname; 8911 { 8912 int i; 8913 8914 for (i = gap->ga_len; --i >= 0; ) 8915 if (VAR_GAP_ENTRY(i, gap).var_name != NULL 8916 && STRCMP(VAR_GAP_ENTRY(i, gap).var_name, varname) == 0) 8917 break; 8918 if (i < 0) 8919 return NULL; 8920 return &VAR_GAP_ENTRY(i, gap); 8921 } 8922 8923 /* 8924 * Find the growarray and start of name without ':' for a variable name. 8925 */ 8926 static garray_T * 8927 find_var_ga(name, varname) 8928 char_u *name; 8929 char_u **varname; 8930 { 8931 if (name[1] != ':') 8932 { 8933 /* If not "x:name" there must not be any ":" in the name. */ 8934 if (vim_strchr(name, ':') != NULL) 8935 return NULL; 8936 *varname = name; 8937 if (current_funccal == NULL) 8938 return &variables; /* global variable */ 8939 return ¤t_funccal->l_vars; /* local function variable */ 8940 } 8941 *varname = name + 2; 8942 if (*name == 'b') /* buffer variable */ 8943 return &curbuf->b_vars; 8944 if (*name == 'w') /* window variable */ 8945 return &curwin->w_vars; 8946 if (*name == 'g') /* global variable */ 8947 return &variables; 8948 if (*name == 'l' && current_funccal != NULL)/* local function variable */ 8949 return ¤t_funccal->l_vars; 8950 if (*name == 's' /* script variable */ 8951 && current_SID > 0 && current_SID <= ga_scripts.ga_len) 8952 return &SCRIPT_VARS(current_SID); 8953 return NULL; 8954 } 8955 8956 /* 8957 * Get the string value of a (global/local) variable. 8958 * Returns NULL when it doesn't exist. 8959 */ 8960 char_u * 8961 get_var_value(name) 8962 char_u *name; 8963 { 8964 VAR v; 8965 8966 v = find_var(name, FALSE); 8967 if (v == NULL) 8968 return NULL; 8969 return get_var_string(v); 8970 } 8971 8972 /* 8973 * Allocate a new growarry for a sourced script. It will be used while 8974 * sourcing this script and when executing functions defined in the script. 8975 */ 8976 void 8977 new_script_vars(id) 8978 scid_T id; 8979 { 8980 if (ga_grow(&ga_scripts, (int)(id - ga_scripts.ga_len)) == OK) 8981 { 8982 while (ga_scripts.ga_len < id) 8983 { 8984 var_init(&SCRIPT_VARS(ga_scripts.ga_len + 1)); 8985 ++ga_scripts.ga_len; 8986 --ga_scripts.ga_room; 8987 } 8988 } 8989 } 8990 8991 /* 8992 * Initialize internal variables for use. 8993 */ 8994 void 8995 var_init(gap) 8996 garray_T *gap; 8997 { 8998 ga_init2(gap, (int)sizeof(var), 4); 8999 } 9000 9001 /* 9002 * Clean up a list of internal variables. 9003 */ 9004 void 9005 var_clear(gap) 9006 garray_T *gap; 9007 { 9008 int i; 9009 9010 for (i = gap->ga_len; --i >= 0; ) 9011 var_free_one(&VAR_GAP_ENTRY(i, gap)); 9012 ga_clear(gap); 9013 } 9014 9015 static void 9016 var_free_one(v) 9017 VAR v; 9018 { 9019 vim_free(v->var_name); 9020 v->var_name = NULL; 9021 if (v->var_type == VAR_STRING) 9022 vim_free(v->var_val.var_string); 9023 v->var_val.var_string = NULL; 9024 } 9025 9026 /* 9027 * List the value of one internal variable. 9028 */ 9029 static void 9030 list_one_var(v, prefix) 9031 VAR v; 9032 char_u *prefix; 9033 { 9034 list_one_var_a(prefix, v->var_name, v->var_type, get_var_string(v)); 9035 } 9036 9037 /* 9038 * List the value of one "v:" variable. 9039 */ 9040 static void 9041 list_vim_var(i) 9042 int i; /* index in vimvars[] */ 9043 { 9044 char_u *p; 9045 char_u numbuf[NUMBUFLEN]; 9046 9047 if (vimvars[i].type == VAR_NUMBER) 9048 { 9049 p = numbuf; 9050 sprintf((char *)p, "%ld", (long)vimvars[i].val); 9051 } 9052 else if (vimvars[i].val == NULL) 9053 p = (char_u *)""; 9054 else 9055 p = vimvars[i].val; 9056 list_one_var_a((char_u *)"v:", (char_u *)vimvars[i].name, 9057 vimvars[i].type, p); 9058 } 9059 9060 static void 9061 list_one_var_a(prefix, name, type, string) 9062 char_u *prefix; 9063 char_u *name; 9064 int type; 9065 char_u *string; 9066 { 9067 msg_attr(prefix, 0); /* don't use msg(), it overwrites "v:statusmsg" */ 9068 if (name != NULL) /* "a:" vars don't have a name stored */ 9069 msg_puts(name); 9070 msg_putchar(' '); 9071 msg_advance(22); 9072 if (type == VAR_NUMBER) 9073 msg_putchar('#'); 9074 else 9075 msg_putchar(' '); 9076 msg_outtrans(string); 9077 } 9078 9079 /* 9080 * Set variable "name" to value in "varp". 9081 * If the variable already exists, the value is updated. 9082 * Otherwise the variable is created. 9083 */ 9084 static void 9085 set_var(name, varp) 9086 char_u *name; 9087 VAR varp; 9088 { 9089 int i; 9090 VAR v; 9091 char_u *varname; 9092 garray_T *gap; 9093 9094 /* 9095 * Handle setting internal v: variables. 9096 */ 9097 i = find_vim_var(name, (int)STRLEN(name)); 9098 if (i >= 0) 9099 { 9100 if (vimvars[i].flags & VV_RO) 9101 EMSG2(_(e_readonlyvar), name); 9102 else if ((vimvars[i].flags & VV_RO_SBX) && sandbox) 9103 EMSG2(_(e_readonlysbx), name); 9104 else 9105 { 9106 if (vimvars[i].type == VAR_STRING) 9107 { 9108 vim_free(vimvars[i].val); 9109 vimvars[i].val = vim_strsave(get_var_string(varp)); 9110 } 9111 else 9112 vimvars[i].val = (char_u *)(long)varp->var_val.var_number; 9113 } 9114 return; 9115 } 9116 9117 v = find_var(name, TRUE); 9118 if (v != NULL) /* existing variable, only need to free string */ 9119 { 9120 if (v->var_type == VAR_STRING) 9121 vim_free(v->var_val.var_string); 9122 } 9123 else /* add a new variable */ 9124 { 9125 gap = find_var_ga(name, &varname); 9126 if (gap == NULL) /* illegal name */ 9127 { 9128 EMSG2(_("E461: Illegal variable name: %s"), name); 9129 return; 9130 } 9131 9132 /* Try to use an empty entry */ 9133 for (i = gap->ga_len; --i >= 0; ) 9134 if (VAR_GAP_ENTRY(i, gap).var_name == NULL) 9135 break; 9136 if (i < 0) /* need to allocate more room */ 9137 { 9138 if (ga_grow(gap, 1) == FAIL) 9139 return; 9140 i = gap->ga_len; 9141 } 9142 v = &VAR_GAP_ENTRY(i, gap); 9143 if ((v->var_name = vim_strsave(varname)) == NULL) 9144 return; 9145 if (i == gap->ga_len) 9146 { 9147 ++gap->ga_len; 9148 --gap->ga_room; 9149 } 9150 } 9151 copy_var(varp, v); 9152 } 9153 9154 static void 9155 copy_var(from, to) 9156 VAR from; 9157 VAR to; 9158 { 9159 to->var_type = from->var_type; 9160 if (from->var_type == VAR_STRING) 9161 to->var_val.var_string = vim_strsave(get_var_string(from)); 9162 else 9163 to->var_val.var_number = from->var_val.var_number; 9164 } 9165 9166 /* 9167 * ":echo expr1 ..." print each argument separated with a space, add a 9168 * newline at the end. 9169 * ":echon expr1 ..." print each argument plain. 9170 */ 9171 void 9172 ex_echo(eap) 9173 exarg_T *eap; 9174 { 9175 char_u *arg = eap->arg; 9176 var retvar; 9177 char_u *p; 9178 int needclr = TRUE; 9179 int atstart = TRUE; 9180 9181 if (eap->skip) 9182 ++emsg_skip; 9183 while (*arg != NUL && *arg != '|' && *arg != '\n' && !got_int) 9184 { 9185 p = arg; 9186 if (eval1(&arg, &retvar, !eap->skip) == FAIL) 9187 { 9188 /* 9189 * Report the invalid expression unless the expression evaluation 9190 * has been cancelled due to an aborting error, an interrupt, or an 9191 * exception. 9192 */ 9193 if (!aborting()) 9194 EMSG2(_(e_invexpr2), p); 9195 break; 9196 } 9197 if (!eap->skip) 9198 { 9199 if (atstart) 9200 { 9201 atstart = FALSE; 9202 /* Call msg_start() after eval1(), evaluating the expression 9203 * may cause a message to appear. */ 9204 if (eap->cmdidx == CMD_echo) 9205 msg_start(); 9206 } 9207 else if (eap->cmdidx == CMD_echo) 9208 msg_puts_attr((char_u *)" ", echo_attr); 9209 for (p = get_var_string(&retvar); *p != NUL && !got_int; ++p) 9210 if (*p == '\n' || *p == '\r' || *p == TAB) 9211 { 9212 if (*p != TAB && needclr) 9213 { 9214 /* remove any text still there from the command */ 9215 msg_clr_eos(); 9216 needclr = FALSE; 9217 } 9218 msg_putchar_attr(*p, echo_attr); 9219 } 9220 else 9221 { 9222 #ifdef FEAT_MBYTE 9223 if (has_mbyte) 9224 { 9225 int i = (*mb_ptr2len_check)(p); 9226 9227 (void)msg_outtrans_len_attr(p, i, echo_attr); 9228 p += i - 1; 9229 } 9230 else 9231 #endif 9232 (void)msg_outtrans_len_attr(p, 1, echo_attr); 9233 } 9234 } 9235 clear_var(&retvar); 9236 arg = skipwhite(arg); 9237 } 9238 eap->nextcmd = check_nextcmd(arg); 9239 9240 if (eap->skip) 9241 --emsg_skip; 9242 else 9243 { 9244 /* remove text that may still be there from the command */ 9245 if (needclr) 9246 msg_clr_eos(); 9247 if (eap->cmdidx == CMD_echo) 9248 msg_end(); 9249 } 9250 } 9251 9252 /* 9253 * ":echohl {name}". 9254 */ 9255 void 9256 ex_echohl(eap) 9257 exarg_T *eap; 9258 { 9259 int id; 9260 9261 id = syn_name2id(eap->arg); 9262 if (id == 0) 9263 echo_attr = 0; 9264 else 9265 echo_attr = syn_id2attr(id); 9266 } 9267 9268 /* 9269 * ":execute expr1 ..." execute the result of an expression. 9270 * ":echomsg expr1 ..." Print a message 9271 * ":echoerr expr1 ..." Print an error 9272 * Each gets spaces around each argument and a newline at the end for 9273 * echo commands 9274 */ 9275 void 9276 ex_execute(eap) 9277 exarg_T *eap; 9278 { 9279 char_u *arg = eap->arg; 9280 var retvar; 9281 int ret = OK; 9282 char_u *p; 9283 garray_T ga; 9284 int len; 9285 int save_did_emsg; 9286 9287 ga_init2(&ga, 1, 80); 9288 9289 if (eap->skip) 9290 ++emsg_skip; 9291 while (*arg != NUL && *arg != '|' && *arg != '\n') 9292 { 9293 p = arg; 9294 if (eval1(&arg, &retvar, !eap->skip) == FAIL) 9295 { 9296 /* 9297 * Report the invalid expression unless the expression evaluation 9298 * has been cancelled due to an aborting error, an interrupt, or an 9299 * exception. 9300 */ 9301 if (!aborting()) 9302 EMSG2(_(e_invexpr2), p); 9303 ret = FAIL; 9304 break; 9305 } 9306 9307 if (!eap->skip) 9308 { 9309 p = get_var_string(&retvar); 9310 len = (int)STRLEN(p); 9311 if (ga_grow(&ga, len + 2) == FAIL) 9312 { 9313 clear_var(&retvar); 9314 ret = FAIL; 9315 break; 9316 } 9317 if (ga.ga_len) 9318 { 9319 ((char_u *)(ga.ga_data))[ga.ga_len++] = ' '; 9320 --ga.ga_room; 9321 } 9322 STRCPY((char_u *)(ga.ga_data) + ga.ga_len, p); 9323 ga.ga_room -= len; 9324 ga.ga_len += len; 9325 } 9326 9327 clear_var(&retvar); 9328 arg = skipwhite(arg); 9329 } 9330 9331 if (ret != FAIL && ga.ga_data != NULL) 9332 { 9333 if (eap->cmdidx == CMD_echomsg) 9334 MSG_ATTR(ga.ga_data, echo_attr); 9335 else if (eap->cmdidx == CMD_echoerr) 9336 { 9337 /* We don't want to abort following commands, restore did_emsg. */ 9338 save_did_emsg = did_emsg; 9339 EMSG((char_u *)ga.ga_data); 9340 if (!force_abort) 9341 did_emsg = save_did_emsg; 9342 } 9343 else if (eap->cmdidx == CMD_execute) 9344 do_cmdline((char_u *)ga.ga_data, 9345 eap->getline, eap->cookie, DOCMD_NOWAIT|DOCMD_VERBOSE); 9346 } 9347 9348 ga_clear(&ga); 9349 9350 if (eap->skip) 9351 --emsg_skip; 9352 9353 eap->nextcmd = check_nextcmd(arg); 9354 } 9355 9356 /* 9357 * Skip over the name of an option: "&option", "&g:option" or "&l:option". 9358 * "arg" points to the "&" or '+' when called, to "option" when returning. 9359 * Returns NULL when no option name found. Otherwise pointer to the char 9360 * after the option name. 9361 */ 9362 static char_u * 9363 find_option_end(arg, opt_flags) 9364 char_u **arg; 9365 int *opt_flags; 9366 { 9367 char_u *p = *arg; 9368 9369 ++p; 9370 if (*p == 'g' && p[1] == ':') 9371 { 9372 *opt_flags = OPT_GLOBAL; 9373 p += 2; 9374 } 9375 else if (*p == 'l' && p[1] == ':') 9376 { 9377 *opt_flags = OPT_LOCAL; 9378 p += 2; 9379 } 9380 else 9381 *opt_flags = 0; 9382 9383 if (!ASCII_ISALPHA(*p)) 9384 return NULL; 9385 *arg = p; 9386 9387 if (p[0] == 't' && p[1] == '_' && p[2] != NUL && p[3] != NUL) 9388 p += 4; /* termcap option */ 9389 else 9390 while (ASCII_ISALPHA(*p)) 9391 ++p; 9392 return p; 9393 } 9394 9395 /* 9396 * ":function" 9397 */ 9398 void 9399 ex_function(eap) 9400 exarg_T *eap; 9401 { 9402 char_u *theline; 9403 int j; 9404 int c; 9405 #ifdef FEAT_MAGIC_BRACES 9406 int saved_did_emsg; 9407 #endif 9408 char_u *name = NULL; 9409 char_u *p; 9410 char_u *arg; 9411 garray_T newargs; 9412 garray_T newlines; 9413 int varargs = FALSE; 9414 int mustend = FALSE; 9415 int flags = 0; 9416 ufunc_T *fp; 9417 int indent; 9418 int nesting; 9419 char_u *skip_until = NULL; 9420 static char_u e_funcexts[] = N_("E122: Function %s already exists, add ! to replace it"); 9421 9422 /* 9423 * ":function" without argument: list functions. 9424 */ 9425 if (ends_excmd(*eap->arg)) 9426 { 9427 if (!eap->skip) 9428 for (fp = firstfunc; fp != NULL && !got_int; fp = fp->next) 9429 list_func_head(fp, FALSE); 9430 eap->nextcmd = check_nextcmd(eap->arg); 9431 return; 9432 } 9433 9434 p = eap->arg; 9435 name = trans_function_name(&p, eap->skip, FALSE); 9436 if (name == NULL && !eap->skip) 9437 { 9438 /* 9439 * Return on an invalid expression in braces, unless the expression 9440 * evaluation has been cancelled due to an aborting error, an 9441 * interrupt, or an exception. 9442 */ 9443 if (!aborting()) 9444 return; 9445 else 9446 eap->skip = TRUE; 9447 } 9448 #ifdef FEAT_MAGIC_BRACES 9449 /* An error in a function call during evaluation of an expression in magic 9450 * braces should not cause the function not to be defined. */ 9451 saved_did_emsg = did_emsg; 9452 did_emsg = FALSE; 9453 #endif 9454 9455 /* 9456 * ":function func" with only function name: list function. 9457 */ 9458 if (vim_strchr(p, '(') == NULL) 9459 { 9460 if (!ends_excmd(*skipwhite(p))) 9461 { 9462 EMSG(_(e_trailing)); 9463 goto erret_name; 9464 } 9465 eap->nextcmd = check_nextcmd(p); 9466 if (eap->nextcmd != NULL) 9467 *p = NUL; 9468 if (!eap->skip && !got_int) 9469 { 9470 fp = find_func(name); 9471 if (fp != NULL) 9472 { 9473 list_func_head(fp, TRUE); 9474 for (j = 0; j < fp->lines.ga_len && !got_int; ++j) 9475 { 9476 msg_putchar('\n'); 9477 msg_outnum((long)(j + 1)); 9478 if (j < 9) 9479 msg_putchar(' '); 9480 if (j < 99) 9481 msg_putchar(' '); 9482 msg_prt_line(FUNCLINE(fp, j)); 9483 out_flush(); /* show a line at a time */ 9484 ui_breakcheck(); 9485 } 9486 if (!got_int) 9487 { 9488 msg_putchar('\n'); 9489 msg_puts((char_u *)" endfunction"); 9490 } 9491 } 9492 else 9493 EMSG2(_("E123: Undefined function: %s"), eap->arg); 9494 } 9495 goto erret_name; 9496 } 9497 9498 /* 9499 * ":function name(arg1, arg2)" Define function. 9500 */ 9501 p = skipwhite(p); 9502 if (*p != '(') 9503 { 9504 if (!eap->skip) 9505 { 9506 EMSG2(_("E124: Missing '(': %s"), eap->arg); 9507 goto erret_name; 9508 } 9509 /* attempt to continue by skipping some text */ 9510 if (vim_strchr(p, '(') != NULL) 9511 p = vim_strchr(p, '('); 9512 } 9513 p = skipwhite(p + 1); 9514 9515 ga_init2(&newargs, (int)sizeof(char_u *), 3); 9516 ga_init2(&newlines, (int)sizeof(char_u *), 3); 9517 9518 /* 9519 * Isolate the arguments: "arg1, arg2, ...)" 9520 */ 9521 while (*p != ')') 9522 { 9523 if (p[0] == '.' && p[1] == '.' && p[2] == '.') 9524 { 9525 varargs = TRUE; 9526 p += 3; 9527 mustend = TRUE; 9528 } 9529 else 9530 { 9531 arg = p; 9532 while (ASCII_ISALNUM(*p) || *p == '_') 9533 ++p; 9534 if (arg == p || isdigit(*arg) 9535 || (p - arg == 9 && STRNCMP(arg, "firstline", 9) == 0) 9536 || (p - arg == 8 && STRNCMP(arg, "lastline", 8) == 0)) 9537 { 9538 if (!eap->skip) 9539 EMSG2(_("E125: Illegal argument: %s"), arg); 9540 break; 9541 } 9542 if (ga_grow(&newargs, 1) == FAIL) 9543 goto erret; 9544 c = *p; 9545 *p = NUL; 9546 arg = vim_strsave(arg); 9547 if (arg == NULL) 9548 goto erret; 9549 ((char_u **)(newargs.ga_data))[newargs.ga_len] = arg; 9550 *p = c; 9551 newargs.ga_len++; 9552 newargs.ga_room--; 9553 if (*p == ',') 9554 ++p; 9555 else 9556 mustend = TRUE; 9557 } 9558 p = skipwhite(p); 9559 if (mustend && *p != ')') 9560 { 9561 if (!eap->skip) 9562 EMSG2(_(e_invarg2), eap->arg); 9563 break; 9564 } 9565 } 9566 ++p; /* skip the ')' */ 9567 9568 /* find extra arguments "range" and "abort" */ 9569 for (;;) 9570 { 9571 p = skipwhite(p); 9572 if (STRNCMP(p, "range", 5) == 0) 9573 { 9574 flags |= FC_RANGE; 9575 p += 5; 9576 } 9577 else if (STRNCMP(p, "abort", 5) == 0) 9578 { 9579 flags |= FC_ABORT; 9580 p += 5; 9581 } 9582 else 9583 break; 9584 } 9585 9586 if (*p != NUL && *p != '"' && *p != '\n' && !eap->skip && !did_emsg) 9587 EMSG(_(e_trailing)); 9588 9589 /* 9590 * Read the body of the function, until ":endfunction" is found. 9591 */ 9592 if (KeyTyped) 9593 { 9594 /* Check if the function already exists, don't let the user type the 9595 * whole function before telling him it doesn't work! For a script we 9596 * need to skip the body to be able to find what follows. */ 9597 if (!eap->skip && !eap->forceit && find_func(name) != NULL) 9598 EMSG2(_(e_funcexts), name); 9599 9600 msg_putchar('\n'); /* don't overwrite the function name */ 9601 cmdline_row = msg_row; 9602 } 9603 9604 indent = 2; 9605 nesting = 0; 9606 for (;;) 9607 { 9608 msg_scroll = TRUE; 9609 need_wait_return = FALSE; 9610 if (eap->getline == NULL) 9611 theline = getcmdline(':', 0L, indent); 9612 else 9613 theline = eap->getline(':', eap->cookie, indent); 9614 if (KeyTyped) 9615 lines_left = Rows - 1; 9616 if (theline == NULL) 9617 { 9618 EMSG(_("E126: Missing :endfunction")); 9619 goto erret; 9620 } 9621 9622 if (skip_until != NULL) 9623 { 9624 /* between ":append" and "." and between ":python <<EOF" and "EOF" 9625 * don't check for ":endfunc". */ 9626 if (STRCMP(theline, skip_until) == 0) 9627 { 9628 vim_free(skip_until); 9629 skip_until = NULL; 9630 } 9631 } 9632 else 9633 { 9634 /* skip ':' and blanks*/ 9635 for (p = theline; vim_iswhite(*p) || *p == ':'; ++p) 9636 ; 9637 9638 /* Check for "endfunction" (should be more strict...). */ 9639 if (STRNCMP(p, "endf", 4) == 0 && nesting-- == 0) 9640 { 9641 vim_free(theline); 9642 break; 9643 } 9644 9645 /* Increase indent inside "if", "while", and "try", decrease 9646 * at "end". */ 9647 if (indent > 2 && STRNCMP(p, "end", 3) == 0) 9648 indent -= 2; 9649 else if (STRNCMP(p, "if", 2) == 0 || STRNCMP(p, "wh", 2) == 0 9650 || STRNCMP(p, "try", 3) == 0) 9651 indent += 2; 9652 9653 /* Check for defining a function inside this function. */ 9654 if (STRNCMP(p, "fu", 2) == 0) 9655 { 9656 p = skipwhite(skiptowhite(p)); 9657 p += eval_fname_script(p); 9658 if (ASCII_ISALPHA(*p)) 9659 { 9660 vim_free(trans_function_name(&p, TRUE, FALSE)); 9661 if (*skipwhite(p) == '(') 9662 { 9663 ++nesting; 9664 indent += 2; 9665 } 9666 } 9667 } 9668 9669 /* Check for ":append" or ":insert". */ 9670 p = skip_range(p, NULL); 9671 if ((p[0] == 'a' && (!ASCII_ISALPHA(p[1]) || p[1] == 'p')) 9672 || (p[0] == 'i' 9673 && (!ASCII_ISALPHA(p[1]) || (p[1] == 'n' 9674 && (!ASCII_ISALPHA(p[2]) || (p[2] == 's')))))) 9675 skip_until = vim_strsave((char_u *)"."); 9676 9677 /* Check for ":python <<EOF", ":tcl <<EOF", etc. */ 9678 arg = skipwhite(skiptowhite(p)); 9679 if (arg[0] == '<' && arg[1] =='<' 9680 && ((p[0] == 'p' && p[1] == 'y' 9681 && (!ASCII_ISALPHA(p[2]) || p[2] == 't')) 9682 || (p[0] == 'p' && p[1] == 'e' 9683 && (!ASCII_ISALPHA(p[2]) || p[2] == 'r')) 9684 || (p[0] == 't' && p[1] == 'c' 9685 && (!ASCII_ISALPHA(p[2]) || p[2] == 'l')) 9686 || (p[0] == 'r' && p[1] == 'u' && p[2] == 'b' 9687 && (!ASCII_ISALPHA(p[3]) || p[3] == 'y')) 9688 || (p[0] == 'm' && p[1] == 'z' 9689 && (!ASCII_ISALPHA(p[2]) || p[2] == 's')) 9690 )) 9691 { 9692 /* ":python <<" continues until a dot, like ":append" */ 9693 p = skipwhite(arg + 2); 9694 if (*p == NUL) 9695 skip_until = vim_strsave((char_u *)"."); 9696 else 9697 skip_until = vim_strsave(p); 9698 } 9699 } 9700 9701 /* Add the line to the function. */ 9702 if (ga_grow(&newlines, 1) == FAIL) 9703 goto erret; 9704 ((char_u **)(newlines.ga_data))[newlines.ga_len] = theline; 9705 newlines.ga_len++; 9706 newlines.ga_room--; 9707 } 9708 9709 /* Don't define the function when skipping commands or when an error was 9710 * detected. */ 9711 if (eap->skip || did_emsg) 9712 goto erret; 9713 9714 /* 9715 * If there are no errors, add the function 9716 */ 9717 fp = find_func(name); 9718 if (fp != NULL) 9719 { 9720 if (!eap->forceit) 9721 { 9722 EMSG2(_(e_funcexts), name); 9723 goto erret; 9724 } 9725 if (fp->calls) 9726 { 9727 EMSG2(_("E127: Cannot redefine function %s: It is in use"), name); 9728 goto erret; 9729 } 9730 /* redefine existing function */ 9731 ga_clear_strings(&(fp->args)); 9732 ga_clear_strings(&(fp->lines)); 9733 vim_free(name); 9734 } 9735 else 9736 { 9737 fp = (ufunc_T *)alloc((unsigned)sizeof(ufunc_T)); 9738 if (fp == NULL) 9739 goto erret; 9740 /* insert the new function in the function list */ 9741 fp->next = firstfunc; 9742 firstfunc = fp; 9743 fp->name = name; 9744 } 9745 fp->args = newargs; 9746 fp->lines = newlines; 9747 fp->varargs = varargs; 9748 fp->flags = flags; 9749 fp->calls = 0; 9750 fp->script_ID = current_SID; 9751 #ifdef FEAT_MAGIC_BRACES 9752 did_emsg |= saved_did_emsg; 9753 #endif 9754 vim_free(skip_until); 9755 return; 9756 9757 erret: 9758 vim_free(skip_until); 9759 ga_clear_strings(&newargs); 9760 ga_clear_strings(&newlines); 9761 erret_name: 9762 vim_free(name); 9763 #ifdef FEAT_MAGIC_BRACES 9764 did_emsg |= saved_did_emsg; 9765 #endif 9766 } 9767 9768 /* 9769 * Get a function name, translating "<SID>" and "<SNR>". 9770 * Returns the function name in allocated memory, or NULL for failure. 9771 * Advances "pp" to just after the function name (if no error). 9772 */ 9773 static char_u * 9774 trans_function_name(pp, skip, internal) 9775 char_u **pp; 9776 int skip; /* only find the end, don't evaluate */ 9777 int internal; /* TRUE if internal function name OK */ 9778 { 9779 char_u *name; 9780 char_u *start; 9781 char_u *end; 9782 int lead; 9783 char_u sid_buf[20]; 9784 char_u *temp_string = NULL; 9785 char_u *expr_start, *expr_end; 9786 int len; 9787 9788 /* A name starting with "<SID>" or "<SNR>" is local to a script. */ 9789 start = *pp; 9790 lead = eval_fname_script(start); 9791 if (lead > 0) 9792 start += lead; 9793 end = find_name_end(start, &expr_start, &expr_end); 9794 if (end == start) 9795 { 9796 if (!skip) 9797 EMSG(_("E129: Function name required")); 9798 return NULL; 9799 } 9800 #ifdef FEAT_MAGIC_BRACES 9801 if (expr_start != NULL && !skip) 9802 { 9803 /* expand magic curlies */ 9804 temp_string = make_expanded_name(start, expr_start, expr_end, end); 9805 if (temp_string == NULL) 9806 { 9807 /* 9808 * Report an invalid expression in braces, unless the expression 9809 * evaluation has been cancelled due to an aborting error, an 9810 * interrupt, or an exception. 9811 */ 9812 if (!aborting()) 9813 EMSG2(_(e_invarg2), start); 9814 else 9815 *pp = end; 9816 return NULL; 9817 } 9818 start = temp_string; 9819 len = (int)STRLEN(temp_string); 9820 } 9821 else 9822 #endif 9823 len = (int)(end - start); 9824 9825 /* 9826 * Copy the function name to allocated memory. 9827 * Accept <SID>name() inside a script, translate into <SNR>123_name(). 9828 * Accept <SNR>123_name() outside a script. 9829 */ 9830 if (skip) 9831 lead = 0; /* do nothing */ 9832 else if (lead > 0) 9833 { 9834 lead = 3; 9835 if (eval_fname_sid(*pp)) /* If it's "<SID>" */ 9836 { 9837 if (current_SID <= 0) 9838 { 9839 EMSG(_(e_usingsid)); 9840 return NULL; 9841 } 9842 sprintf((char *)sid_buf, "%ld_", (long)current_SID); 9843 lead += (int)STRLEN(sid_buf); 9844 } 9845 } 9846 else if (!internal && !ASCII_ISUPPER(*start)) 9847 { 9848 EMSG2(_("E128: Function name must start with a capital: %s"), start); 9849 return NULL; 9850 } 9851 name = alloc((unsigned)(len + lead + 1)); 9852 if (name != NULL) 9853 { 9854 if (lead > 0) 9855 { 9856 name[0] = K_SPECIAL; 9857 name[1] = KS_EXTRA; 9858 name[2] = (int)KE_SNR; 9859 if (eval_fname_sid(*pp)) /* If it's "<SID>" */ 9860 STRCPY(name + 3, sid_buf); 9861 } 9862 mch_memmove(name + lead, start, (size_t)len); 9863 name[len + lead] = NUL; 9864 } 9865 *pp = end; 9866 9867 vim_free(temp_string); 9868 return name; 9869 } 9870 9871 /* 9872 * Return 5 if "p" starts with "<SID>" or "<SNR>" (ignoring case). 9873 * Return 2 if "p" starts with "s:". 9874 * Return 0 otherwise. 9875 */ 9876 static int 9877 eval_fname_script(p) 9878 char_u *p; 9879 { 9880 if (p[0] == '<' && (STRNICMP(p + 1, "SID>", 4) == 0 9881 || STRNICMP(p + 1, "SNR>", 4) == 0)) 9882 return 5; 9883 if (p[0] == 's' && p[1] == ':') 9884 return 2; 9885 return 0; 9886 } 9887 9888 /* 9889 * Return TRUE if "p" starts with "<SID>" or "s:". 9890 * Only works if eval_fname_script() returned non-zero for "p"! 9891 */ 9892 static int 9893 eval_fname_sid(p) 9894 char_u *p; 9895 { 9896 return (*p == 's' || TOUPPER_ASC(p[2]) == 'I'); 9897 } 9898 9899 /* 9900 * List the head of the function: "name(arg1, arg2)". 9901 */ 9902 static void 9903 list_func_head(fp, indent) 9904 ufunc_T *fp; 9905 int indent; 9906 { 9907 int j; 9908 9909 msg_start(); 9910 if (indent) 9911 MSG_PUTS(" "); 9912 MSG_PUTS("function "); 9913 if (fp->name[0] == K_SPECIAL) 9914 { 9915 MSG_PUTS_ATTR("<SNR>", hl_attr(HLF_8)); 9916 msg_puts(fp->name + 3); 9917 } 9918 else 9919 msg_puts(fp->name); 9920 msg_putchar('('); 9921 for (j = 0; j < fp->args.ga_len; ++j) 9922 { 9923 if (j) 9924 MSG_PUTS(", "); 9925 msg_puts(FUNCARG(fp, j)); 9926 } 9927 if (fp->varargs) 9928 { 9929 if (j) 9930 MSG_PUTS(", "); 9931 MSG_PUTS("..."); 9932 } 9933 msg_putchar(')'); 9934 } 9935 9936 /* 9937 * Find a function by name, return pointer to it in ufuncs. 9938 * Return NULL for unknown function. 9939 */ 9940 static ufunc_T * 9941 find_func(name) 9942 char_u *name; 9943 { 9944 ufunc_T *fp; 9945 9946 for (fp = firstfunc; fp != NULL; fp = fp->next) 9947 if (STRCMP(name, fp->name) == 0) 9948 break; 9949 return fp; 9950 } 9951 9952 #if defined(FEAT_CMDL_COMPL) || defined(PROTO) 9953 9954 /* 9955 * Function given to ExpandGeneric() to obtain the list of user defined 9956 * function names. 9957 */ 9958 char_u * 9959 get_user_func_name(xp, idx) 9960 expand_T *xp; 9961 int idx; 9962 { 9963 static ufunc_T *fp = NULL; 9964 9965 if (idx == 0) 9966 fp = firstfunc; 9967 if (fp != NULL) 9968 { 9969 if (STRLEN(fp->name) + 4 >= IOSIZE) 9970 return fp->name; /* prevents overflow */ 9971 9972 cat_func_name(IObuff, fp); 9973 if (xp->xp_context != EXPAND_USER_FUNC) 9974 { 9975 STRCAT(IObuff, "("); 9976 if (!fp->varargs && fp->args.ga_len == 0) 9977 STRCAT(IObuff, ")"); 9978 } 9979 9980 fp = fp->next; 9981 return IObuff; 9982 } 9983 return NULL; 9984 } 9985 9986 #endif /* FEAT_CMDL_COMPL */ 9987 9988 /* 9989 * Copy the function name of "fp" to buffer "buf". 9990 * "buf" must be able to hold the function name plus three bytes. 9991 * Takes care of script-local function names. 9992 */ 9993 static void 9994 cat_func_name(buf, fp) 9995 char_u *buf; 9996 ufunc_T *fp; 9997 { 9998 if (fp->name[0] == K_SPECIAL) 9999 { 10000 STRCPY(buf, "<SNR>"); 10001 STRCAT(buf, fp->name + 3); 10002 } 10003 else 10004 STRCPY(buf, fp->name); 10005 } 10006 10007 /* 10008 * ":delfunction {name}" 10009 */ 10010 void 10011 ex_delfunction(eap) 10012 exarg_T *eap; 10013 { 10014 ufunc_T *fp = NULL, *pfp; 10015 char_u *p; 10016 char_u *name; 10017 10018 p = eap->arg; 10019 name = trans_function_name(&p, eap->skip, FALSE); 10020 if (name == NULL) 10021 return; 10022 if (!ends_excmd(*skipwhite(p))) 10023 { 10024 vim_free(name); 10025 EMSG(_(e_trailing)); 10026 return; 10027 } 10028 eap->nextcmd = check_nextcmd(p); 10029 if (eap->nextcmd != NULL) 10030 *p = NUL; 10031 10032 if (!eap->skip) 10033 fp = find_func(name); 10034 vim_free(name); 10035 10036 if (!eap->skip) 10037 { 10038 if (fp == NULL) 10039 { 10040 EMSG2(_("E130: Undefined function: %s"), eap->arg); 10041 return; 10042 } 10043 if (fp->calls) 10044 { 10045 EMSG2(_("E131: Cannot delete function %s: It is in use"), eap->arg); 10046 return; 10047 } 10048 10049 /* clear this function */ 10050 vim_free(fp->name); 10051 ga_clear_strings(&(fp->args)); 10052 ga_clear_strings(&(fp->lines)); 10053 10054 /* remove the function from the function list */ 10055 if (firstfunc == fp) 10056 firstfunc = fp->next; 10057 else 10058 { 10059 for (pfp = firstfunc; pfp != NULL; pfp = pfp->next) 10060 if (pfp->next == fp) 10061 { 10062 pfp->next = fp->next; 10063 break; 10064 } 10065 } 10066 vim_free(fp); 10067 } 10068 } 10069 10070 /* 10071 * Call a user function. 10072 */ 10073 static void 10074 call_user_func(fp, argcount, argvars, retvar, firstline, lastline) 10075 ufunc_T *fp; /* pointer to function */ 10076 int argcount; /* nr of args */ 10077 VAR argvars; /* arguments */ 10078 VAR retvar; /* return value */ 10079 linenr_T firstline; /* first line of range */ 10080 linenr_T lastline; /* last line of range */ 10081 { 10082 char_u *save_sourcing_name; 10083 linenr_T save_sourcing_lnum; 10084 scid_T save_current_SID; 10085 struct funccall fc; 10086 struct funccall *save_fcp = current_funccal; 10087 int save_did_emsg; 10088 static int depth = 0; 10089 10090 /* If depth of calling is getting too high, don't execute the function */ 10091 if (depth >= p_mfd) 10092 { 10093 EMSG(_("E132: Function call depth is higher than 'maxfuncdepth'")); 10094 retvar->var_type = VAR_NUMBER; 10095 retvar->var_val.var_number = -1; 10096 return; 10097 } 10098 ++depth; 10099 10100 line_breakcheck(); /* check for CTRL-C hit */ 10101 10102 /* set local variables */ 10103 var_init(&fc.l_vars); 10104 fc.func = fp; 10105 fc.argcount = argcount; 10106 fc.argvars = argvars; 10107 fc.retvar = retvar; 10108 retvar->var_val.var_number = 0; 10109 fc.linenr = 0; 10110 fc.returned = FALSE; 10111 fc.level = ex_nesting_level; 10112 fc.a0_var.var_type = VAR_NUMBER; 10113 fc.a0_var.var_val.var_number = argcount - fp->args.ga_len; 10114 fc.a0_var.var_name = NULL; 10115 current_funccal = &fc; 10116 fc.firstline.var_type = VAR_NUMBER; 10117 fc.firstline.var_val.var_number = firstline; 10118 fc.firstline.var_name = NULL; 10119 fc.lastline.var_type = VAR_NUMBER; 10120 fc.lastline.var_val.var_number = lastline; 10121 fc.lastline.var_name = NULL; 10122 /* Check if this function has a breakpoint. */ 10123 fc.breakpoint = dbg_find_breakpoint(FALSE, fp->name, (linenr_T)0); 10124 fc.dbg_tick = debug_tick; 10125 10126 /* Don't redraw while executing the function. */ 10127 ++RedrawingDisabled; 10128 save_sourcing_name = sourcing_name; 10129 save_sourcing_lnum = sourcing_lnum; 10130 sourcing_lnum = 1; 10131 sourcing_name = alloc((unsigned)((save_sourcing_name == NULL ? 0 10132 : STRLEN(save_sourcing_name)) + STRLEN(fp->name) + 13)); 10133 if (sourcing_name != NULL) 10134 { 10135 if (save_sourcing_name != NULL 10136 && STRNCMP(save_sourcing_name, "function ", 9) == 0) 10137 sprintf((char *)sourcing_name, "%s..", save_sourcing_name); 10138 else 10139 STRCPY(sourcing_name, "function "); 10140 cat_func_name(sourcing_name + STRLEN(sourcing_name), fp); 10141 10142 if (p_verbose >= 12) 10143 { 10144 ++no_wait_return; 10145 msg_scroll = TRUE; /* always scroll up, don't overwrite */ 10146 msg_str((char_u *)_("calling %s"), sourcing_name); 10147 if (p_verbose >= 14) 10148 { 10149 int i; 10150 char_u buf[MSG_BUF_LEN]; 10151 10152 msg_puts((char_u *)"("); 10153 for (i = 0; i < argcount; ++i) 10154 { 10155 if (i > 0) 10156 msg_puts((char_u *)", "); 10157 if (argvars[i].var_type == VAR_NUMBER) 10158 msg_outnum((long)argvars[i].var_val.var_number); 10159 else 10160 { 10161 trunc_string(get_var_string(&argvars[i]), 10162 buf, MSG_BUF_LEN); 10163 msg_puts((char_u *)"\""); 10164 msg_puts(buf); 10165 msg_puts((char_u *)"\""); 10166 } 10167 } 10168 msg_puts((char_u *)")"); 10169 } 10170 msg_puts((char_u *)"\n"); /* don't overwrite this either */ 10171 cmdline_row = msg_row; 10172 --no_wait_return; 10173 } 10174 } 10175 save_current_SID = current_SID; 10176 current_SID = fp->script_ID; 10177 save_did_emsg = did_emsg; 10178 did_emsg = FALSE; 10179 10180 /* call do_cmdline() to execute the lines */ 10181 do_cmdline(NULL, get_func_line, (void *)&fc, 10182 DOCMD_NOWAIT|DOCMD_VERBOSE|DOCMD_REPEAT); 10183 10184 --RedrawingDisabled; 10185 10186 /* when the function was aborted because of an error, return -1 */ 10187 if ((did_emsg && (fp->flags & FC_ABORT)) || retvar->var_type == VAR_UNKNOWN) 10188 { 10189 clear_var(retvar); 10190 retvar->var_type = VAR_NUMBER; 10191 retvar->var_val.var_number = -1; 10192 } 10193 10194 /* when being verbose, mention the return value */ 10195 if (p_verbose >= 12) 10196 { 10197 char_u *sn, *val; 10198 10199 ++no_wait_return; 10200 msg_scroll = TRUE; /* always scroll up, don't overwrite */ 10201 10202 /* Make sure the output fits in IObuff. */ 10203 sn = sourcing_name; 10204 if (STRLEN(sourcing_name) > IOSIZE / 2 - 50) 10205 sn = sourcing_name + STRLEN(sourcing_name) - (IOSIZE / 2 - 50); 10206 10207 if (aborting()) 10208 smsg((char_u *)_("%s aborted"), sn); 10209 else if (fc.retvar->var_type == VAR_NUMBER) 10210 smsg((char_u *)_("%s returning #%ld"), sn, 10211 (long)fc.retvar->var_val.var_number); 10212 else if (fc.retvar->var_type == VAR_STRING) 10213 { 10214 val = get_var_string(fc.retvar); 10215 if (STRLEN(val) > IOSIZE / 2 - 50) 10216 val = val + STRLEN(val) - (IOSIZE / 2 - 50); 10217 smsg((char_u *)_("%s returning \"%s\""), sn, val); 10218 } 10219 msg_puts((char_u *)"\n"); /* don't overwrite this either */ 10220 cmdline_row = msg_row; 10221 --no_wait_return; 10222 } 10223 10224 vim_free(sourcing_name); 10225 sourcing_name = save_sourcing_name; 10226 sourcing_lnum = save_sourcing_lnum; 10227 current_SID = save_current_SID; 10228 10229 if (p_verbose >= 12 && sourcing_name != NULL) 10230 { 10231 ++no_wait_return; 10232 msg_scroll = TRUE; /* always scroll up, don't overwrite */ 10233 msg_str((char_u *)_("continuing in %s"), sourcing_name); 10234 msg_puts((char_u *)"\n"); /* don't overwrite this either */ 10235 cmdline_row = msg_row; 10236 --no_wait_return; 10237 } 10238 10239 did_emsg |= save_did_emsg; 10240 current_funccal = save_fcp; 10241 10242 var_clear(&fc.l_vars); /* free all local variables */ 10243 --depth; 10244 } 10245 10246 /* 10247 * ":return [expr]" 10248 */ 10249 void 10250 ex_return(eap) 10251 exarg_T *eap; 10252 { 10253 char_u *arg = eap->arg; 10254 var retvar; 10255 int returning = FALSE; 10256 10257 if (current_funccal == NULL) 10258 { 10259 EMSG(_("E133: :return not inside a function")); 10260 return; 10261 } 10262 10263 if (eap->skip) 10264 ++emsg_skip; 10265 10266 eap->nextcmd = NULL; 10267 if ((*arg != NUL && *arg != '|' && *arg != '\n') 10268 && eval0(arg, &retvar, &eap->nextcmd, !eap->skip) != FAIL) 10269 { 10270 if (!eap->skip) 10271 returning = do_return(eap, FALSE, TRUE, &retvar); 10272 else 10273 clear_var(&retvar); 10274 } 10275 /* It's safer to return also on error. */ 10276 else if (!eap->skip) 10277 { 10278 /* 10279 * Return unless the expression evaluation has been cancelled due to an 10280 * aborting error, an interrupt, or an exception. 10281 */ 10282 if (!aborting()) 10283 returning = do_return(eap, FALSE, TRUE, NULL); 10284 } 10285 10286 /* When skipping or the return gets pending, advance to the next command 10287 * in this line (!returning). Otherwise, ignore the rest of the line. 10288 * Following lines will be ignored by get_func_line(). */ 10289 if (returning) 10290 eap->nextcmd = NULL; 10291 else if (eap->nextcmd == NULL) /* no argument */ 10292 eap->nextcmd = check_nextcmd(arg); 10293 10294 if (eap->skip) 10295 --emsg_skip; 10296 } 10297 10298 /* 10299 * Return from a function. Possibly makes the return pending. Also called 10300 * for a pending return at the ":endtry" or after returning from an extra 10301 * do_cmdline(). "reanimate" is used in the latter case. "is_cmd" is set 10302 * when called due to a ":return" command. "value" may point to a variable 10303 * with the return value. Returns TRUE when the return can be carried out, 10304 * FALSE when the return gets pending. 10305 */ 10306 int 10307 do_return(eap, reanimate, is_cmd, value) 10308 exarg_T *eap; 10309 int reanimate; 10310 int is_cmd; 10311 void *value; 10312 { 10313 int idx; 10314 struct condstack *cstack = eap->cstack; 10315 10316 if (reanimate) 10317 /* Undo the return. */ 10318 current_funccal->returned = FALSE; 10319 10320 /* 10321 * Cleanup (and inactivate) conditionals, but stop when a try conditional 10322 * not in its finally clause (which then is to be executed next) is found. 10323 * In this case, make the ":return" pending for execution at the ":endtry". 10324 * Otherwise, return normally. 10325 */ 10326 idx = cleanup_conditionals(eap->cstack, 0, TRUE); 10327 if (idx >= 0) 10328 { 10329 cstack->cs_pending[idx] = CSTP_RETURN; 10330 10331 if (!is_cmd && !reanimate) 10332 /* A pending return again gets pending. "value" points to an 10333 * allocated variable with the value of the original ":return"'s 10334 * argument if present or is NULL else. */ 10335 cstack->cs_retvar[idx] = value; 10336 else 10337 { 10338 /* When undoing a return in order to make it pending, get the stored 10339 * return value. */ 10340 if (reanimate) 10341 value = current_funccal->retvar; 10342 10343 if (value != NULL) 10344 { 10345 /* Store the value of the pending return. */ 10346 if ((cstack->cs_retvar[idx] = alloc_var()) != NULL) 10347 *(VAR)cstack->cs_retvar[idx] = *(VAR)value; 10348 else 10349 EMSG(_(e_outofmem)); 10350 } 10351 else 10352 cstack->cs_retvar[idx] = NULL; 10353 10354 if (reanimate) 10355 { 10356 /* The pending return value could be overwritten by a ":return" 10357 * without argument in a finally clause; reset the default 10358 * return value. */ 10359 current_funccal->retvar->var_type = VAR_NUMBER; 10360 current_funccal->retvar->var_val.var_number = 0; 10361 } 10362 } 10363 report_make_pending(CSTP_RETURN, value); 10364 } 10365 else 10366 { 10367 current_funccal->returned = TRUE; 10368 10369 /* If the return is carried out now, store the return value. For 10370 * a return immediately after reanimation, the value is already 10371 * there. */ 10372 if (!reanimate && value != NULL) 10373 { 10374 clear_var(current_funccal->retvar); 10375 *current_funccal->retvar = *(VAR)value; 10376 if (!is_cmd) 10377 vim_free(value); 10378 } 10379 } 10380 10381 return idx < 0; 10382 } 10383 10384 /* 10385 * Free the variable with a pending return value. 10386 */ 10387 void 10388 discard_pending_return(retvar) 10389 void *retvar; 10390 { 10391 /* The variable was copied from one with an undefined var_name. So we can't 10392 * use free_var() to clear and free it. */ 10393 clear_var((VAR)retvar); 10394 vim_free(retvar); 10395 } 10396 10397 /* 10398 * Generate a return command for producing the value of "retvar". The result 10399 * is an allocated string. Used by report_pending() for verbose messages. 10400 */ 10401 char_u * 10402 get_return_cmd(retvar) 10403 void *retvar; 10404 { 10405 char_u *s = IObuff; 10406 10407 if (retvar == NULL || ((VAR)retvar)->var_type == VAR_UNKNOWN) 10408 s = (char_u *)":return"; 10409 else if (((VAR)retvar)->var_type == VAR_STRING) 10410 sprintf((char *)IObuff, ":return \"%s\"", 10411 ((VAR)retvar)->var_val.var_string); 10412 else 10413 sprintf((char *)IObuff, ":return %ld", 10414 (long)(((VAR)retvar)->var_val.var_number)); 10415 return vim_strsave(s); 10416 } 10417 10418 /* 10419 * Get next function line. 10420 * Called by do_cmdline() to get the next line. 10421 * Returns allocated string, or NULL for end of function. 10422 */ 10423 /* ARGSUSED */ 10424 char_u * 10425 get_func_line(c, cookie, indent) 10426 int c; /* not used */ 10427 void *cookie; 10428 int indent; /* not used */ 10429 { 10430 struct funccall *fcp = (struct funccall *)cookie; 10431 char_u *retval; 10432 garray_T *gap; /* growarray with function lines */ 10433 10434 /* If breakpoints have been added/deleted need to check for it. */ 10435 if (fcp->dbg_tick != debug_tick) 10436 { 10437 fcp->breakpoint = dbg_find_breakpoint(FALSE, fcp->func->name, 10438 sourcing_lnum); 10439 fcp->dbg_tick = debug_tick; 10440 } 10441 10442 gap = &fcp->func->lines; 10443 if ((fcp->func->flags & FC_ABORT) && did_emsg && !aborted_in_try()) 10444 retval = NULL; 10445 else if (fcp->returned || fcp->linenr >= gap->ga_len) 10446 retval = NULL; 10447 else 10448 { 10449 retval = vim_strsave(((char_u **)(gap->ga_data))[fcp->linenr++]); 10450 sourcing_lnum = fcp->linenr; 10451 } 10452 10453 /* Did we encounter a breakpoint? */ 10454 if (fcp->breakpoint != 0 && fcp->breakpoint <= sourcing_lnum) 10455 { 10456 dbg_breakpoint(fcp->func->name, sourcing_lnum); 10457 /* Find next breakpoint. */ 10458 fcp->breakpoint = dbg_find_breakpoint(FALSE, fcp->func->name, 10459 sourcing_lnum); 10460 fcp->dbg_tick = debug_tick; 10461 } 10462 10463 return retval; 10464 } 10465 10466 /* 10467 * Return TRUE if the currently active function should be ended, because a 10468 * return was encountered or an error occured. Used inside a ":while". 10469 */ 10470 int 10471 func_has_ended(cookie) 10472 void *cookie; 10473 { 10474 struct funccall *fcp = (struct funccall *)cookie; 10475 10476 /* Ignore the "abort" flag if the abortion behavior has been changed due to 10477 * an error inside a try conditional. */ 10478 return (((fcp->func->flags & FC_ABORT) && did_emsg && !aborted_in_try()) 10479 || fcp->returned); 10480 } 10481 10482 /* 10483 * return TRUE if cookie indicates a function which "abort"s on errors. 10484 */ 10485 int 10486 func_has_abort(cookie) 10487 void *cookie; 10488 { 10489 return ((struct funccall *)cookie)->func->flags & FC_ABORT; 10490 } 10491 10492 #if defined(FEAT_VIMINFO) || defined(FEAT_SESSION) 10493 typedef enum 10494 { 10495 VAR_FLAVOUR_DEFAULT, 10496 VAR_FLAVOUR_SESSION, 10497 VAR_FLAVOUR_VIMINFO 10498 } var_flavour_T; 10499 10500 static var_flavour_T var_flavour __ARGS((char_u *varname)); 10501 10502 static var_flavour_T 10503 var_flavour(varname) 10504 char_u *varname; 10505 { 10506 char_u *p = varname; 10507 10508 if (ASCII_ISUPPER(*p)) 10509 { 10510 while (*(++p)) 10511 if (ASCII_ISLOWER(*p)) 10512 return VAR_FLAVOUR_SESSION; 10513 return VAR_FLAVOUR_VIMINFO; 10514 } 10515 else 10516 return VAR_FLAVOUR_DEFAULT; 10517 } 10518 #endif 10519 10520 #if defined(FEAT_VIMINFO) || defined(PROTO) 10521 /* 10522 * Restore global vars that start with a capital from the viminfo file 10523 */ 10524 int 10525 read_viminfo_varlist(virp, writing) 10526 vir_T *virp; 10527 int writing; 10528 { 10529 char_u *tab; 10530 int is_string = FALSE; 10531 VAR varp = NULL; 10532 char_u *val; 10533 10534 if (!writing && (find_viminfo_parameter('!') != NULL)) 10535 { 10536 tab = vim_strchr(virp->vir_line + 1, '\t'); 10537 if (tab != NULL) 10538 { 10539 *tab++ = '\0'; /* isolate the variable name */ 10540 if (*tab == 'S') /* string var */ 10541 is_string = TRUE; 10542 10543 tab = vim_strchr(tab, '\t'); 10544 if (tab != NULL) 10545 { 10546 /* create a nameless variable to hold the value */ 10547 if (is_string) 10548 { 10549 val = viminfo_readstring(virp, 10550 (int)(tab - virp->vir_line + 1), TRUE); 10551 if (val != NULL) 10552 varp = alloc_string_var(val); 10553 } 10554 else 10555 { 10556 varp = alloc_var(); 10557 if (varp != NULL) 10558 { 10559 varp->var_type = VAR_NUMBER; 10560 varp->var_val.var_number = atol((char *)tab + 1); 10561 } 10562 } 10563 /* assign the value to the variable */ 10564 if (varp != NULL) 10565 { 10566 set_var(virp->vir_line + 1, varp); 10567 free_var(varp); 10568 } 10569 } 10570 } 10571 } 10572 10573 return viminfo_readline(virp); 10574 } 10575 10576 /* 10577 * Write global vars that start with a capital to the viminfo file 10578 */ 10579 void 10580 write_viminfo_varlist(fp) 10581 FILE *fp; 10582 { 10583 garray_T *gap = &variables; /* global variable */ 10584 VAR this_var; 10585 int i; 10586 10587 if (find_viminfo_parameter('!') == NULL) 10588 return; 10589 10590 fprintf(fp, _("\n# global variables:\n")); 10591 for (i = gap->ga_len; --i >= 0; ) 10592 { 10593 this_var = &VAR_GAP_ENTRY(i, gap); 10594 if (this_var->var_name != NULL 10595 && var_flavour(this_var->var_name) == VAR_FLAVOUR_VIMINFO) 10596 { 10597 fprintf(fp, "!%s\t%s\t", this_var->var_name, 10598 (this_var->var_type == VAR_STRING) ? "STR" : "NUM"); 10599 viminfo_writestring(fp, get_var_string(this_var)); 10600 } 10601 } 10602 } 10603 #endif 10604 10605 #if defined(FEAT_SESSION) || defined(PROTO) 10606 int 10607 store_session_globals(fd) 10608 FILE *fd; 10609 { 10610 garray_T *gap = &variables; /* global variable */ 10611 VAR this_var; 10612 int i; 10613 char_u *p, *t; 10614 10615 for (i = gap->ga_len; --i >= 0; ) 10616 { 10617 this_var = &VAR_GAP_ENTRY(i, gap); 10618 if (this_var->var_name != NULL) 10619 { 10620 if (var_flavour(this_var->var_name) == VAR_FLAVOUR_SESSION) 10621 { 10622 /* Escapse special characters with a backslash. Turn a LF and 10623 * CR into \n and \r. */ 10624 p = vim_strsave_escaped(get_var_string(this_var), 10625 (char_u *)"\\\"\n\r"); 10626 if (p == NULL) /* out of memory */ 10627 continue; 10628 for (t = p; *t != NUL; ++t) 10629 if (*t == '\n') 10630 *t = 'n'; 10631 else if (*t == '\r') 10632 *t = 'r'; 10633 if ((fprintf(fd, "let %s = %c%s%c", 10634 this_var->var_name, 10635 (this_var->var_type == VAR_STRING) ? '"' : ' ', 10636 p, 10637 (this_var->var_type == VAR_STRING) ? '"' : ' ') < 0) 10638 || put_eol(fd) == FAIL) 10639 { 10640 vim_free(p); 10641 return FAIL; 10642 } 10643 vim_free(p); 10644 } 10645 10646 } 10647 } 10648 return OK; 10649 } 10650 #endif 10651 10652 #endif /* FEAT_EVAL */ 10653 10654 #if defined(FEAT_MODIFY_FNAME) || defined(FEAT_EVAL) || defined(PROTO) 10655 10656 10657 #ifdef WIN3264 10658 /* 10659 * Functions for ":8" filename modifier: get 8.3 version of a filename. 10660 */ 10661 static int get_short_pathname __ARGS((char_u **fnamep, char_u **bufp, int *fnamelen)); 10662 static int shortpath_for_invalid_fname __ARGS((char_u **fname, char_u **bufp, int *fnamelen)); 10663 static int shortpath_for_partial __ARGS((char_u **fnamep, char_u **bufp, int *fnamelen)); 10664 10665 /* 10666 * Get the short pathname of a file. 10667 * Returns 1 on success. *fnamelen is 0 for nonexistant path. 10668 */ 10669 static int 10670 get_short_pathname(fnamep, bufp, fnamelen) 10671 char_u **fnamep; 10672 char_u **bufp; 10673 int *fnamelen; 10674 { 10675 int l,len; 10676 char_u *newbuf; 10677 10678 len = *fnamelen; 10679 10680 l = GetShortPathName(*fnamep, *fnamep, len); 10681 if (l > len - 1) 10682 { 10683 /* If that doesn't work (not enough space), then save the string 10684 * and try again with a new buffer big enough 10685 */ 10686 newbuf = vim_strnsave(*fnamep, l); 10687 if (newbuf == NULL) 10688 return 0; 10689 10690 vim_free(*bufp); 10691 *fnamep = *bufp = newbuf; 10692 10693 l = GetShortPathName(*fnamep,*fnamep,l+1); 10694 10695 /* Really should always succeed, as the buffer is big enough */ 10696 } 10697 10698 *fnamelen = l; 10699 return 1; 10700 } 10701 10702 /* 10703 * Create a short path name. Returns the length of the buffer it needs. 10704 * Doesn't copy over the end of the buffer passed in. 10705 */ 10706 static int 10707 shortpath_for_invalid_fname(fname, bufp, fnamelen) 10708 char_u **fname; 10709 char_u **bufp; 10710 int *fnamelen; 10711 { 10712 char_u *s, *p, *pbuf2, *pbuf3; 10713 char_u ch; 10714 int l,len,len2,plen,slen; 10715 10716 /* Make a copy */ 10717 len2 = *fnamelen; 10718 pbuf2 = vim_strnsave(*fname, len2); 10719 pbuf3 = NULL; 10720 10721 s = pbuf2 + len2 - 1; /* Find the end */ 10722 slen = 1; 10723 plen = len2; 10724 10725 l = 0; 10726 if (vim_ispathsep(*s)) 10727 { 10728 --s; 10729 ++slen; 10730 --plen; 10731 } 10732 10733 do 10734 { 10735 /* Go back one path-seperator */ 10736 while (s > pbuf2 && !vim_ispathsep(*s)) 10737 { 10738 --s; 10739 ++slen; 10740 --plen; 10741 } 10742 if (s <= pbuf2) 10743 break; 10744 10745 /* Remeber the character that is about to be blatted */ 10746 ch = *s; 10747 *s = 0; /* get_short_pathname requires a null-terminated string */ 10748 10749 /* Try it in situ */ 10750 p = pbuf2; 10751 if (!get_short_pathname(&p, &pbuf3, &plen)) 10752 { 10753 vim_free(pbuf2); 10754 return -1; 10755 } 10756 *s = ch; /* Preserve the string */ 10757 } while (plen == 0); 10758 10759 if (plen > 0) 10760 { 10761 /* Remeber the length of the new string. */ 10762 *fnamelen = len = plen + slen; 10763 vim_free(*bufp); 10764 if (len > len2) 10765 { 10766 /* If there's not enough space in the currently allocated string, 10767 * then copy it to a buffer big enough. 10768 */ 10769 *fname= *bufp = vim_strnsave(p, len); 10770 if (*fname == NULL) 10771 return -1; 10772 } 10773 else 10774 { 10775 /* Transfer pbuf2 to being the main buffer (it's big enough) */ 10776 *fname = *bufp = pbuf2; 10777 if (p != pbuf2) 10778 strncpy(*fname, p, plen); 10779 pbuf2 = NULL; 10780 } 10781 /* Concat the next bit */ 10782 strncpy(*fname + plen, s, slen); 10783 (*fname)[len] = '\0'; 10784 } 10785 vim_free(pbuf3); 10786 vim_free(pbuf2); 10787 return 0; 10788 } 10789 10790 /* 10791 * Get a pathname for a partial path. 10792 */ 10793 static int 10794 shortpath_for_partial(fnamep, bufp, fnamelen) 10795 char_u **fnamep; 10796 char_u **bufp; 10797 int *fnamelen; 10798 { 10799 int sepcount, len, tflen; 10800 char_u *p; 10801 char_u *pbuf, *tfname; 10802 int hasTilde; 10803 10804 /* Count up the path seperators from the RHS.. so we know which part 10805 * of the path to return. 10806 */ 10807 sepcount = 0; 10808 for (p = *fnamep + *fnamelen - 1; p >= *fnamep; --p) 10809 if (vim_ispathsep(*p)) 10810 ++sepcount; 10811 10812 /* Need full path first (use expand_env() to remove a "~/") */ 10813 hasTilde = (**fnamep == '~'); 10814 if (hasTilde) 10815 pbuf = tfname = expand_env_save(*fnamep); 10816 else 10817 pbuf = tfname = FullName_save(*fnamep, FALSE); 10818 10819 len = tflen = STRLEN(tfname); 10820 10821 if (!get_short_pathname(&tfname, &pbuf, &len)) 10822 return -1; 10823 10824 if (len == 0) 10825 { 10826 /* Don't have a valid filename, so shorten the rest of the 10827 * path if we can. This CAN give us invalid 8.3 filenames, but 10828 * there's not a lot of point in guessing what it might be. 10829 */ 10830 len = tflen; 10831 if (shortpath_for_invalid_fname(&tfname, &pbuf, &len) == -1) 10832 return -1; 10833 } 10834 10835 /* Count the paths backward to find the beginning of the desired string. */ 10836 for (p = tfname + len - 1; p >= tfname; --p) 10837 if (vim_ispathsep(*p)) 10838 { 10839 if (sepcount == 0 || (hasTilde && sepcount == 1)) 10840 break; 10841 else 10842 sepcount --; 10843 } 10844 if (hasTilde) 10845 { 10846 --p; 10847 if (p >= tfname) 10848 *p = '~'; 10849 else 10850 return -1; 10851 } 10852 else 10853 ++p; 10854 10855 /* Copy in the string - p indexes into tfname - allocated at pbuf */ 10856 vim_free(*bufp); 10857 *fnamelen = (int)STRLEN(p); 10858 *bufp = pbuf; 10859 *fnamep = p; 10860 10861 return 0; 10862 } 10863 #endif /* WIN3264 */ 10864 10865 /* 10866 * Adjust a filename, according to a string of modifiers. 10867 * *fnamep must be NUL terminated when called. When returning, the length is 10868 * determined by *fnamelen. 10869 * Returns valid flags. 10870 * When there is an error, *fnamep is set to NULL. 10871 */ 10872 int 10873 modify_fname(src, usedlen, fnamep, bufp, fnamelen) 10874 char_u *src; /* string with modifiers */ 10875 int *usedlen; /* characters after src that are used */ 10876 char_u **fnamep; /* file name so far */ 10877 char_u **bufp; /* buffer for allocated file name or NULL */ 10878 int *fnamelen; /* length of fnamep */ 10879 { 10880 int valid = 0; 10881 char_u *tail; 10882 char_u *s, *p, *pbuf; 10883 char_u dirname[MAXPATHL]; 10884 int c; 10885 int has_fullname = 0; 10886 #ifdef WIN3264 10887 int has_shortname = 0; 10888 #endif 10889 10890 repeat: 10891 /* ":p" - full path/file_name */ 10892 if (src[*usedlen] == ':' && src[*usedlen + 1] == 'p') 10893 { 10894 has_fullname = 1; 10895 10896 valid |= VALID_PATH; 10897 *usedlen += 2; 10898 10899 /* Expand "~/path" for all systems and "~user/path" for Unix and VMS */ 10900 if ((*fnamep)[0] == '~' 10901 #if !defined(UNIX) && !(defined(VMS) && defined(USER_HOME)) 10902 && ((*fnamep)[1] == '/' 10903 # ifdef BACKSLASH_IN_FILENAME 10904 || (*fnamep)[1] == '\\' 10905 # endif 10906 || (*fnamep)[1] == NUL) 10907 10908 #endif 10909 ) 10910 { 10911 *fnamep = expand_env_save(*fnamep); 10912 vim_free(*bufp); /* free any allocated file name */ 10913 *bufp = *fnamep; 10914 if (*fnamep == NULL) 10915 return -1; 10916 } 10917 10918 /* When "/." or "/.." is used: force expansion to get rid of it. */ 10919 for (p = *fnamep; *p != NUL; ++p) 10920 { 10921 if (vim_ispathsep(*p) 10922 && p[1] == '.' 10923 && (p[2] == NUL 10924 || vim_ispathsep(p[2]) 10925 || (p[2] == '.' 10926 && (p[3] == NUL || vim_ispathsep(p[3]))))) 10927 break; 10928 } 10929 10930 /* FullName_save() is slow, don't use it when not needed. */ 10931 if (*p != NUL || !vim_isAbsName(*fnamep)) 10932 { 10933 *fnamep = FullName_save(*fnamep, *p != NUL); 10934 vim_free(*bufp); /* free any allocated file name */ 10935 *bufp = *fnamep; 10936 if (*fnamep == NULL) 10937 return -1; 10938 } 10939 10940 /* Append a path separator to a directory. */ 10941 if (mch_isdir(*fnamep)) 10942 { 10943 /* Make room for one or two extra characters. */ 10944 *fnamep = vim_strnsave(*fnamep, (int)STRLEN(*fnamep) + 2); 10945 vim_free(*bufp); /* free any allocated file name */ 10946 *bufp = *fnamep; 10947 if (*fnamep == NULL) 10948 return -1; 10949 add_pathsep(*fnamep); 10950 } 10951 } 10952 10953 /* ":." - path relative to the current directory */ 10954 /* ":~" - path relative to the home directory */ 10955 /* ":8" - shortname path - postponed till after */ 10956 while (src[*usedlen] == ':' 10957 && ((c = src[*usedlen + 1]) == '.' || c == '~' || c == '8')) 10958 { 10959 *usedlen += 2; 10960 if (c == '8') 10961 { 10962 #ifdef WIN3264 10963 has_shortname = 1; /* Postpone this. */ 10964 #endif 10965 continue; 10966 } 10967 pbuf = NULL; 10968 /* Need full path first (use expand_env() to remove a "~/") */ 10969 if (!has_fullname) 10970 { 10971 if (c == '.' && **fnamep == '~') 10972 p = pbuf = expand_env_save(*fnamep); 10973 else 10974 p = pbuf = FullName_save(*fnamep, FALSE); 10975 } 10976 else 10977 p = *fnamep; 10978 10979 has_fullname = 0; 10980 10981 if (p != NULL) 10982 { 10983 if (c == '.') 10984 { 10985 mch_dirname(dirname, MAXPATHL); 10986 s = shorten_fname(p, dirname); 10987 if (s != NULL) 10988 { 10989 *fnamep = s; 10990 if (pbuf != NULL) 10991 { 10992 vim_free(*bufp); /* free any allocated file name */ 10993 *bufp = pbuf; 10994 pbuf = NULL; 10995 } 10996 } 10997 } 10998 else 10999 { 11000 home_replace(NULL, p, dirname, MAXPATHL, TRUE); 11001 /* Only replace it when it starts with '~' */ 11002 if (*dirname == '~') 11003 { 11004 s = vim_strsave(dirname); 11005 if (s != NULL) 11006 { 11007 *fnamep = s; 11008 vim_free(*bufp); 11009 *bufp = s; 11010 } 11011 } 11012 } 11013 vim_free(pbuf); 11014 } 11015 } 11016 11017 tail = gettail(*fnamep); 11018 *fnamelen = (int)STRLEN(*fnamep); 11019 11020 /* ":h" - head, remove "/file_name", can be repeated */ 11021 /* Don't remove the first "/" or "c:\" */ 11022 while (src[*usedlen] == ':' && src[*usedlen + 1] == 'h') 11023 { 11024 valid |= VALID_HEAD; 11025 *usedlen += 2; 11026 s = get_past_head(*fnamep); 11027 while (tail > s && vim_ispathsep(tail[-1])) 11028 --tail; 11029 *fnamelen = (int)(tail - *fnamep); 11030 #ifdef VMS 11031 if (*fnamelen > 0) 11032 *fnamelen += 1; /* the path separator is part of the path */ 11033 #endif 11034 while (tail > s && !vim_ispathsep(tail[-1])) 11035 --tail; 11036 } 11037 11038 /* ":8" - shortname */ 11039 if (src[*usedlen] == ':' && src[*usedlen + 1] == '8') 11040 { 11041 *usedlen += 2; 11042 #ifdef WIN3264 11043 has_shortname = 1; 11044 #endif 11045 } 11046 11047 #ifdef WIN3264 11048 /* Check shortname after we have done 'heads' and before we do 'tails' 11049 */ 11050 if (has_shortname) 11051 { 11052 pbuf = NULL; 11053 /* Copy the string if it is shortened by :h */ 11054 if (*fnamelen < (int)STRLEN(*fnamep)) 11055 { 11056 p = vim_strnsave(*fnamep, *fnamelen); 11057 if (p == 0) 11058 return -1; 11059 vim_free(*bufp); 11060 *bufp = *fnamep = p; 11061 } 11062 11063 /* Split into two implementations - makes it easier. First is where 11064 * there isn't a full name already, second is where there is. 11065 */ 11066 if (!has_fullname && !vim_isAbsName(*fnamep)) 11067 { 11068 if (shortpath_for_partial(fnamep, bufp, fnamelen) == -1) 11069 return -1; 11070 } 11071 else 11072 { 11073 int l; 11074 11075 /* Simple case, already have the full-name 11076 * Nearly always shorter, so try first time. */ 11077 l = *fnamelen; 11078 if (!get_short_pathname(fnamep, bufp, &l)) 11079 return -1; 11080 11081 if (l == 0) 11082 { 11083 /* Couldn't find the filename.. search the paths. 11084 */ 11085 l = *fnamelen; 11086 if (shortpath_for_invalid_fname(fnamep, bufp, &l ) == -1) 11087 return -1; 11088 } 11089 *fnamelen = l; 11090 } 11091 } 11092 #endif /* WIN3264 */ 11093 11094 /* ":t" - tail, just the basename */ 11095 if (src[*usedlen] == ':' && src[*usedlen + 1] == 't') 11096 { 11097 *usedlen += 2; 11098 *fnamelen -= (int)(tail - *fnamep); 11099 *fnamep = tail; 11100 } 11101 11102 /* ":e" - extension, can be repeated */ 11103 /* ":r" - root, without extension, can be repeated */ 11104 while (src[*usedlen] == ':' 11105 && (src[*usedlen + 1] == 'e' || src[*usedlen + 1] == 'r')) 11106 { 11107 /* find a '.' in the tail: 11108 * - for second :e: before the current fname 11109 * - otherwise: The last '.' 11110 */ 11111 if (src[*usedlen + 1] == 'e' && *fnamep > tail) 11112 s = *fnamep - 2; 11113 else 11114 s = *fnamep + *fnamelen - 1; 11115 for ( ; s > tail; --s) 11116 if (s[0] == '.') 11117 break; 11118 if (src[*usedlen + 1] == 'e') /* :e */ 11119 { 11120 if (s > tail) 11121 { 11122 *fnamelen += (int)(*fnamep - (s + 1)); 11123 *fnamep = s + 1; 11124 #ifdef VMS 11125 /* cut version from the extension */ 11126 s = *fnamep + *fnamelen - 1; 11127 for ( ; s > *fnamep; --s) 11128 if (s[0] == ';') 11129 break; 11130 if (s > *fnamep) 11131 *fnamelen = s - *fnamep; 11132 #endif 11133 } 11134 else if (*fnamep <= tail) 11135 *fnamelen = 0; 11136 } 11137 else /* :r */ 11138 { 11139 if (s > tail) /* remove one extension */ 11140 *fnamelen = (int)(s - *fnamep); 11141 } 11142 *usedlen += 2; 11143 } 11144 11145 /* ":s?pat?foo?" - substitute */ 11146 /* ":gs?pat?foo?" - global substitute */ 11147 if (src[*usedlen] == ':' 11148 && (src[*usedlen + 1] == 's' 11149 || (src[*usedlen + 1] == 'g' && src[*usedlen + 2] == 's'))) 11150 { 11151 char_u *str; 11152 char_u *pat; 11153 char_u *sub; 11154 int sep; 11155 char_u *flags; 11156 int didit = FALSE; 11157 11158 flags = (char_u *)""; 11159 s = src + *usedlen + 2; 11160 if (src[*usedlen + 1] == 'g') 11161 { 11162 flags = (char_u *)"g"; 11163 ++s; 11164 } 11165 11166 sep = *s++; 11167 if (sep) 11168 { 11169 /* find end of pattern */ 11170 p = vim_strchr(s, sep); 11171 if (p != NULL) 11172 { 11173 pat = vim_strnsave(s, (int)(p - s)); 11174 if (pat != NULL) 11175 { 11176 s = p + 1; 11177 /* find end of substitution */ 11178 p = vim_strchr(s, sep); 11179 if (p != NULL) 11180 { 11181 sub = vim_strnsave(s, (int)(p - s)); 11182 str = vim_strnsave(*fnamep, *fnamelen); 11183 if (sub != NULL && str != NULL) 11184 { 11185 *usedlen = (int)(p + 1 - src); 11186 s = do_string_sub(str, pat, sub, flags); 11187 if (s != NULL) 11188 { 11189 *fnamep = s; 11190 *fnamelen = (int)STRLEN(s); 11191 vim_free(*bufp); 11192 *bufp = s; 11193 didit = TRUE; 11194 } 11195 } 11196 vim_free(sub); 11197 vim_free(str); 11198 } 11199 vim_free(pat); 11200 } 11201 } 11202 /* after using ":s", repeat all the modifiers */ 11203 if (didit) 11204 goto repeat; 11205 } 11206 } 11207 11208 return valid; 11209 } 11210 11211 /* 11212 * Perform a substitution on "str" with pattern "pat" and substitute "sub". 11213 * "flags" can be "g" to do a global substitute. 11214 * Returns an allocated string, NULL for error. 11215 */ 11216 char_u * 11217 do_string_sub(str, pat, sub, flags) 11218 char_u *str; 11219 char_u *pat; 11220 char_u *sub; 11221 char_u *flags; 11222 { 11223 int sublen; 11224 regmatch_T regmatch; 11225 int i; 11226 int do_all; 11227 char_u *tail; 11228 garray_T ga; 11229 char_u *ret; 11230 char_u *save_cpo; 11231 11232 /* Make 'cpoptions' empty, so that the 'l' flag doesn't work here */ 11233 save_cpo = p_cpo; 11234 p_cpo = (char_u *)""; 11235 11236 ga_init2(&ga, 1, 200); 11237 11238 do_all = (flags[0] == 'g'); 11239 11240 regmatch.rm_ic = p_ic; 11241 regmatch.regprog = vim_regcomp(pat, RE_MAGIC + RE_STRING); 11242 if (regmatch.regprog != NULL) 11243 { 11244 tail = str; 11245 while (vim_regexec_nl(®match, str, (colnr_T)(tail - str))) 11246 { 11247 /* 11248 * Get some space for a temporary buffer to do the substitution 11249 * into. It will contain: 11250 * - The text up to where the match is. 11251 * - The substituted text. 11252 * - The text after the match. 11253 */ 11254 sublen = vim_regsub(®match, sub, tail, FALSE, TRUE, FALSE); 11255 if (ga_grow(&ga, (int)(STRLEN(tail) + sublen - 11256 (regmatch.endp[0] - regmatch.startp[0]))) == FAIL) 11257 { 11258 ga_clear(&ga); 11259 break; 11260 } 11261 11262 /* copy the text up to where the match is */ 11263 i = (int)(regmatch.startp[0] - tail); 11264 mch_memmove((char_u *)ga.ga_data + ga.ga_len, tail, (size_t)i); 11265 /* add the substituted text */ 11266 (void)vim_regsub(®match, sub, (char_u *)ga.ga_data 11267 + ga.ga_len + i, TRUE, TRUE, FALSE); 11268 ga.ga_len += i + sublen - 1; 11269 ga.ga_room -= i + sublen - 1; 11270 /* avoid getting stuck on a match with an empty string */ 11271 if (tail == regmatch.endp[0]) 11272 { 11273 if (*tail == NUL) 11274 break; 11275 *((char_u *)ga.ga_data + ga.ga_len) = *tail++; 11276 ++ga.ga_len; 11277 --ga.ga_room; 11278 } 11279 else 11280 { 11281 tail = regmatch.endp[0]; 11282 if (*tail == NUL) 11283 break; 11284 } 11285 if (!do_all) 11286 break; 11287 } 11288 11289 if (ga.ga_data != NULL) 11290 STRCPY((char *)ga.ga_data + ga.ga_len, tail); 11291 11292 vim_free(regmatch.regprog); 11293 } 11294 11295 ret = vim_strsave(ga.ga_data == NULL ? str : (char_u *)ga.ga_data); 11296 ga_clear(&ga); 11297 p_cpo = save_cpo; 11298 11299 return ret; 11300 } 11301 11302 #endif /* defined(FEAT_MODIFY_FNAME) || defined(FEAT_EVAL) */ 11303