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