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 rest = haystack; 7345 while (*haystack != '\0') 7346 { 7347 rest = (char_u *)strstr((char *)rest, (char *)needle); 7348 if (rest == NULL) 7349 break; 7350 lastmatch = rest++; 7351 } 7352 7353 if (lastmatch == NULL) 7354 retvar->var_val.var_number = -1; 7355 else 7356 retvar->var_val.var_number = (varnumber_T) (lastmatch - haystack); 7357 } 7358 7359 /* 7360 * "strlen()" function 7361 */ 7362 static void 7363 f_strlen(argvars, retvar) 7364 VAR argvars; 7365 VAR retvar; 7366 { 7367 retvar->var_val.var_number = (varnumber_T) (STRLEN(get_var_string(&argvars[0]))); 7368 } 7369 7370 /* 7371 * "strpart()" function 7372 */ 7373 static void 7374 f_strpart(argvars, retvar) 7375 VAR argvars; 7376 VAR retvar; 7377 { 7378 char_u *p; 7379 int n; 7380 int len; 7381 int slen; 7382 7383 p = get_var_string(&argvars[0]); 7384 slen = (int)STRLEN(p); 7385 7386 n = get_var_number(&argvars[1]); 7387 if (argvars[2].var_type != VAR_UNKNOWN) 7388 len = get_var_number(&argvars[2]); 7389 else 7390 len = slen - n; /* default len: all bytes that are available. */ 7391 7392 /* 7393 * Only return the overlap between the specified part and the actual 7394 * string. 7395 */ 7396 if (n < 0) 7397 { 7398 len += n; 7399 n = 0; 7400 } 7401 else if (n > slen) 7402 n = slen; 7403 if (len < 0) 7404 len = 0; 7405 else if (n + len > slen) 7406 len = slen - n; 7407 7408 retvar->var_type = VAR_STRING; 7409 retvar->var_val.var_string = vim_strnsave(p + n, len); 7410 } 7411 7412 /* 7413 * "strtrans()" function 7414 */ 7415 static void 7416 f_strtrans(argvars, retvar) 7417 VAR argvars; 7418 VAR retvar; 7419 { 7420 retvar->var_type = VAR_STRING; 7421 retvar->var_val.var_string = transstr(get_var_string(&argvars[0])); 7422 } 7423 7424 /* 7425 * "synID(line, col, trans)" function 7426 */ 7427 /*ARGSUSED*/ 7428 static void 7429 f_synID(argvars, retvar) 7430 VAR argvars; 7431 VAR retvar; 7432 { 7433 int id = 0; 7434 #ifdef FEAT_SYN_HL 7435 long line; 7436 long col; 7437 int trans; 7438 7439 line = get_var_lnum(argvars); 7440 col = get_var_number(&argvars[1]) - 1; 7441 trans = get_var_number(&argvars[2]); 7442 7443 if (line >= 1 && line <= curbuf->b_ml.ml_line_count 7444 && col >= 0 && col < (long)STRLEN(ml_get(line))) 7445 id = syn_get_id(line, col, trans); 7446 #endif 7447 7448 retvar->var_val.var_number = id; 7449 } 7450 7451 /* 7452 * "synIDattr(id, what [, mode])" function 7453 */ 7454 /*ARGSUSED*/ 7455 static void 7456 f_synIDattr(argvars, retvar) 7457 VAR argvars; 7458 VAR retvar; 7459 { 7460 char_u *p = NULL; 7461 #ifdef FEAT_SYN_HL 7462 int id; 7463 char_u *what; 7464 char_u *mode; 7465 char_u modebuf[NUMBUFLEN]; 7466 int modec; 7467 7468 id = get_var_number(&argvars[0]); 7469 what = get_var_string(&argvars[1]); 7470 if (argvars[2].var_type != VAR_UNKNOWN) 7471 { 7472 mode = get_var_string_buf(&argvars[2], modebuf); 7473 modec = TOLOWER_ASC(mode[0]); 7474 if (modec != 't' && modec != 'c' 7475 #ifdef FEAT_GUI 7476 && modec != 'g' 7477 #endif 7478 ) 7479 modec = 0; /* replace invalid with current */ 7480 } 7481 else 7482 { 7483 #ifdef FEAT_GUI 7484 if (gui.in_use) 7485 modec = 'g'; 7486 else 7487 #endif 7488 if (t_colors > 1) 7489 modec = 'c'; 7490 else 7491 modec = 't'; 7492 } 7493 7494 7495 switch (TOLOWER_ASC(what[0])) 7496 { 7497 case 'b': 7498 if (TOLOWER_ASC(what[1]) == 'g') /* bg[#] */ 7499 p = highlight_color(id, what, modec); 7500 else /* bold */ 7501 p = highlight_has_attr(id, HL_BOLD, modec); 7502 break; 7503 7504 case 'f': /* fg[#] */ 7505 p = highlight_color(id, what, modec); 7506 break; 7507 7508 case 'i': 7509 if (TOLOWER_ASC(what[1]) == 'n') /* inverse */ 7510 p = highlight_has_attr(id, HL_INVERSE, modec); 7511 else /* italic */ 7512 p = highlight_has_attr(id, HL_ITALIC, modec); 7513 break; 7514 7515 case 'n': /* name */ 7516 p = get_highlight_name(NULL, id - 1); 7517 break; 7518 7519 case 'r': /* reverse */ 7520 p = highlight_has_attr(id, HL_INVERSE, modec); 7521 break; 7522 7523 case 's': /* standout */ 7524 p = highlight_has_attr(id, HL_STANDOUT, modec); 7525 break; 7526 7527 case 'u': /* underline */ 7528 p = highlight_has_attr(id, HL_UNDERLINE, modec); 7529 break; 7530 } 7531 7532 if (p != NULL) 7533 p = vim_strsave(p); 7534 #endif 7535 retvar->var_type = VAR_STRING; 7536 retvar->var_val.var_string = p; 7537 } 7538 7539 /* 7540 * "synIDtrans(id)" function 7541 */ 7542 /*ARGSUSED*/ 7543 static void 7544 f_synIDtrans(argvars, retvar) 7545 VAR argvars; 7546 VAR retvar; 7547 { 7548 int id; 7549 7550 #ifdef FEAT_SYN_HL 7551 id = get_var_number(&argvars[0]); 7552 7553 if (id > 0) 7554 id = syn_get_final_id(id); 7555 else 7556 #endif 7557 id = 0; 7558 7559 retvar->var_val.var_number = id; 7560 } 7561 7562 /* 7563 * "system()" function 7564 */ 7565 static void 7566 f_system(argvars, retvar) 7567 VAR argvars; 7568 VAR retvar; 7569 { 7570 char_u *p; 7571 7572 p = get_cmd_output(get_var_string(&argvars[0]), SHELL_SILENT); 7573 #ifdef USE_CR 7574 /* translate <CR> into <NL> */ 7575 if (p != NULL) 7576 { 7577 char_u *s; 7578 7579 for (s = p; *s; ++s) 7580 { 7581 if (*s == CAR) 7582 *s = NL; 7583 } 7584 } 7585 #else 7586 # ifdef USE_CRNL 7587 /* translate <CR><NL> into <NL> */ 7588 if (p != NULL) 7589 { 7590 char_u *s, *d; 7591 7592 d = p; 7593 for (s = p; *s; ++s) 7594 { 7595 if (s[0] == CAR && s[1] == NL) 7596 ++s; 7597 *d++ = *s; 7598 } 7599 *d = NUL; 7600 } 7601 # endif 7602 #endif 7603 retvar->var_type = VAR_STRING; 7604 retvar->var_val.var_string = p; 7605 } 7606 7607 /* 7608 * "submatch()" function 7609 */ 7610 static void 7611 f_submatch(argvars, retvar) 7612 VAR argvars; 7613 VAR retvar; 7614 { 7615 retvar->var_type = VAR_STRING; 7616 retvar->var_val.var_string = reg_submatch((int)get_var_number(&argvars[0])); 7617 } 7618 7619 /* 7620 * "substitute()" function 7621 */ 7622 static void 7623 f_substitute(argvars, retvar) 7624 VAR argvars; 7625 VAR retvar; 7626 { 7627 char_u patbuf[NUMBUFLEN]; 7628 char_u subbuf[NUMBUFLEN]; 7629 char_u flagsbuf[NUMBUFLEN]; 7630 7631 retvar->var_type = VAR_STRING; 7632 retvar->var_val.var_string = do_string_sub( 7633 get_var_string(&argvars[0]), 7634 get_var_string_buf(&argvars[1], patbuf), 7635 get_var_string_buf(&argvars[2], subbuf), 7636 get_var_string_buf(&argvars[3], flagsbuf)); 7637 } 7638 7639 /* 7640 * "tempname()" function 7641 */ 7642 /*ARGSUSED*/ 7643 static void 7644 f_tempname(argvars, retvar) 7645 VAR argvars; 7646 VAR retvar; 7647 { 7648 static int x = 'A'; 7649 7650 retvar->var_type = VAR_STRING; 7651 retvar->var_val.var_string = vim_tempname(x); 7652 7653 /* Advance 'x' to use A-Z and 0-9, so that there are at least 34 different 7654 * names. Skip 'I' and 'O', they are used for shell redirection. */ 7655 do 7656 { 7657 if (x == 'Z') 7658 x = '0'; 7659 else if (x == '9') 7660 x = 'A'; 7661 else 7662 { 7663 #ifdef EBCDIC 7664 if (x == 'I') 7665 x = 'J'; 7666 else if (x == 'R') 7667 x = 'S'; 7668 else 7669 #endif 7670 ++x; 7671 } 7672 } while (x == 'I' || x == 'O'); 7673 } 7674 7675 /* 7676 * "tolower(string)" function 7677 */ 7678 static void 7679 f_tolower(argvars, retvar) 7680 VAR argvars; 7681 VAR retvar; 7682 { 7683 char_u *p; 7684 7685 p = vim_strsave(get_var_string(&argvars[0])); 7686 retvar->var_type = VAR_STRING; 7687 retvar->var_val.var_string = p; 7688 7689 if (p != NULL) 7690 while (*p != NUL) 7691 { 7692 #ifdef FEAT_MBYTE 7693 int l; 7694 7695 if (enc_utf8) 7696 { 7697 int c, lc; 7698 7699 c = utf_ptr2char(p); 7700 lc = utf_tolower(c); 7701 l = utf_ptr2len_check(p); 7702 /* TODO: reallocate string when byte count changes. */ 7703 if (utf_char2len(lc) == l) 7704 utf_char2bytes(lc, p); 7705 p += l; 7706 } 7707 else if (has_mbyte && (l = (*mb_ptr2len_check)(p)) > 1) 7708 p += l; /* skip multi-byte character */ 7709 else 7710 #endif 7711 { 7712 *p = TOLOWER_LOC(*p); /* note that tolower() can be a macro */ 7713 ++p; 7714 } 7715 } 7716 } 7717 7718 /* 7719 * "toupper(string)" function 7720 */ 7721 static void 7722 f_toupper(argvars, retvar) 7723 VAR argvars; 7724 VAR retvar; 7725 { 7726 char_u *p; 7727 7728 p = vim_strsave(get_var_string(&argvars[0])); 7729 retvar->var_type = VAR_STRING; 7730 retvar->var_val.var_string = p; 7731 7732 if (p != NULL) 7733 while (*p != NUL) 7734 { 7735 #ifdef FEAT_MBYTE 7736 int l; 7737 7738 if (enc_utf8) 7739 { 7740 int c, uc; 7741 7742 c = utf_ptr2char(p); 7743 uc = utf_toupper(c); 7744 l = utf_ptr2len_check(p); 7745 /* TODO: reallocate string when byte count changes. */ 7746 if (utf_char2len(uc) == l) 7747 utf_char2bytes(uc, p); 7748 p += l; 7749 } 7750 else if (has_mbyte && (l = (*mb_ptr2len_check)(p)) > 1) 7751 p += l; /* skip multi-byte character */ 7752 else 7753 #endif 7754 { 7755 *p = TOUPPER_LOC(*p); /* note that toupper() can be a macro */ 7756 p++; 7757 } 7758 } 7759 } 7760 7761 /* 7762 * "tr(string, fromstr, tostr)" function 7763 */ 7764 static void 7765 f_tr(argvars, retvar) 7766 VAR argvars; 7767 VAR retvar; 7768 { 7769 char_u *instr; 7770 char_u *fromstr; 7771 char_u *tostr; 7772 char_u *p; 7773 #ifdef FEAT_MBYTE 7774 int inlen; 7775 int fromlen; 7776 int tolen; 7777 int idx; 7778 char_u *cpstr; 7779 int cplen; 7780 int first = TRUE; 7781 #endif 7782 char_u buf[NUMBUFLEN]; 7783 char_u buf2[NUMBUFLEN]; 7784 garray_T ga; 7785 7786 instr = get_var_string(&argvars[0]); 7787 fromstr = get_var_string_buf(&argvars[1], buf); 7788 tostr = get_var_string_buf(&argvars[2], buf2); 7789 7790 /* Default return value: empty string. */ 7791 retvar->var_type = VAR_STRING; 7792 retvar->var_val.var_string = NULL; 7793 ga_init2(&ga, (int)sizeof(char), 80); 7794 7795 #ifdef FEAT_MBYTE 7796 if (!has_mbyte) 7797 #endif 7798 /* not multi-byte: fromstr and tostr must be the same length */ 7799 if (STRLEN(fromstr) != STRLEN(tostr)) 7800 { 7801 #ifdef FEAT_MBYTE 7802 error: 7803 #endif 7804 EMSG2(_(e_invarg2), fromstr); 7805 ga_clear(&ga); 7806 return; 7807 } 7808 7809 /* fromstr and tostr have to contain the same number of chars */ 7810 while (*instr != NUL) 7811 { 7812 #ifdef FEAT_MBYTE 7813 if (has_mbyte) 7814 { 7815 inlen = mb_ptr2len_check(instr); 7816 cpstr = instr; 7817 cplen = inlen; 7818 idx = 0; 7819 for (p = fromstr; *p != NUL; p += fromlen) 7820 { 7821 fromlen = mb_ptr2len_check(p); 7822 if (fromlen == inlen && STRNCMP(instr, p, inlen) == 0) 7823 { 7824 for (p = tostr; *p != NUL; p += tolen) 7825 { 7826 tolen = mb_ptr2len_check(p); 7827 if (idx-- == 0) 7828 { 7829 cplen = tolen; 7830 cpstr = p; 7831 break; 7832 } 7833 } 7834 if (*p == NUL) /* tostr is shorter than fromstr */ 7835 goto error; 7836 break; 7837 } 7838 ++idx; 7839 } 7840 7841 if (first && cpstr == instr) 7842 { 7843 /* Check that fromstr and tostr have the same number of 7844 * (multi-byte) characters. Done only once when a character 7845 * of instr doesn't appear in fromstr. */ 7846 first = FALSE; 7847 for (p = tostr; *p != NUL; p += tolen) 7848 { 7849 tolen = mb_ptr2len_check(p); 7850 --idx; 7851 } 7852 if (idx != 0) 7853 goto error; 7854 } 7855 7856 ga_grow(&ga, cplen); 7857 mch_memmove((char *)ga.ga_data + ga.ga_len, cpstr, (size_t)cplen); 7858 ga.ga_len += cplen; 7859 ga.ga_room -= cplen; 7860 7861 instr += inlen; 7862 } 7863 else 7864 #endif 7865 { 7866 /* When not using multi-byte chars we can do it faster. */ 7867 p = vim_strchr(fromstr, *instr); 7868 if (p != NULL) 7869 ga_append(&ga, tostr[p - fromstr]); 7870 else 7871 ga_append(&ga, *instr); 7872 ++instr; 7873 } 7874 } 7875 7876 retvar->var_val.var_string = ga.ga_data; 7877 } 7878 7879 /* 7880 * "type(expr)" function 7881 */ 7882 static void 7883 f_type(argvars, retvar) 7884 VAR argvars; 7885 VAR retvar; 7886 { 7887 if (argvars[0].var_type == VAR_NUMBER) 7888 retvar->var_val.var_number = 0; 7889 else 7890 retvar->var_val.var_number = 1; 7891 } 7892 7893 /* 7894 * "virtcol(string)" function 7895 */ 7896 static void 7897 f_virtcol(argvars, retvar) 7898 VAR argvars; 7899 VAR retvar; 7900 { 7901 colnr_T vcol = 0; 7902 pos_T *fp; 7903 7904 fp = var2fpos(&argvars[0], FALSE); 7905 if (fp != NULL && fp->lnum <= curbuf->b_ml.ml_line_count) 7906 { 7907 getvvcol(curwin, fp, NULL, NULL, &vcol); 7908 ++vcol; 7909 } 7910 7911 retvar->var_val.var_number = vcol; 7912 } 7913 7914 /* 7915 * "visualmode()" function 7916 */ 7917 /*ARGSUSED*/ 7918 static void 7919 f_visualmode(argvars, retvar) 7920 VAR argvars; 7921 VAR retvar; 7922 { 7923 #ifdef FEAT_VISUAL 7924 char_u str[2]; 7925 7926 retvar->var_type = VAR_STRING; 7927 str[0] = curbuf->b_visual_mode_eval; 7928 str[1] = NUL; 7929 retvar->var_val.var_string = vim_strsave(str); 7930 7931 /* A non-zero number or non-empty string argument: reset mode. */ 7932 if ((argvars[0].var_type == VAR_NUMBER 7933 && argvars[0].var_val.var_number != 0) 7934 || (argvars[0].var_type == VAR_STRING 7935 && *get_var_string(&argvars[0]) != NUL)) 7936 curbuf->b_visual_mode_eval = NUL; 7937 #else 7938 retvar->var_val.var_number = 0; /* return anything, it won't work anyway */ 7939 #endif 7940 } 7941 7942 /* 7943 * "winbufnr(nr)" function 7944 */ 7945 static void 7946 f_winbufnr(argvars, retvar) 7947 VAR argvars; 7948 VAR retvar; 7949 { 7950 win_T *wp; 7951 7952 wp = find_win_by_nr(&argvars[0]); 7953 if (wp == NULL) 7954 retvar->var_val.var_number = -1; 7955 else 7956 retvar->var_val.var_number = wp->w_buffer->b_fnum; 7957 } 7958 7959 /* 7960 * "wincol()" function 7961 */ 7962 /*ARGSUSED*/ 7963 static void 7964 f_wincol(argvars, retvar) 7965 VAR argvars; 7966 VAR retvar; 7967 { 7968 validate_cursor(); 7969 retvar->var_val.var_number = curwin->w_wcol + 1; 7970 } 7971 7972 /* 7973 * "winheight(nr)" function 7974 */ 7975 static void 7976 f_winheight(argvars, retvar) 7977 VAR argvars; 7978 VAR retvar; 7979 { 7980 win_T *wp; 7981 7982 wp = find_win_by_nr(&argvars[0]); 7983 if (wp == NULL) 7984 retvar->var_val.var_number = -1; 7985 else 7986 retvar->var_val.var_number = wp->w_height; 7987 } 7988 7989 /* 7990 * "winline()" function 7991 */ 7992 /*ARGSUSED*/ 7993 static void 7994 f_winline(argvars, retvar) 7995 VAR argvars; 7996 VAR retvar; 7997 { 7998 validate_cursor(); 7999 retvar->var_val.var_number = curwin->w_wrow + 1; 8000 } 8001 8002 /* 8003 * "winnr()" function 8004 */ 8005 /* ARGSUSED */ 8006 static void 8007 f_winnr(argvars, retvar) 8008 VAR argvars; 8009 VAR retvar; 8010 { 8011 int nr = 1; 8012 #ifdef FEAT_WINDOWS 8013 win_T *wp; 8014 win_T *twin = curwin; 8015 char_u *arg; 8016 8017 if (argvars[0].var_type != VAR_UNKNOWN) 8018 { 8019 arg = get_var_string(&argvars[0]); 8020 if (STRCMP(arg, "$") == 0) 8021 twin = lastwin; 8022 else if (STRCMP(arg, "#") == 0) 8023 { 8024 twin = prevwin; 8025 if (prevwin == NULL) 8026 nr = 0; 8027 } 8028 else 8029 { 8030 EMSG2(_(e_invexpr2), arg); 8031 nr = 0; 8032 } 8033 } 8034 8035 if (nr > 0) 8036 for (wp = firstwin; wp != twin; wp = wp->w_next) 8037 ++nr; 8038 #endif 8039 retvar->var_val.var_number = nr; 8040 } 8041 8042 /* 8043 * "winrestcmd()" function 8044 */ 8045 /* ARGSUSED */ 8046 static void 8047 f_winrestcmd(argvars, retvar) 8048 VAR argvars; 8049 VAR retvar; 8050 { 8051 #ifdef FEAT_WINDOWS 8052 win_T *wp; 8053 int winnr = 1; 8054 garray_T ga; 8055 char_u buf[50]; 8056 8057 ga_init2(&ga, (int)sizeof(char), 70); 8058 for (wp = firstwin; wp != NULL; wp = wp->w_next) 8059 { 8060 sprintf((char *)buf, "%dresize %d|", winnr, wp->w_height); 8061 ga_concat(&ga, buf); 8062 # ifdef FEAT_VERTSPLIT 8063 sprintf((char *)buf, "vert %dresize %d|", winnr, wp->w_width); 8064 ga_concat(&ga, buf); 8065 # endif 8066 ++winnr; 8067 } 8068 8069 retvar->var_val.var_string = ga.ga_data; 8070 #else 8071 retvar->var_val.var_string = NULL; 8072 #endif 8073 retvar->var_type = VAR_STRING; 8074 } 8075 8076 /* 8077 * "winwidth(nr)" function 8078 */ 8079 static void 8080 f_winwidth(argvars, retvar) 8081 VAR argvars; 8082 VAR retvar; 8083 { 8084 win_T *wp; 8085 8086 wp = find_win_by_nr(&argvars[0]); 8087 if (wp == NULL) 8088 retvar->var_val.var_number = -1; 8089 else 8090 #ifdef FEAT_VERTSPLIT 8091 retvar->var_val.var_number = wp->w_width; 8092 #else 8093 retvar->var_val.var_number = Columns; 8094 #endif 8095 } 8096 8097 static win_T * 8098 find_win_by_nr(vp) 8099 VAR vp; 8100 { 8101 #ifdef FEAT_WINDOWS 8102 win_T *wp; 8103 #endif 8104 int nr; 8105 8106 nr = get_var_number(vp); 8107 8108 #ifdef FEAT_WINDOWS 8109 if (nr == 0) 8110 return curwin; 8111 8112 for (wp = firstwin; wp != NULL; wp = wp->w_next) 8113 if (--nr <= 0) 8114 break; 8115 return wp; 8116 #else 8117 if (nr == 0 || nr == 1) 8118 return curwin; 8119 return NULL; 8120 #endif 8121 } 8122 8123 /* 8124 * Translate a String variable into a position. 8125 */ 8126 static pos_T * 8127 var2fpos(varp, lnum) 8128 VAR varp; 8129 int lnum; /* TRUE when $ is last line */ 8130 { 8131 char_u *name; 8132 static pos_T pos; 8133 pos_T *pp; 8134 8135 name = get_var_string(varp); 8136 if (name[0] == '.') /* cursor */ 8137 return &curwin->w_cursor; 8138 if (name[0] == '\'') /* mark */ 8139 { 8140 pp = getmark(name[1], FALSE); 8141 if (pp == NULL || pp == (pos_T *)-1 || pp->lnum <= 0) 8142 return NULL; 8143 return pp; 8144 } 8145 if (name[0] == '$') /* last column or line */ 8146 { 8147 if (lnum) 8148 { 8149 pos.lnum = curbuf->b_ml.ml_line_count; 8150 pos.col = 0; 8151 } 8152 else 8153 { 8154 pos.lnum = curwin->w_cursor.lnum; 8155 pos.col = (colnr_T)STRLEN(ml_get_curline()); 8156 } 8157 return &pos; 8158 } 8159 return NULL; 8160 } 8161 8162 /* 8163 * Get the length of an environment variable name. 8164 * Advance "arg" to the first character after the name. 8165 * Return 0 for error. 8166 */ 8167 static int 8168 get_env_len(arg) 8169 char_u **arg; 8170 { 8171 char_u *p; 8172 int len; 8173 8174 for (p = *arg; vim_isIDc(*p); ++p) 8175 ; 8176 if (p == *arg) /* no name found */ 8177 return 0; 8178 8179 len = (int)(p - *arg); 8180 *arg = p; 8181 return len; 8182 } 8183 8184 /* 8185 * Get the length of the name of a function or internal variable. 8186 * "arg" is advanced to the first non-white character after the name. 8187 * Return 0 if something is wrong. 8188 */ 8189 static int 8190 get_id_len(arg) 8191 char_u **arg; 8192 { 8193 char_u *p; 8194 int len; 8195 8196 /* Find the end of the name. */ 8197 for (p = *arg; eval_isnamec(*p); ++p) 8198 ; 8199 if (p == *arg) /* no name found */ 8200 return 0; 8201 8202 len = (int)(p - *arg); 8203 *arg = skipwhite(p); 8204 8205 return len; 8206 } 8207 8208 /* 8209 * Get the length of the name of a function. 8210 * "arg" is advanced to the first non-white character after the name. 8211 * Return 0 if something is wrong. 8212 * If the name contains 'magic' {}'s, expand them and return the 8213 * expanded name in an allocated string via 'alias' - caller must free. 8214 */ 8215 static int 8216 get_func_len(arg, alias, evaluate) 8217 char_u **arg; 8218 char_u **alias; 8219 int evaluate; 8220 { 8221 int len; 8222 #ifdef FEAT_MAGIC_BRACES 8223 char_u *p; 8224 char_u *expr_start; 8225 char_u *expr_end; 8226 #endif 8227 8228 *alias = NULL; /* default to no alias */ 8229 8230 if ((*arg)[0] == K_SPECIAL && (*arg)[1] == KS_EXTRA 8231 && (*arg)[2] == (int)KE_SNR) 8232 { 8233 /* hard coded <SNR>, already translated */ 8234 *arg += 3; 8235 return get_id_len(arg) + 3; 8236 } 8237 len = eval_fname_script(*arg); 8238 if (len > 0) 8239 { 8240 /* literal "<SID>", "s:" or "<SNR>" */ 8241 *arg += len; 8242 } 8243 8244 #ifdef FEAT_MAGIC_BRACES 8245 /* 8246 * Find the end of the name; 8247 */ 8248 p = find_name_end(*arg, &expr_start, &expr_end); 8249 /* check for {} construction */ 8250 if (expr_start != NULL) 8251 { 8252 char_u *temp_string; 8253 8254 if (!evaluate) 8255 { 8256 len += (int)(p - *arg); 8257 *arg = skipwhite(p); 8258 return len; 8259 } 8260 8261 /* 8262 * Include any <SID> etc in the expanded string: 8263 * Thus the -len here. 8264 */ 8265 temp_string = make_expanded_name(*arg - len, expr_start, expr_end, p); 8266 if (temp_string == NULL) 8267 return 0; 8268 *alias = temp_string; 8269 *arg = skipwhite(p); 8270 return (int)STRLEN(temp_string); 8271 } 8272 #endif 8273 8274 len += get_id_len(arg); 8275 if (len == 0) 8276 EMSG2(_(e_invexpr2), *arg); 8277 8278 return len; 8279 } 8280 8281 static char_u * 8282 find_name_end(arg, expr_start, expr_end) 8283 char_u *arg; 8284 char_u **expr_start; 8285 char_u **expr_end; 8286 { 8287 int nesting = 0; 8288 char_u *p; 8289 8290 *expr_start = NULL; 8291 *expr_end = NULL; 8292 8293 for (p = arg; (*p != NUL && (eval_isnamec(*p) || nesting != 0)); ++p) 8294 { 8295 #ifdef FEAT_MAGIC_BRACES 8296 if (*p == '{') 8297 { 8298 nesting++; 8299 if (*expr_start == NULL) 8300 *expr_start = p; 8301 } 8302 else if (*p == '}') 8303 { 8304 nesting--; 8305 if (nesting == 0 && *expr_end == NULL) 8306 *expr_end = p; 8307 } 8308 #endif 8309 } 8310 8311 return p; 8312 } 8313 8314 /* 8315 * Return TRUE if character "c" can be used in a variable or function name. 8316 */ 8317 static int 8318 eval_isnamec(c) 8319 int c; 8320 { 8321 return (ASCII_ISALNUM(c) || c == '_' || c == ':' 8322 #ifdef FEAT_MAGIC_BRACES 8323 || c == '{' || c == '}' 8324 #endif 8325 ); 8326 } 8327 8328 /* 8329 * Find a v: variable. 8330 * Return it's index, or -1 if not found. 8331 */ 8332 static int 8333 find_vim_var(name, len) 8334 char_u *name; 8335 int len; /* length of "name" */ 8336 { 8337 char_u *vname; 8338 int vlen; 8339 int i; 8340 8341 /* 8342 * Ignore "v:" for old built-in variables, require it for new ones. 8343 */ 8344 if (name[0] == 'v' && name[1] == ':') 8345 { 8346 vname = name + 2; 8347 vlen = len - 2; 8348 } 8349 else 8350 { 8351 vname = name; 8352 vlen = len; 8353 } 8354 for (i = 0; i < VV_LEN; ++i) 8355 if (vlen == vimvars[i].len && STRCMP(vname, vimvars[i].name) == 0 8356 && ((vimvars[i].flags & VV_COMPAT) || vname != name)) 8357 return i; 8358 return -1; 8359 } 8360 8361 /* 8362 * Set number v: variable to "val". 8363 */ 8364 void 8365 set_vim_var_nr(idx, val) 8366 int idx; 8367 long val; 8368 { 8369 vimvars[idx].val = (char_u *)val; 8370 } 8371 8372 /* 8373 * Get number v: variable value; 8374 */ 8375 long 8376 get_vim_var_nr(idx) 8377 int idx; 8378 { 8379 return (long)vimvars[idx].val; 8380 } 8381 8382 /* 8383 * Set v:count, v:count1 and v:prevcount. 8384 */ 8385 void 8386 set_vcount(count, count1) 8387 long count; 8388 long count1; 8389 { 8390 vimvars[VV_PREVCOUNT].val = vimvars[VV_COUNT].val; 8391 vimvars[VV_COUNT].val = (char_u *)count; 8392 vimvars[VV_COUNT1].val = (char_u *)count1; 8393 } 8394 8395 /* 8396 * Set string v: variable to a copy of "val". 8397 */ 8398 void 8399 set_vim_var_string(idx, val, len) 8400 int idx; 8401 char_u *val; 8402 int len; /* length of "val" to use or -1 (whole string) */ 8403 { 8404 vim_free(vimvars[idx].val); 8405 if (val == NULL) 8406 vimvars[idx].val = NULL; 8407 else if (len == -1) 8408 vimvars[idx].val = vim_strsave(val); 8409 else 8410 vimvars[idx].val = vim_strnsave(val, len); 8411 } 8412 8413 /* 8414 * Set v:register if needed. 8415 */ 8416 void 8417 set_reg_var(c) 8418 int c; 8419 { 8420 char_u regname; 8421 8422 if (c == 0 || c == ' ') 8423 regname = '"'; 8424 else 8425 regname = c; 8426 /* Avoid free/alloc when the value is already right. */ 8427 if (vimvars[VV_REG].val == NULL || vimvars[VV_REG].val[0] != c) 8428 set_vim_var_string(VV_REG, ®name, 1); 8429 } 8430 8431 /* 8432 * Get or set v:exception. If "oldval" == NULL, return the current value. 8433 * Otherwise, restore the value to "oldval" and return NULL. 8434 * Must always be called in pairs to save and restore v:exception! Does not 8435 * take care of memory allocations. 8436 */ 8437 char_u * 8438 v_exception(oldval) 8439 char_u *oldval; 8440 { 8441 if (oldval == NULL) 8442 return vimvars[VV_EXCEPTION].val; 8443 8444 vimvars[VV_EXCEPTION].val = oldval; 8445 return NULL; 8446 } 8447 8448 /* 8449 * Get or set v:throwpoint. If "oldval" == NULL, return the current value. 8450 * Otherwise, restore the value to "oldval" and return NULL. 8451 * Must always be called in pairs to save and restore v:throwpoint! Does not 8452 * take care of memory allocations. 8453 */ 8454 char_u * 8455 v_throwpoint(oldval) 8456 char_u *oldval; 8457 { 8458 if (oldval == NULL) 8459 return vimvars[VV_THROWPOINT].val; 8460 8461 vimvars[VV_THROWPOINT].val = oldval; 8462 return NULL; 8463 } 8464 8465 #if defined(FEAT_AUTOCMD) || defined(PROTO) 8466 /* 8467 * Set v:cmdarg. 8468 * If "eap" != NULL, use "eap" to generate the value and return the old value. 8469 * If "oldarg" != NULL, restore the value to "oldarg" and return NULL. 8470 * Must always be called in pairs! 8471 */ 8472 char_u * 8473 set_cmdarg(eap, oldarg) 8474 exarg_T *eap; 8475 char_u *oldarg; 8476 { 8477 char_u *oldval; 8478 char_u *newval; 8479 unsigned len; 8480 8481 oldval = vimvars[VV_CMDARG].val; 8482 if (eap != NULL) 8483 { 8484 if (eap->force_bin == FORCE_BIN) 8485 len = 6; 8486 else if (eap->force_bin == FORCE_NOBIN) 8487 len = 8; 8488 else 8489 len = 0; 8490 if (eap->force_ff != 0) 8491 len += (unsigned)STRLEN(eap->cmd + eap->force_ff) + 6; 8492 # ifdef FEAT_MBYTE 8493 if (eap->force_enc != 0) 8494 len += (unsigned)STRLEN(eap->cmd + eap->force_enc) + 7; 8495 # endif 8496 8497 newval = alloc(len + 1); 8498 if (newval == NULL) 8499 return NULL; 8500 8501 if (eap->force_bin == FORCE_BIN) 8502 sprintf((char *)newval, " ++bin"); 8503 else if (eap->force_bin == FORCE_NOBIN) 8504 sprintf((char *)newval, " ++nobin"); 8505 else 8506 *newval = NUL; 8507 if (eap->force_ff != 0) 8508 sprintf((char *)newval + STRLEN(newval), " ++ff=%s", 8509 eap->cmd + eap->force_ff); 8510 # ifdef FEAT_MBYTE 8511 if (eap->force_enc != 0) 8512 sprintf((char *)newval + STRLEN(newval), " ++enc=%s", 8513 eap->cmd + eap->force_enc); 8514 # endif 8515 vimvars[VV_CMDARG].val = newval; 8516 return oldval; 8517 } 8518 8519 vim_free(oldval); 8520 vimvars[VV_CMDARG].val = oldarg; 8521 return NULL; 8522 } 8523 #endif 8524 8525 /* 8526 * Get the value of internal variable "name". 8527 * Return OK or FAIL. 8528 */ 8529 static int 8530 get_var_var(name, len, retvar) 8531 char_u *name; 8532 int len; /* length of "name" */ 8533 VAR retvar; /* NULL when only checking existence */ 8534 { 8535 int ret = OK; 8536 int type = VAR_UNKNOWN; 8537 long number = 1; 8538 char_u *string = NULL; 8539 VAR v; 8540 int cc; 8541 int i; 8542 8543 /* truncate the name, so that we can use strcmp() */ 8544 cc = name[len]; 8545 name[len] = NUL; 8546 8547 /* 8548 * Check for "b:changedtick". 8549 */ 8550 if (STRCMP(name, "b:changedtick") == 0) 8551 { 8552 type = VAR_NUMBER; 8553 number = curbuf->b_changedtick; 8554 } 8555 8556 /* 8557 * Check for built-in v: variables. 8558 */ 8559 else if ((i = find_vim_var(name, len)) >= 0) 8560 { 8561 type = vimvars[i].type; 8562 number = (long)vimvars[i].val; 8563 string = vimvars[i].val; 8564 } 8565 8566 /* 8567 * Check for user-defined variables. 8568 */ 8569 else 8570 { 8571 v = find_var(name, FALSE); 8572 if (v != NULL) 8573 { 8574 type = v->var_type; 8575 number = v->var_val.var_number; 8576 string = v->var_val.var_string; 8577 } 8578 } 8579 8580 if (type == VAR_UNKNOWN) 8581 { 8582 if (retvar != NULL) 8583 EMSG2(_("E121: Undefined variable: %s"), name); 8584 ret = FAIL; 8585 } 8586 else if (retvar != NULL) 8587 { 8588 retvar->var_type = type; 8589 if (type == VAR_NUMBER) 8590 retvar->var_val.var_number = number; 8591 else if (type == VAR_STRING) 8592 { 8593 if (string != NULL) 8594 string = vim_strsave(string); 8595 retvar->var_val.var_string = string; 8596 } 8597 } 8598 8599 name[len] = cc; 8600 8601 return ret; 8602 } 8603 8604 /* 8605 * Allocate memory for a variable, and make it emtpy (0 or NULL value). 8606 */ 8607 static VAR 8608 alloc_var() 8609 { 8610 return (VAR)alloc_clear((unsigned)sizeof(var)); 8611 } 8612 8613 /* 8614 * Allocate memory for a variable, and assign a string to it. 8615 * The string "s" must have been allocated, it is consumed. 8616 * Return NULL for out of memory, the variable otherwise. 8617 */ 8618 static VAR 8619 alloc_string_var(s) 8620 char_u *s; 8621 { 8622 VAR retvar; 8623 8624 retvar = alloc_var(); 8625 if (retvar != NULL) 8626 { 8627 retvar->var_type = VAR_STRING; 8628 retvar->var_val.var_string = s; 8629 } 8630 else 8631 vim_free(s); 8632 return retvar; 8633 } 8634 8635 /* 8636 * Free the memory for a variable. 8637 */ 8638 static void 8639 free_var(varp) 8640 VAR varp; 8641 { 8642 if (varp != NULL) 8643 { 8644 if (varp->var_type == VAR_STRING) 8645 vim_free(varp->var_val.var_string); 8646 vim_free(varp->var_name); 8647 vim_free(varp); 8648 } 8649 } 8650 8651 /* 8652 * Free the memory for a variable value and set the value to NULL or 0. 8653 */ 8654 static void 8655 clear_var(varp) 8656 VAR varp; 8657 { 8658 if (varp != NULL) 8659 { 8660 if (varp->var_type == VAR_STRING) 8661 { 8662 vim_free(varp->var_val.var_string); 8663 varp->var_val.var_string = NULL; 8664 } 8665 else 8666 varp->var_val.var_number = 0; 8667 } 8668 } 8669 8670 /* 8671 * Get the number value of a variable. 8672 * If it is a String variable, uses vim_str2nr(). 8673 */ 8674 static long 8675 get_var_number(varp) 8676 VAR varp; 8677 { 8678 long n; 8679 8680 if (varp->var_type == VAR_NUMBER) 8681 return (long)(varp->var_val.var_number); 8682 else if (varp->var_type == VAR_UNKNOWN || varp->var_val.var_string == NULL) 8683 return 0L; 8684 else 8685 { 8686 vim_str2nr(varp->var_val.var_string, NULL, NULL, TRUE, TRUE, &n, NULL); 8687 return n; 8688 } 8689 } 8690 8691 /* 8692 * Get the lnum from the first argument. Also accepts ".", "$", etc. 8693 */ 8694 static linenr_T 8695 get_var_lnum(argvars) 8696 VAR argvars; 8697 { 8698 var retvar; 8699 linenr_T lnum; 8700 8701 lnum = get_var_number(&argvars[0]); 8702 if (lnum == 0) /* no valid number, try using line() */ 8703 { 8704 retvar.var_type = VAR_NUMBER; 8705 f_line(argvars, &retvar); 8706 lnum = retvar.var_val.var_number; 8707 clear_var(&retvar); 8708 } 8709 return lnum; 8710 } 8711 8712 /* 8713 * Get the string value of a variable. 8714 * If it is a Number variable, the number is converted into a string. 8715 * get_var_string() uses a single, static buffer. YOU CAN ONLY USE IT ONCE! 8716 * get_var_string_buf() uses a given buffer. 8717 * If the String variable has never been set, return an empty string. 8718 * Never returns NULL; 8719 */ 8720 static char_u * 8721 get_var_string(varp) 8722 VAR varp; 8723 { 8724 static char_u mybuf[NUMBUFLEN]; 8725 8726 return get_var_string_buf(varp, mybuf); 8727 } 8728 8729 static char_u * 8730 get_var_string_buf(varp, buf) 8731 VAR varp; 8732 char_u *buf; 8733 { 8734 if (varp->var_type == VAR_NUMBER) 8735 { 8736 sprintf((char *)buf, "%ld", (long)varp->var_val.var_number); 8737 return buf; 8738 } 8739 else if (varp->var_val.var_string == NULL) 8740 return (char_u *)""; 8741 else 8742 return varp->var_val.var_string; 8743 } 8744 8745 /* 8746 * Find variable "name" in the list of variables. 8747 * Return a pointer to it if found, NULL if not found. 8748 */ 8749 static VAR 8750 find_var(name, writing) 8751 char_u *name; 8752 int writing; 8753 { 8754 int i; 8755 char_u *varname; 8756 garray_T *gap; 8757 8758 /* Check for function arguments "a:" */ 8759 if (name[0] == 'a' && name[1] == ':') 8760 { 8761 if (writing) 8762 { 8763 EMSG2(_(e_readonlyvar), name); 8764 return NULL; 8765 } 8766 name += 2; 8767 if (current_funccal == NULL) 8768 return NULL; 8769 if (VIM_ISDIGIT(*name)) 8770 { 8771 i = atol((char *)name); 8772 if (i == 0) /* a:0 */ 8773 return ¤t_funccal->a0_var; 8774 i += current_funccal->func->args.ga_len; 8775 if (i > current_funccal->argcount) /* a:999 */ 8776 return NULL; 8777 return &(current_funccal->argvars[i - 1]); /* a:1, a:2, etc. */ 8778 } 8779 if (STRCMP(name, "firstline") == 0) 8780 return &(current_funccal->firstline); 8781 if (STRCMP(name, "lastline") == 0) 8782 return &(current_funccal->lastline); 8783 for (i = 0; i < current_funccal->func->args.ga_len; ++i) 8784 if (STRCMP(name, ((char_u **) 8785 (current_funccal->func->args.ga_data))[i]) == 0) 8786 return &(current_funccal->argvars[i]); /* a:name */ 8787 return NULL; 8788 } 8789 8790 gap = find_var_ga(name, &varname); 8791 if (gap == NULL) 8792 return NULL; 8793 return find_var_in_ga(gap, varname); 8794 } 8795 8796 static VAR 8797 find_var_in_ga(gap, varname) 8798 garray_T *gap; 8799 char_u *varname; 8800 { 8801 int i; 8802 8803 for (i = gap->ga_len; --i >= 0; ) 8804 if (VAR_GAP_ENTRY(i, gap).var_name != NULL 8805 && STRCMP(VAR_GAP_ENTRY(i, gap).var_name, varname) == 0) 8806 break; 8807 if (i < 0) 8808 return NULL; 8809 return &VAR_GAP_ENTRY(i, gap); 8810 } 8811 8812 /* 8813 * Find the growarray and start of name without ':' for a variable name. 8814 */ 8815 static garray_T * 8816 find_var_ga(name, varname) 8817 char_u *name; 8818 char_u **varname; 8819 { 8820 if (name[1] != ':') 8821 { 8822 /* If not "x:name" there must not be any ":" in the name. */ 8823 if (vim_strchr(name, ':') != NULL) 8824 return NULL; 8825 *varname = name; 8826 if (current_funccal == NULL) 8827 return &variables; /* global variable */ 8828 return ¤t_funccal->l_vars; /* local function variable */ 8829 } 8830 *varname = name + 2; 8831 if (*name == 'b') /* buffer variable */ 8832 return &curbuf->b_vars; 8833 if (*name == 'w') /* window variable */ 8834 return &curwin->w_vars; 8835 if (*name == 'g') /* global variable */ 8836 return &variables; 8837 if (*name == 'l' && current_funccal != NULL)/* local function variable */ 8838 return ¤t_funccal->l_vars; 8839 if (*name == 's' /* script variable */ 8840 && current_SID > 0 && current_SID <= ga_scripts.ga_len) 8841 return &SCRIPT_VARS(current_SID); 8842 return NULL; 8843 } 8844 8845 /* 8846 * Get the string value of a (global/local) variable. 8847 * Returns NULL when it doesn't exist. 8848 */ 8849 char_u * 8850 get_var_value(name) 8851 char_u *name; 8852 { 8853 VAR v; 8854 8855 v = find_var(name, FALSE); 8856 if (v == NULL) 8857 return NULL; 8858 return get_var_string(v); 8859 } 8860 8861 /* 8862 * Allocate a new growarry for a sourced script. It will be used while 8863 * sourcing this script and when executing functions defined in the script. 8864 */ 8865 void 8866 new_script_vars(id) 8867 scid_T id; 8868 { 8869 if (ga_grow(&ga_scripts, (int)(id - ga_scripts.ga_len)) == OK) 8870 { 8871 while (ga_scripts.ga_len < id) 8872 { 8873 var_init(&SCRIPT_VARS(ga_scripts.ga_len + 1)); 8874 ++ga_scripts.ga_len; 8875 --ga_scripts.ga_room; 8876 } 8877 } 8878 } 8879 8880 /* 8881 * Initialize internal variables for use. 8882 */ 8883 void 8884 var_init(gap) 8885 garray_T *gap; 8886 { 8887 ga_init2(gap, (int)sizeof(var), 4); 8888 } 8889 8890 /* 8891 * Clean up a list of internal variables. 8892 */ 8893 void 8894 var_clear(gap) 8895 garray_T *gap; 8896 { 8897 int i; 8898 8899 for (i = gap->ga_len; --i >= 0; ) 8900 var_free_one(&VAR_GAP_ENTRY(i, gap)); 8901 ga_clear(gap); 8902 } 8903 8904 static void 8905 var_free_one(v) 8906 VAR v; 8907 { 8908 vim_free(v->var_name); 8909 v->var_name = NULL; 8910 if (v->var_type == VAR_STRING) 8911 vim_free(v->var_val.var_string); 8912 v->var_val.var_string = NULL; 8913 } 8914 8915 /* 8916 * List the value of one internal variable. 8917 */ 8918 static void 8919 list_one_var(v, prefix) 8920 VAR v; 8921 char_u *prefix; 8922 { 8923 list_one_var_a(prefix, v->var_name, v->var_type, get_var_string(v)); 8924 } 8925 8926 /* 8927 * List the value of one "v:" variable. 8928 */ 8929 static void 8930 list_vim_var(i) 8931 int i; /* index in vimvars[] */ 8932 { 8933 char_u *p; 8934 char_u numbuf[NUMBUFLEN]; 8935 8936 if (vimvars[i].type == VAR_NUMBER) 8937 { 8938 p = numbuf; 8939 sprintf((char *)p, "%ld", (long)vimvars[i].val); 8940 } 8941 else if (vimvars[i].val == NULL) 8942 p = (char_u *)""; 8943 else 8944 p = vimvars[i].val; 8945 list_one_var_a((char_u *)"v:", (char_u *)vimvars[i].name, 8946 vimvars[i].type, p); 8947 } 8948 8949 static void 8950 list_one_var_a(prefix, name, type, string) 8951 char_u *prefix; 8952 char_u *name; 8953 int type; 8954 char_u *string; 8955 { 8956 msg_attr(prefix, 0); /* don't use msg(), it overwrites "v:statusmsg" */ 8957 if (name != NULL) /* "a:" vars don't have a name stored */ 8958 msg_puts(name); 8959 msg_putchar(' '); 8960 msg_advance(22); 8961 if (type == VAR_NUMBER) 8962 msg_putchar('#'); 8963 else 8964 msg_putchar(' '); 8965 msg_outtrans(string); 8966 } 8967 8968 /* 8969 * Set variable "name" to value in "varp". 8970 * If the variable already exists, the value is updated. 8971 * Otherwise the variable is created. 8972 */ 8973 static void 8974 set_var(name, varp) 8975 char_u *name; 8976 VAR varp; 8977 { 8978 int i; 8979 VAR v; 8980 char_u *varname; 8981 garray_T *gap; 8982 8983 /* 8984 * Handle setting internal v: variables. 8985 */ 8986 i = find_vim_var(name, (int)STRLEN(name)); 8987 if (i >= 0) 8988 { 8989 if (vimvars[i].flags & VV_RO) 8990 EMSG2(_(e_readonlyvar), name); 8991 else 8992 { 8993 if (vimvars[i].type == VAR_STRING) 8994 { 8995 vim_free(vimvars[i].val); 8996 vimvars[i].val = vim_strsave(get_var_string(varp)); 8997 } 8998 else 8999 vimvars[i].val = (char_u *)(long)varp->var_val.var_number; 9000 } 9001 return; 9002 } 9003 9004 v = find_var(name, TRUE); 9005 if (v != NULL) /* existing variable, only need to free string */ 9006 { 9007 if (v->var_type == VAR_STRING) 9008 vim_free(v->var_val.var_string); 9009 } 9010 else /* add a new variable */ 9011 { 9012 gap = find_var_ga(name, &varname); 9013 if (gap == NULL) /* illegal name */ 9014 { 9015 EMSG2(_("E461: Illegal variable name: %s"), name); 9016 return; 9017 } 9018 9019 /* Try to use an empty entry */ 9020 for (i = gap->ga_len; --i >= 0; ) 9021 if (VAR_GAP_ENTRY(i, gap).var_name == NULL) 9022 break; 9023 if (i < 0) /* need to allocate more room */ 9024 { 9025 if (ga_grow(gap, 1) == FAIL) 9026 return; 9027 i = gap->ga_len; 9028 } 9029 v = &VAR_GAP_ENTRY(i, gap); 9030 if ((v->var_name = vim_strsave(varname)) == NULL) 9031 return; 9032 if (i == gap->ga_len) 9033 { 9034 ++gap->ga_len; 9035 --gap->ga_room; 9036 } 9037 } 9038 copy_var(varp, v); 9039 } 9040 9041 static void 9042 copy_var(from, to) 9043 VAR from; 9044 VAR to; 9045 { 9046 to->var_type = from->var_type; 9047 if (from->var_type == VAR_STRING) 9048 to->var_val.var_string = vim_strsave(get_var_string(from)); 9049 else 9050 to->var_val.var_number = from->var_val.var_number; 9051 } 9052 9053 /* 9054 * ":echo expr1 ..." print each argument separated with a space, add a 9055 * newline at the end. 9056 * ":echon expr1 ..." print each argument plain. 9057 */ 9058 void 9059 ex_echo(eap) 9060 exarg_T *eap; 9061 { 9062 char_u *arg = eap->arg; 9063 var retvar; 9064 char_u *p; 9065 int needclr = TRUE; 9066 int atstart = TRUE; 9067 9068 if (eap->skip) 9069 ++emsg_skip; 9070 while (*arg != NUL && *arg != '|' && *arg != '\n' && !got_int) 9071 { 9072 p = arg; 9073 if (eval1(&arg, &retvar, !eap->skip) == FAIL) 9074 { 9075 /* 9076 * Report the invalid expression unless the expression evaluation 9077 * has been cancelled due to an aborting error, an interrupt, or an 9078 * exception. 9079 */ 9080 if (!aborting()) 9081 EMSG2(_(e_invexpr2), p); 9082 break; 9083 } 9084 if (!eap->skip) 9085 { 9086 if (atstart) 9087 { 9088 atstart = FALSE; 9089 /* Call msg_start() after eval1(), evaluating the expression 9090 * may cause a message to appear. */ 9091 if (eap->cmdidx == CMD_echo) 9092 msg_start(); 9093 } 9094 else if (eap->cmdidx == CMD_echo) 9095 msg_puts_attr((char_u *)" ", echo_attr); 9096 for (p = get_var_string(&retvar); *p != NUL && !got_int; ++p) 9097 if (*p == '\n' || *p == '\r' || *p == TAB) 9098 { 9099 if (*p != TAB && needclr) 9100 { 9101 /* remove any text still there from the command */ 9102 msg_clr_eos(); 9103 needclr = FALSE; 9104 } 9105 msg_putchar_attr(*p, echo_attr); 9106 } 9107 else 9108 { 9109 #ifdef FEAT_MBYTE 9110 if (has_mbyte) 9111 { 9112 int i = (*mb_ptr2len_check)(p); 9113 9114 (void)msg_outtrans_len_attr(p, i, echo_attr); 9115 p += i - 1; 9116 } 9117 else 9118 #endif 9119 (void)msg_outtrans_len_attr(p, 1, echo_attr); 9120 } 9121 } 9122 clear_var(&retvar); 9123 arg = skipwhite(arg); 9124 } 9125 eap->nextcmd = check_nextcmd(arg); 9126 9127 if (eap->skip) 9128 --emsg_skip; 9129 else 9130 { 9131 /* remove text that may still be there from the command */ 9132 if (needclr) 9133 msg_clr_eos(); 9134 if (eap->cmdidx == CMD_echo) 9135 msg_end(); 9136 } 9137 } 9138 9139 /* 9140 * ":echohl {name}". 9141 */ 9142 void 9143 ex_echohl(eap) 9144 exarg_T *eap; 9145 { 9146 int id; 9147 9148 id = syn_name2id(eap->arg); 9149 if (id == 0) 9150 echo_attr = 0; 9151 else 9152 echo_attr = syn_id2attr(id); 9153 } 9154 9155 /* 9156 * ":execute expr1 ..." execute the result of an expression. 9157 * ":echomsg expr1 ..." Print a message 9158 * ":echoerr expr1 ..." Print an error 9159 * Each gets spaces around each argument and a newline at the end for 9160 * echo commands 9161 */ 9162 void 9163 ex_execute(eap) 9164 exarg_T *eap; 9165 { 9166 char_u *arg = eap->arg; 9167 var retvar; 9168 int ret = OK; 9169 char_u *p; 9170 garray_T ga; 9171 int len; 9172 int save_did_emsg; 9173 9174 ga_init2(&ga, 1, 80); 9175 9176 if (eap->skip) 9177 ++emsg_skip; 9178 while (*arg != NUL && *arg != '|' && *arg != '\n') 9179 { 9180 p = arg; 9181 if (eval1(&arg, &retvar, !eap->skip) == FAIL) 9182 { 9183 /* 9184 * Report the invalid expression unless the expression evaluation 9185 * has been cancelled due to an aborting error, an interrupt, or an 9186 * exception. 9187 */ 9188 if (!aborting()) 9189 EMSG2(_(e_invexpr2), p); 9190 ret = FAIL; 9191 break; 9192 } 9193 9194 if (!eap->skip) 9195 { 9196 p = get_var_string(&retvar); 9197 len = (int)STRLEN(p); 9198 if (ga_grow(&ga, len + 2) == FAIL) 9199 { 9200 clear_var(&retvar); 9201 ret = FAIL; 9202 break; 9203 } 9204 if (ga.ga_len) 9205 { 9206 ((char_u *)(ga.ga_data))[ga.ga_len++] = ' '; 9207 --ga.ga_room; 9208 } 9209 STRCPY((char_u *)(ga.ga_data) + ga.ga_len, p); 9210 ga.ga_room -= len; 9211 ga.ga_len += len; 9212 } 9213 9214 clear_var(&retvar); 9215 arg = skipwhite(arg); 9216 } 9217 9218 if (ret != FAIL && ga.ga_data != NULL) 9219 { 9220 if (eap->cmdidx == CMD_echomsg) 9221 MSG_ATTR(ga.ga_data, echo_attr); 9222 else if (eap->cmdidx == CMD_echoerr) 9223 { 9224 /* We don't want to abort following commands, restore did_emsg. */ 9225 save_did_emsg = did_emsg; 9226 EMSG((char_u *)ga.ga_data); 9227 if (!force_abort) 9228 did_emsg = save_did_emsg; 9229 } 9230 else if (eap->cmdidx == CMD_execute) 9231 do_cmdline((char_u *)ga.ga_data, 9232 eap->getline, eap->cookie, DOCMD_NOWAIT|DOCMD_VERBOSE); 9233 } 9234 9235 ga_clear(&ga); 9236 9237 if (eap->skip) 9238 --emsg_skip; 9239 9240 eap->nextcmd = check_nextcmd(arg); 9241 } 9242 9243 /* 9244 * Skip over the name of an option: "&option", "&g:option" or "&l:option". 9245 * "arg" points to the "&" or '+' when called, to "option" when returning. 9246 * Returns NULL when no option name found. Otherwise pointer to the char 9247 * after the option name. 9248 */ 9249 static char_u * 9250 find_option_end(arg, opt_flags) 9251 char_u **arg; 9252 int *opt_flags; 9253 { 9254 char_u *p = *arg; 9255 9256 ++p; 9257 if (*p == 'g' && p[1] == ':') 9258 { 9259 *opt_flags = OPT_GLOBAL; 9260 p += 2; 9261 } 9262 else if (*p == 'l' && p[1] == ':') 9263 { 9264 *opt_flags = OPT_LOCAL; 9265 p += 2; 9266 } 9267 else 9268 *opt_flags = 0; 9269 9270 if (!ASCII_ISALPHA(*p)) 9271 return NULL; 9272 *arg = p; 9273 9274 if (p[0] == 't' && p[1] == '_' && p[2] != NUL && p[3] != NUL) 9275 p += 4; /* termcap option */ 9276 else 9277 while (ASCII_ISALPHA(*p)) 9278 ++p; 9279 return p; 9280 } 9281 9282 /* 9283 * ":function" 9284 */ 9285 void 9286 ex_function(eap) 9287 exarg_T *eap; 9288 { 9289 char_u *theline; 9290 int j; 9291 int c; 9292 #ifdef FEAT_MAGIC_BRACES 9293 int saved_did_emsg; 9294 #endif 9295 char_u *name = NULL; 9296 char_u *p; 9297 char_u *arg; 9298 garray_T newargs; 9299 garray_T newlines; 9300 int varargs = FALSE; 9301 int mustend = FALSE; 9302 int flags = 0; 9303 ufunc_T *fp; 9304 int indent; 9305 int nesting; 9306 char_u *skip_until = NULL; 9307 static char_u e_funcexts[] = N_("E122: Function %s already exists, add ! to replace it"); 9308 9309 /* 9310 * ":function" without argument: list functions. 9311 */ 9312 if (ends_excmd(*eap->arg)) 9313 { 9314 if (!eap->skip) 9315 for (fp = firstfunc; fp != NULL && !got_int; fp = fp->next) 9316 list_func_head(fp, FALSE); 9317 eap->nextcmd = check_nextcmd(eap->arg); 9318 return; 9319 } 9320 9321 p = eap->arg; 9322 name = trans_function_name(&p, eap->skip, FALSE); 9323 if (name == NULL && !eap->skip) 9324 { 9325 /* 9326 * Return on an invalid expression in braces, unless the expression 9327 * evaluation has been cancelled due to an aborting error, an 9328 * interrupt, or an exception. 9329 */ 9330 if (!aborting()) 9331 return; 9332 else 9333 eap->skip = TRUE; 9334 } 9335 #ifdef FEAT_MAGIC_BRACES 9336 /* An error in a function call during evaluation of an expression in magic 9337 * braces should not cause the function not to be defined. */ 9338 saved_did_emsg = did_emsg; 9339 did_emsg = FALSE; 9340 #endif 9341 9342 /* 9343 * ":function func" with only function name: list function. 9344 */ 9345 if (vim_strchr(p, '(') == NULL) 9346 { 9347 if (!ends_excmd(*skipwhite(p))) 9348 { 9349 EMSG(_(e_trailing)); 9350 goto erret_name; 9351 } 9352 eap->nextcmd = check_nextcmd(p); 9353 if (eap->nextcmd != NULL) 9354 *p = NUL; 9355 if (!eap->skip && !got_int) 9356 { 9357 fp = find_func(name); 9358 if (fp != NULL) 9359 { 9360 list_func_head(fp, TRUE); 9361 for (j = 0; j < fp->lines.ga_len && !got_int; ++j) 9362 { 9363 msg_putchar('\n'); 9364 msg_outnum((long)(j + 1)); 9365 if (j < 9) 9366 msg_putchar(' '); 9367 if (j < 99) 9368 msg_putchar(' '); 9369 msg_prt_line(FUNCLINE(fp, j)); 9370 out_flush(); /* show a line at a time */ 9371 ui_breakcheck(); 9372 } 9373 if (!got_int) 9374 { 9375 msg_putchar('\n'); 9376 msg_puts((char_u *)" endfunction"); 9377 } 9378 } 9379 else 9380 EMSG2(_("E123: Undefined function: %s"), eap->arg); 9381 } 9382 goto erret_name; 9383 } 9384 9385 /* 9386 * ":function name(arg1, arg2)" Define function. 9387 */ 9388 p = skipwhite(p); 9389 if (*p != '(') 9390 { 9391 if (!eap->skip) 9392 { 9393 EMSG2(_("E124: Missing '(': %s"), eap->arg); 9394 goto erret_name; 9395 } 9396 /* attempt to continue by skipping some text */ 9397 if (vim_strchr(p, '(') != NULL) 9398 p = vim_strchr(p, '('); 9399 } 9400 p = skipwhite(p + 1); 9401 9402 ga_init2(&newargs, (int)sizeof(char_u *), 3); 9403 ga_init2(&newlines, (int)sizeof(char_u *), 3); 9404 9405 /* 9406 * Isolate the arguments: "arg1, arg2, ...)" 9407 */ 9408 while (*p != ')') 9409 { 9410 if (p[0] == '.' && p[1] == '.' && p[2] == '.') 9411 { 9412 varargs = TRUE; 9413 p += 3; 9414 mustend = TRUE; 9415 } 9416 else 9417 { 9418 arg = p; 9419 while (ASCII_ISALNUM(*p) || *p == '_') 9420 ++p; 9421 if (arg == p || isdigit(*arg) 9422 || (p - arg == 9 && STRNCMP(arg, "firstline", 9) == 0) 9423 || (p - arg == 8 && STRNCMP(arg, "lastline", 8) == 0)) 9424 { 9425 if (!eap->skip) 9426 EMSG2(_("E125: Illegal argument: %s"), arg); 9427 break; 9428 } 9429 if (ga_grow(&newargs, 1) == FAIL) 9430 goto erret; 9431 c = *p; 9432 *p = NUL; 9433 arg = vim_strsave(arg); 9434 if (arg == NULL) 9435 goto erret; 9436 ((char_u **)(newargs.ga_data))[newargs.ga_len] = arg; 9437 *p = c; 9438 newargs.ga_len++; 9439 newargs.ga_room--; 9440 if (*p == ',') 9441 ++p; 9442 else 9443 mustend = TRUE; 9444 } 9445 p = skipwhite(p); 9446 if (mustend && *p != ')') 9447 { 9448 if (!eap->skip) 9449 EMSG2(_(e_invarg2), eap->arg); 9450 break; 9451 } 9452 } 9453 ++p; /* skip the ')' */ 9454 9455 /* find extra arguments "range" and "abort" */ 9456 for (;;) 9457 { 9458 p = skipwhite(p); 9459 if (STRNCMP(p, "range", 5) == 0) 9460 { 9461 flags |= FC_RANGE; 9462 p += 5; 9463 } 9464 else if (STRNCMP(p, "abort", 5) == 0) 9465 { 9466 flags |= FC_ABORT; 9467 p += 5; 9468 } 9469 else 9470 break; 9471 } 9472 9473 if (*p != NUL && *p != '"' && *p != '\n' && !eap->skip && !did_emsg) 9474 EMSG(_(e_trailing)); 9475 9476 /* 9477 * Read the body of the function, until ":endfunction" is found. 9478 */ 9479 if (KeyTyped) 9480 { 9481 /* Check if the function already exists, don't let the user type the 9482 * whole function before telling him it doesn't work! For a script we 9483 * need to skip the body to be able to find what follows. */ 9484 if (!eap->skip && !eap->forceit && find_func(name) != NULL) 9485 EMSG2(_(e_funcexts), name); 9486 9487 msg_putchar('\n'); /* don't overwrite the function name */ 9488 cmdline_row = msg_row; 9489 } 9490 9491 indent = 2; 9492 nesting = 0; 9493 for (;;) 9494 { 9495 msg_scroll = TRUE; 9496 need_wait_return = FALSE; 9497 if (eap->getline == NULL) 9498 theline = getcmdline(':', 0L, indent); 9499 else 9500 theline = eap->getline(':', eap->cookie, indent); 9501 if (KeyTyped) 9502 lines_left = Rows - 1; 9503 if (theline == NULL) 9504 { 9505 EMSG(_("E126: Missing :endfunction")); 9506 goto erret; 9507 } 9508 9509 if (skip_until != NULL) 9510 { 9511 /* between ":append" and "." and between ":python <<EOF" and "EOF" 9512 * don't check for ":endfunc". */ 9513 if (STRCMP(theline, skip_until) == 0) 9514 { 9515 vim_free(skip_until); 9516 skip_until = NULL; 9517 } 9518 } 9519 else 9520 { 9521 /* skip ':' and blanks*/ 9522 for (p = theline; vim_iswhite(*p) || *p == ':'; ++p) 9523 ; 9524 9525 /* Check for "endfunction" (should be more strict...). */ 9526 if (STRNCMP(p, "endf", 4) == 0 && nesting-- == 0) 9527 { 9528 vim_free(theline); 9529 break; 9530 } 9531 9532 /* Increase indent inside "if", "while", and "try", decrease 9533 * at "end". */ 9534 if (indent > 2 && STRNCMP(p, "end", 3) == 0) 9535 indent -= 2; 9536 else if (STRNCMP(p, "if", 2) == 0 || STRNCMP(p, "wh", 2) == 0 9537 || STRNCMP(p, "try", 3) == 0) 9538 indent += 2; 9539 9540 /* Check for defining a function inside this function. */ 9541 if (STRNCMP(p, "fu", 2) == 0) 9542 { 9543 p = skipwhite(skiptowhite(p)); 9544 p += eval_fname_script(p); 9545 if (ASCII_ISALPHA(*p)) 9546 { 9547 vim_free(trans_function_name(&p, TRUE, FALSE)); 9548 if (*skipwhite(p) == '(') 9549 { 9550 ++nesting; 9551 indent += 2; 9552 } 9553 } 9554 } 9555 9556 /* Check for ":append" or ":insert". */ 9557 p = skip_range(p, NULL); 9558 if ((p[0] == 'a' && (!ASCII_ISALPHA(p[1]) || p[1] == 'p')) 9559 || (p[0] == 'i' 9560 && (!ASCII_ISALPHA(p[1]) || (p[1] == 'n' 9561 && (!ASCII_ISALPHA(p[2]) || (p[2] == 's')))))) 9562 skip_until = vim_strsave((char_u *)"."); 9563 9564 /* Check for ":python <<EOF", ":tcl <<EOF", etc. */ 9565 arg = skipwhite(skiptowhite(p)); 9566 if (arg[0] == '<' && arg[1] =='<' 9567 && ((p[0] == 'p' && p[1] == 'y' 9568 && (!ASCII_ISALPHA(p[2]) || p[2] == 't')) 9569 || (p[0] == 'p' && p[1] == 'e' 9570 && (!ASCII_ISALPHA(p[2]) || p[2] == 'r')) 9571 || (p[0] == 't' && p[1] == 'c' 9572 && (!ASCII_ISALPHA(p[2]) || p[2] == 'l')) 9573 || (p[0] == 'r' && p[1] == 'u' && p[2] == 'b' 9574 && (!ASCII_ISALPHA(p[3]) || p[3] == 'y')) 9575 || (p[0] == 'm' && p[1] == 'z' 9576 && (!ASCII_ISALPHA(p[2]) || p[2] == 's')) 9577 )) 9578 { 9579 /* ":python <<" continues until a dot, like ":append" */ 9580 p = skipwhite(arg + 2); 9581 if (*p == NUL) 9582 skip_until = vim_strsave((char_u *)"."); 9583 else 9584 skip_until = vim_strsave(p); 9585 } 9586 } 9587 9588 /* Add the line to the function. */ 9589 if (ga_grow(&newlines, 1) == FAIL) 9590 goto erret; 9591 ((char_u **)(newlines.ga_data))[newlines.ga_len] = theline; 9592 newlines.ga_len++; 9593 newlines.ga_room--; 9594 } 9595 9596 /* Don't define the function when skipping commands or when an error was 9597 * detected. */ 9598 if (eap->skip || did_emsg) 9599 goto erret; 9600 9601 /* 9602 * If there are no errors, add the function 9603 */ 9604 fp = find_func(name); 9605 if (fp != NULL) 9606 { 9607 if (!eap->forceit) 9608 { 9609 EMSG2(_(e_funcexts), name); 9610 goto erret; 9611 } 9612 if (fp->calls) 9613 { 9614 EMSG2(_("E127: Cannot redefine function %s: It is in use"), name); 9615 goto erret; 9616 } 9617 /* redefine existing function */ 9618 ga_clear_strings(&(fp->args)); 9619 ga_clear_strings(&(fp->lines)); 9620 vim_free(name); 9621 } 9622 else 9623 { 9624 fp = (ufunc_T *)alloc((unsigned)sizeof(ufunc_T)); 9625 if (fp == NULL) 9626 goto erret; 9627 /* insert the new function in the function list */ 9628 fp->next = firstfunc; 9629 firstfunc = fp; 9630 fp->name = name; 9631 } 9632 fp->args = newargs; 9633 fp->lines = newlines; 9634 fp->varargs = varargs; 9635 fp->flags = flags; 9636 fp->calls = 0; 9637 fp->script_ID = current_SID; 9638 #ifdef FEAT_MAGIC_BRACES 9639 did_emsg |= saved_did_emsg; 9640 #endif 9641 vim_free(skip_until); 9642 return; 9643 9644 erret: 9645 vim_free(skip_until); 9646 ga_clear_strings(&newargs); 9647 ga_clear_strings(&newlines); 9648 erret_name: 9649 vim_free(name); 9650 #ifdef FEAT_MAGIC_BRACES 9651 did_emsg |= saved_did_emsg; 9652 #endif 9653 } 9654 9655 /* 9656 * Get a function name, translating "<SID>" and "<SNR>". 9657 * Returns the function name in allocated memory, or NULL for failure. 9658 * Advances "pp" to just after the function name (if no error). 9659 */ 9660 static char_u * 9661 trans_function_name(pp, skip, internal) 9662 char_u **pp; 9663 int skip; /* only find the end, don't evaluate */ 9664 int internal; /* TRUE if internal function name OK */ 9665 { 9666 char_u *name; 9667 char_u *start; 9668 char_u *end; 9669 int lead; 9670 char_u sid_buf[20]; 9671 char_u *temp_string = NULL; 9672 char_u *expr_start, *expr_end; 9673 int len; 9674 9675 /* A name starting with "<SID>" or "<SNR>" is local to a script. */ 9676 start = *pp; 9677 lead = eval_fname_script(start); 9678 if (lead > 0) 9679 start += lead; 9680 end = find_name_end(start, &expr_start, &expr_end); 9681 if (end == start) 9682 { 9683 if (!skip) 9684 EMSG(_("E129: Function name required")); 9685 return NULL; 9686 } 9687 #ifdef FEAT_MAGIC_BRACES 9688 if (expr_start != NULL && !skip) 9689 { 9690 /* expand magic curlies */ 9691 temp_string = make_expanded_name(start, expr_start, expr_end, end); 9692 if (temp_string == NULL) 9693 { 9694 /* 9695 * Report an invalid expression in braces, unless the expression 9696 * evaluation has been cancelled due to an aborting error, an 9697 * interrupt, or an exception. 9698 */ 9699 if (!aborting()) 9700 EMSG2(_(e_invarg2), start); 9701 else 9702 *pp = end; 9703 return NULL; 9704 } 9705 start = temp_string; 9706 len = (int)STRLEN(temp_string); 9707 } 9708 else 9709 #endif 9710 len = (int)(end - start); 9711 9712 /* 9713 * Copy the function name to allocated memory. 9714 * Accept <SID>name() inside a script, translate into <SNR>123_name(). 9715 * Accept <SNR>123_name() outside a script. 9716 */ 9717 if (skip) 9718 lead = 0; /* do nothing */ 9719 else if (lead > 0) 9720 { 9721 lead = 3; 9722 if (eval_fname_sid(*pp)) /* If it's "<SID>" */ 9723 { 9724 if (current_SID <= 0) 9725 { 9726 EMSG(_(e_usingsid)); 9727 return NULL; 9728 } 9729 sprintf((char *)sid_buf, "%ld_", (long)current_SID); 9730 lead += (int)STRLEN(sid_buf); 9731 } 9732 } 9733 else if (!internal && !ASCII_ISUPPER(*start)) 9734 { 9735 EMSG2(_("E128: Function name must start with a capital: %s"), start); 9736 return NULL; 9737 } 9738 name = alloc((unsigned)(len + lead + 1)); 9739 if (name != NULL) 9740 { 9741 if (lead > 0) 9742 { 9743 name[0] = K_SPECIAL; 9744 name[1] = KS_EXTRA; 9745 name[2] = (int)KE_SNR; 9746 if (eval_fname_sid(*pp)) /* If it's "<SID>" */ 9747 STRCPY(name + 3, sid_buf); 9748 } 9749 mch_memmove(name + lead, start, (size_t)len); 9750 name[len + lead] = NUL; 9751 } 9752 *pp = end; 9753 9754 vim_free(temp_string); 9755 return name; 9756 } 9757 9758 /* 9759 * Return 5 if "p" starts with "<SID>" or "<SNR>" (ignoring case). 9760 * Return 2 if "p" starts with "s:". 9761 * Return 0 otherwise. 9762 */ 9763 static int 9764 eval_fname_script(p) 9765 char_u *p; 9766 { 9767 if (p[0] == '<' && (STRNICMP(p + 1, "SID>", 4) == 0 9768 || STRNICMP(p + 1, "SNR>", 4) == 0)) 9769 return 5; 9770 if (p[0] == 's' && p[1] == ':') 9771 return 2; 9772 return 0; 9773 } 9774 9775 /* 9776 * Return TRUE if "p" starts with "<SID>" or "s:". 9777 * Only works if eval_fname_script() returned non-zero for "p"! 9778 */ 9779 static int 9780 eval_fname_sid(p) 9781 char_u *p; 9782 { 9783 return (*p == 's' || TOUPPER_ASC(p[2]) == 'I'); 9784 } 9785 9786 /* 9787 * List the head of the function: "name(arg1, arg2)". 9788 */ 9789 static void 9790 list_func_head(fp, indent) 9791 ufunc_T *fp; 9792 int indent; 9793 { 9794 int j; 9795 9796 msg_start(); 9797 if (indent) 9798 MSG_PUTS(" "); 9799 MSG_PUTS("function "); 9800 if (fp->name[0] == K_SPECIAL) 9801 { 9802 MSG_PUTS_ATTR("<SNR>", hl_attr(HLF_8)); 9803 msg_puts(fp->name + 3); 9804 } 9805 else 9806 msg_puts(fp->name); 9807 msg_putchar('('); 9808 for (j = 0; j < fp->args.ga_len; ++j) 9809 { 9810 if (j) 9811 MSG_PUTS(", "); 9812 msg_puts(FUNCARG(fp, j)); 9813 } 9814 if (fp->varargs) 9815 { 9816 if (j) 9817 MSG_PUTS(", "); 9818 MSG_PUTS("..."); 9819 } 9820 msg_putchar(')'); 9821 } 9822 9823 /* 9824 * Find a function by name, return pointer to it in ufuncs. 9825 * Return NULL for unknown function. 9826 */ 9827 static ufunc_T * 9828 find_func(name) 9829 char_u *name; 9830 { 9831 ufunc_T *fp; 9832 9833 for (fp = firstfunc; fp != NULL; fp = fp->next) 9834 if (STRCMP(name, fp->name) == 0) 9835 break; 9836 return fp; 9837 } 9838 9839 #if defined(FEAT_CMDL_COMPL) || defined(PROTO) 9840 9841 /* 9842 * Function given to ExpandGeneric() to obtain the list of user defined 9843 * function names. 9844 */ 9845 char_u * 9846 get_user_func_name(xp, idx) 9847 expand_T *xp; 9848 int idx; 9849 { 9850 static ufunc_T *fp = NULL; 9851 9852 if (idx == 0) 9853 fp = firstfunc; 9854 if (fp != NULL) 9855 { 9856 if (STRLEN(fp->name) + 4 >= IOSIZE) 9857 return fp->name; /* prevents overflow */ 9858 9859 cat_func_name(IObuff, fp); 9860 if (xp->xp_context != EXPAND_USER_FUNC) 9861 { 9862 STRCAT(IObuff, "("); 9863 if (!fp->varargs && fp->args.ga_len == 0) 9864 STRCAT(IObuff, ")"); 9865 } 9866 9867 fp = fp->next; 9868 return IObuff; 9869 } 9870 return NULL; 9871 } 9872 9873 #endif /* FEAT_CMDL_COMPL */ 9874 9875 /* 9876 * Copy the function name of "fp" to buffer "buf". 9877 * "buf" must be able to hold the function name plus three bytes. 9878 * Takes care of script-local function names. 9879 */ 9880 static void 9881 cat_func_name(buf, fp) 9882 char_u *buf; 9883 ufunc_T *fp; 9884 { 9885 if (fp->name[0] == K_SPECIAL) 9886 { 9887 STRCPY(buf, "<SNR>"); 9888 STRCAT(buf, fp->name + 3); 9889 } 9890 else 9891 STRCPY(buf, fp->name); 9892 } 9893 9894 /* 9895 * ":delfunction {name}" 9896 */ 9897 void 9898 ex_delfunction(eap) 9899 exarg_T *eap; 9900 { 9901 ufunc_T *fp = NULL, *pfp; 9902 char_u *p; 9903 char_u *name; 9904 9905 p = eap->arg; 9906 name = trans_function_name(&p, eap->skip, FALSE); 9907 if (name == NULL) 9908 return; 9909 if (!ends_excmd(*skipwhite(p))) 9910 { 9911 vim_free(name); 9912 EMSG(_(e_trailing)); 9913 return; 9914 } 9915 eap->nextcmd = check_nextcmd(p); 9916 if (eap->nextcmd != NULL) 9917 *p = NUL; 9918 9919 if (!eap->skip) 9920 fp = find_func(name); 9921 vim_free(name); 9922 9923 if (!eap->skip) 9924 { 9925 if (fp == NULL) 9926 { 9927 EMSG2(_("E130: Undefined function: %s"), eap->arg); 9928 return; 9929 } 9930 if (fp->calls) 9931 { 9932 EMSG2(_("E131: Cannot delete function %s: It is in use"), eap->arg); 9933 return; 9934 } 9935 9936 /* clear this function */ 9937 vim_free(fp->name); 9938 ga_clear_strings(&(fp->args)); 9939 ga_clear_strings(&(fp->lines)); 9940 9941 /* remove the function from the function list */ 9942 if (firstfunc == fp) 9943 firstfunc = fp->next; 9944 else 9945 { 9946 for (pfp = firstfunc; pfp != NULL; pfp = pfp->next) 9947 if (pfp->next == fp) 9948 { 9949 pfp->next = fp->next; 9950 break; 9951 } 9952 } 9953 vim_free(fp); 9954 } 9955 } 9956 9957 /* 9958 * Call a user function. 9959 */ 9960 static void 9961 call_user_func(fp, argcount, argvars, retvar, firstline, lastline) 9962 ufunc_T *fp; /* pointer to function */ 9963 int argcount; /* nr of args */ 9964 VAR argvars; /* arguments */ 9965 VAR retvar; /* return value */ 9966 linenr_T firstline; /* first line of range */ 9967 linenr_T lastline; /* last line of range */ 9968 { 9969 char_u *save_sourcing_name; 9970 linenr_T save_sourcing_lnum; 9971 scid_T save_current_SID; 9972 struct funccall fc; 9973 struct funccall *save_fcp = current_funccal; 9974 int save_did_emsg; 9975 static int depth = 0; 9976 9977 /* If depth of calling is getting too high, don't execute the function */ 9978 if (depth >= p_mfd) 9979 { 9980 EMSG(_("E132: Function call depth is higher than 'maxfuncdepth'")); 9981 retvar->var_type = VAR_NUMBER; 9982 retvar->var_val.var_number = -1; 9983 return; 9984 } 9985 ++depth; 9986 9987 line_breakcheck(); /* check for CTRL-C hit */ 9988 9989 /* set local variables */ 9990 var_init(&fc.l_vars); 9991 fc.func = fp; 9992 fc.argcount = argcount; 9993 fc.argvars = argvars; 9994 fc.retvar = retvar; 9995 retvar->var_val.var_number = 0; 9996 fc.linenr = 0; 9997 fc.returned = FALSE; 9998 fc.level = ex_nesting_level; 9999 fc.a0_var.var_type = VAR_NUMBER; 10000 fc.a0_var.var_val.var_number = argcount - fp->args.ga_len; 10001 fc.a0_var.var_name = NULL; 10002 current_funccal = &fc; 10003 fc.firstline.var_type = VAR_NUMBER; 10004 fc.firstline.var_val.var_number = firstline; 10005 fc.firstline.var_name = NULL; 10006 fc.lastline.var_type = VAR_NUMBER; 10007 fc.lastline.var_val.var_number = lastline; 10008 fc.lastline.var_name = NULL; 10009 /* Check if this function has a breakpoint. */ 10010 fc.breakpoint = dbg_find_breakpoint(FALSE, fp->name, (linenr_T)0); 10011 fc.dbg_tick = debug_tick; 10012 10013 /* Don't redraw while executing the function. */ 10014 ++RedrawingDisabled; 10015 save_sourcing_name = sourcing_name; 10016 save_sourcing_lnum = sourcing_lnum; 10017 sourcing_lnum = 1; 10018 sourcing_name = alloc((unsigned)((save_sourcing_name == NULL ? 0 10019 : STRLEN(save_sourcing_name)) + STRLEN(fp->name) + 13)); 10020 if (sourcing_name != NULL) 10021 { 10022 if (save_sourcing_name != NULL 10023 && STRNCMP(save_sourcing_name, "function ", 9) == 0) 10024 sprintf((char *)sourcing_name, "%s..", save_sourcing_name); 10025 else 10026 STRCPY(sourcing_name, "function "); 10027 cat_func_name(sourcing_name + STRLEN(sourcing_name), fp); 10028 10029 if (p_verbose >= 12) 10030 { 10031 ++no_wait_return; 10032 msg_scroll = TRUE; /* always scroll up, don't overwrite */ 10033 msg_str((char_u *)_("calling %s"), sourcing_name); 10034 if (p_verbose >= 14) 10035 { 10036 int i; 10037 char_u buf[MSG_BUF_LEN]; 10038 10039 msg_puts((char_u *)"("); 10040 for (i = 0; i < argcount; ++i) 10041 { 10042 if (i > 0) 10043 msg_puts((char_u *)", "); 10044 if (argvars[i].var_type == VAR_NUMBER) 10045 msg_outnum((long)argvars[i].var_val.var_number); 10046 else 10047 { 10048 trunc_string(get_var_string(&argvars[i]), 10049 buf, MSG_BUF_LEN); 10050 msg_puts((char_u *)"\""); 10051 msg_puts(buf); 10052 msg_puts((char_u *)"\""); 10053 } 10054 } 10055 msg_puts((char_u *)")"); 10056 } 10057 msg_puts((char_u *)"\n"); /* don't overwrite this either */ 10058 cmdline_row = msg_row; 10059 --no_wait_return; 10060 } 10061 } 10062 save_current_SID = current_SID; 10063 current_SID = fp->script_ID; 10064 save_did_emsg = did_emsg; 10065 did_emsg = FALSE; 10066 10067 /* call do_cmdline() to execute the lines */ 10068 do_cmdline(NULL, get_func_line, (void *)&fc, 10069 DOCMD_NOWAIT|DOCMD_VERBOSE|DOCMD_REPEAT); 10070 10071 --RedrawingDisabled; 10072 10073 /* when the function was aborted because of an error, return -1 */ 10074 if ((did_emsg && (fp->flags & FC_ABORT)) || retvar->var_type == VAR_UNKNOWN) 10075 { 10076 clear_var(retvar); 10077 retvar->var_type = VAR_NUMBER; 10078 retvar->var_val.var_number = -1; 10079 } 10080 10081 /* when being verbose, mention the return value */ 10082 if (p_verbose >= 12) 10083 { 10084 char_u *sn, *val; 10085 10086 ++no_wait_return; 10087 msg_scroll = TRUE; /* always scroll up, don't overwrite */ 10088 10089 /* Make sure the output fits in IObuff. */ 10090 sn = sourcing_name; 10091 if (STRLEN(sourcing_name) > IOSIZE / 2 - 50) 10092 sn = sourcing_name + STRLEN(sourcing_name) - (IOSIZE / 2 - 50); 10093 10094 if (aborting()) 10095 smsg((char_u *)_("%s aborted"), sn); 10096 else if (fc.retvar->var_type == VAR_NUMBER) 10097 smsg((char_u *)_("%s returning #%ld"), sn, 10098 (long)fc.retvar->var_val.var_number); 10099 else if (fc.retvar->var_type == VAR_STRING) 10100 { 10101 val = get_var_string(fc.retvar); 10102 if (STRLEN(val) > IOSIZE / 2 - 50) 10103 val = val + STRLEN(val) - (IOSIZE / 2 - 50); 10104 smsg((char_u *)_("%s returning \"%s\""), sn, val); 10105 } 10106 msg_puts((char_u *)"\n"); /* don't overwrite this either */ 10107 cmdline_row = msg_row; 10108 --no_wait_return; 10109 } 10110 10111 vim_free(sourcing_name); 10112 sourcing_name = save_sourcing_name; 10113 sourcing_lnum = save_sourcing_lnum; 10114 current_SID = save_current_SID; 10115 10116 if (p_verbose >= 12 && sourcing_name != NULL) 10117 { 10118 ++no_wait_return; 10119 msg_scroll = TRUE; /* always scroll up, don't overwrite */ 10120 msg_str((char_u *)_("continuing in %s"), sourcing_name); 10121 msg_puts((char_u *)"\n"); /* don't overwrite this either */ 10122 cmdline_row = msg_row; 10123 --no_wait_return; 10124 } 10125 10126 did_emsg |= save_did_emsg; 10127 current_funccal = save_fcp; 10128 10129 var_clear(&fc.l_vars); /* free all local variables */ 10130 --depth; 10131 } 10132 10133 /* 10134 * ":return [expr]" 10135 */ 10136 void 10137 ex_return(eap) 10138 exarg_T *eap; 10139 { 10140 char_u *arg = eap->arg; 10141 var retvar; 10142 int returning = FALSE; 10143 10144 if (current_funccal == NULL) 10145 { 10146 EMSG(_("E133: :return not inside a function")); 10147 return; 10148 } 10149 10150 if (eap->skip) 10151 ++emsg_skip; 10152 10153 eap->nextcmd = NULL; 10154 if ((*arg != NUL && *arg != '|' && *arg != '\n') 10155 && eval0(arg, &retvar, &eap->nextcmd, !eap->skip) != FAIL) 10156 { 10157 if (!eap->skip) 10158 returning = do_return(eap, FALSE, TRUE, &retvar); 10159 else 10160 clear_var(&retvar); 10161 } 10162 /* It's safer to return also on error. */ 10163 else if (!eap->skip) 10164 { 10165 /* 10166 * Return unless the expression evaluation has been cancelled due to an 10167 * aborting error, an interrupt, or an exception. 10168 */ 10169 if (!aborting()) 10170 returning = do_return(eap, FALSE, TRUE, NULL); 10171 } 10172 10173 /* When skipping or the return gets pending, advance to the next command 10174 * in this line (!returning). Otherwise, ignore the rest of the line. 10175 * Following lines will be ignored by get_func_line(). */ 10176 if (returning) 10177 eap->nextcmd = NULL; 10178 else if (eap->nextcmd == NULL) /* no argument */ 10179 eap->nextcmd = check_nextcmd(arg); 10180 10181 if (eap->skip) 10182 --emsg_skip; 10183 } 10184 10185 /* 10186 * Return from a function. Possibly makes the return pending. Also called 10187 * for a pending return at the ":endtry" or after returning from an extra 10188 * do_cmdline(). "reanimate" is used in the latter case. "is_cmd" is set 10189 * when called due to a ":return" command. "value" may point to a variable 10190 * with the return value. Returns TRUE when the return can be carried out, 10191 * FALSE when the return gets pending. 10192 */ 10193 int 10194 do_return(eap, reanimate, is_cmd, value) 10195 exarg_T *eap; 10196 int reanimate; 10197 int is_cmd; 10198 void *value; 10199 { 10200 int idx; 10201 struct condstack *cstack = eap->cstack; 10202 10203 if (reanimate) 10204 /* Undo the return. */ 10205 current_funccal->returned = FALSE; 10206 10207 /* 10208 * Cleanup (and inactivate) conditionals, but stop when a try conditional 10209 * not in its finally clause (which then is to be executed next) is found. 10210 * In this case, make the ":return" pending for execution at the ":endtry". 10211 * Otherwise, return normally. 10212 */ 10213 idx = cleanup_conditionals(eap->cstack, 0, TRUE); 10214 if (idx >= 0) 10215 { 10216 cstack->cs_pending[idx] = CSTP_RETURN; 10217 10218 if (!is_cmd && !reanimate) 10219 /* A pending return again gets pending. "value" points to an 10220 * allocated variable with the value of the original ":return"'s 10221 * argument if present or is NULL else. */ 10222 cstack->cs_retvar[idx] = value; 10223 else 10224 { 10225 /* When undoing a return in order to make it pending, get the stored 10226 * return value. */ 10227 if (reanimate) 10228 value = current_funccal->retvar; 10229 10230 if (value != NULL) 10231 { 10232 /* Store the value of the pending return. */ 10233 if ((cstack->cs_retvar[idx] = alloc_var()) != NULL) 10234 *(VAR)cstack->cs_retvar[idx] = *(VAR)value; 10235 else 10236 EMSG(_(e_outofmem)); 10237 } 10238 else 10239 cstack->cs_retvar[idx] = NULL; 10240 10241 if (reanimate) 10242 { 10243 /* The pending return value could be overwritten by a ":return" 10244 * without argument in a finally clause; reset the default 10245 * return value. */ 10246 current_funccal->retvar->var_type = VAR_NUMBER; 10247 current_funccal->retvar->var_val.var_number = 0; 10248 } 10249 } 10250 report_make_pending(CSTP_RETURN, value); 10251 } 10252 else 10253 { 10254 current_funccal->returned = TRUE; 10255 10256 /* If the return is carried out now, store the return value. For 10257 * a return immediately after reanimation, the value is already 10258 * there. */ 10259 if (!reanimate && value != NULL) 10260 { 10261 clear_var(current_funccal->retvar); 10262 *current_funccal->retvar = *(VAR)value; 10263 if (!is_cmd) 10264 vim_free(value); 10265 } 10266 } 10267 10268 return idx < 0; 10269 } 10270 10271 /* 10272 * Free the variable with a pending return value. 10273 */ 10274 void 10275 discard_pending_return(retvar) 10276 void *retvar; 10277 { 10278 /* The variable was copied from one with an undefined var_name. So we can't 10279 * use free_var() to clear and free it. */ 10280 clear_var((VAR)retvar); 10281 vim_free(retvar); 10282 } 10283 10284 /* 10285 * Generate a return command for producing the value of "retvar". The result 10286 * is an allocated string. Used by report_pending() for verbose messages. 10287 */ 10288 char_u * 10289 get_return_cmd(retvar) 10290 void *retvar; 10291 { 10292 char_u *s = IObuff; 10293 10294 if (retvar == NULL || ((VAR)retvar)->var_type == VAR_UNKNOWN) 10295 s = (char_u *)":return"; 10296 else if (((VAR)retvar)->var_type == VAR_STRING) 10297 sprintf((char *)IObuff, ":return \"%s\"", 10298 ((VAR)retvar)->var_val.var_string); 10299 else 10300 sprintf((char *)IObuff, ":return %ld", 10301 (long)(((VAR)retvar)->var_val.var_number)); 10302 return vim_strsave(s); 10303 } 10304 10305 /* 10306 * Get next function line. 10307 * Called by do_cmdline() to get the next line. 10308 * Returns allocated string, or NULL for end of function. 10309 */ 10310 /* ARGSUSED */ 10311 char_u * 10312 get_func_line(c, cookie, indent) 10313 int c; /* not used */ 10314 void *cookie; 10315 int indent; /* not used */ 10316 { 10317 struct funccall *fcp = (struct funccall *)cookie; 10318 char_u *retval; 10319 garray_T *gap; /* growarray with function lines */ 10320 10321 /* If breakpoints have been added/deleted need to check for it. */ 10322 if (fcp->dbg_tick != debug_tick) 10323 { 10324 fcp->breakpoint = dbg_find_breakpoint(FALSE, fcp->func->name, 10325 sourcing_lnum); 10326 fcp->dbg_tick = debug_tick; 10327 } 10328 10329 gap = &fcp->func->lines; 10330 if ((fcp->func->flags & FC_ABORT) && did_emsg && !aborted_in_try()) 10331 retval = NULL; 10332 else if (fcp->returned || fcp->linenr >= gap->ga_len) 10333 retval = NULL; 10334 else 10335 { 10336 retval = vim_strsave(((char_u **)(gap->ga_data))[fcp->linenr++]); 10337 sourcing_lnum = fcp->linenr; 10338 } 10339 10340 /* Did we encounter a breakpoint? */ 10341 if (fcp->breakpoint != 0 && fcp->breakpoint <= sourcing_lnum) 10342 { 10343 dbg_breakpoint(fcp->func->name, sourcing_lnum); 10344 /* Find next breakpoint. */ 10345 fcp->breakpoint = dbg_find_breakpoint(FALSE, fcp->func->name, 10346 sourcing_lnum); 10347 fcp->dbg_tick = debug_tick; 10348 } 10349 10350 return retval; 10351 } 10352 10353 /* 10354 * Return TRUE if the currently active function should be ended, because a 10355 * return was encountered or an error occured. Used inside a ":while". 10356 */ 10357 int 10358 func_has_ended(cookie) 10359 void *cookie; 10360 { 10361 struct funccall *fcp = (struct funccall *)cookie; 10362 10363 /* Ignore the "abort" flag if the abortion behavior has been changed due to 10364 * an error inside a try conditional. */ 10365 return (((fcp->func->flags & FC_ABORT) && did_emsg && !aborted_in_try()) 10366 || fcp->returned); 10367 } 10368 10369 /* 10370 * return TRUE if cookie indicates a function which "abort"s on errors. 10371 */ 10372 int 10373 func_has_abort(cookie) 10374 void *cookie; 10375 { 10376 return ((struct funccall *)cookie)->func->flags & FC_ABORT; 10377 } 10378 10379 #if defined(FEAT_VIMINFO) || defined(FEAT_SESSION) 10380 typedef enum 10381 { 10382 VAR_FLAVOUR_DEFAULT, 10383 VAR_FLAVOUR_SESSION, 10384 VAR_FLAVOUR_VIMINFO 10385 } var_flavour_T; 10386 10387 static var_flavour_T var_flavour __ARGS((char_u *varname)); 10388 10389 static var_flavour_T 10390 var_flavour(varname) 10391 char_u *varname; 10392 { 10393 char_u *p = varname; 10394 10395 if (ASCII_ISUPPER(*p)) 10396 { 10397 while (*(++p)) 10398 if (ASCII_ISLOWER(*p)) 10399 return VAR_FLAVOUR_SESSION; 10400 return VAR_FLAVOUR_VIMINFO; 10401 } 10402 else 10403 return VAR_FLAVOUR_DEFAULT; 10404 } 10405 #endif 10406 10407 #if defined(FEAT_VIMINFO) || defined(PROTO) 10408 /* 10409 * Restore global vars that start with a capital from the viminfo file 10410 */ 10411 int 10412 read_viminfo_varlist(virp, writing) 10413 vir_T *virp; 10414 int writing; 10415 { 10416 char_u *tab; 10417 int is_string = FALSE; 10418 VAR varp = NULL; 10419 char_u *val; 10420 10421 if (!writing && (find_viminfo_parameter('!') != NULL)) 10422 { 10423 tab = vim_strchr(virp->vir_line + 1, '\t'); 10424 if (tab != NULL) 10425 { 10426 *tab++ = '\0'; /* isolate the variable name */ 10427 if (*tab == 'S') /* string var */ 10428 is_string = TRUE; 10429 10430 tab = vim_strchr(tab, '\t'); 10431 if (tab != NULL) 10432 { 10433 /* create a nameless variable to hold the value */ 10434 if (is_string) 10435 { 10436 val = viminfo_readstring(virp, 10437 (int)(tab - virp->vir_line + 1), TRUE); 10438 if (val != NULL) 10439 varp = alloc_string_var(val); 10440 } 10441 else 10442 { 10443 varp = alloc_var(); 10444 if (varp != NULL) 10445 { 10446 varp->var_type = VAR_NUMBER; 10447 varp->var_val.var_number = atol((char *)tab + 1); 10448 } 10449 } 10450 /* assign the value to the variable */ 10451 if (varp != NULL) 10452 { 10453 set_var(virp->vir_line + 1, varp); 10454 free_var(varp); 10455 } 10456 } 10457 } 10458 } 10459 10460 return viminfo_readline(virp); 10461 } 10462 10463 /* 10464 * Write global vars that start with a capital to the viminfo file 10465 */ 10466 void 10467 write_viminfo_varlist(fp) 10468 FILE *fp; 10469 { 10470 garray_T *gap = &variables; /* global variable */ 10471 VAR this_var; 10472 int i; 10473 10474 if (find_viminfo_parameter('!') == NULL) 10475 return; 10476 10477 fprintf(fp, _("\n# global variables:\n")); 10478 for (i = gap->ga_len; --i >= 0; ) 10479 { 10480 this_var = &VAR_GAP_ENTRY(i, gap); 10481 if (this_var->var_name != NULL 10482 && var_flavour(this_var->var_name) == VAR_FLAVOUR_VIMINFO) 10483 { 10484 fprintf(fp, "!%s\t%s\t", this_var->var_name, 10485 (this_var->var_type == VAR_STRING) ? "STR" : "NUM"); 10486 viminfo_writestring(fp, get_var_string(this_var)); 10487 } 10488 } 10489 } 10490 #endif 10491 10492 #if defined(FEAT_SESSION) || defined(PROTO) 10493 int 10494 store_session_globals(fd) 10495 FILE *fd; 10496 { 10497 garray_T *gap = &variables; /* global variable */ 10498 VAR this_var; 10499 int i; 10500 char_u *p, *t; 10501 10502 for (i = gap->ga_len; --i >= 0; ) 10503 { 10504 this_var = &VAR_GAP_ENTRY(i, gap); 10505 if (this_var->var_name != NULL) 10506 { 10507 if (var_flavour(this_var->var_name) == VAR_FLAVOUR_SESSION) 10508 { 10509 /* Escapse special characters with a backslash. Turn a LF and 10510 * CR into \n and \r. */ 10511 p = vim_strsave_escaped(get_var_string(this_var), 10512 (char_u *)"\\\"\n\r"); 10513 if (p == NULL) /* out of memory */ 10514 continue; 10515 for (t = p; *t != NUL; ++t) 10516 if (*t == '\n') 10517 *t = 'n'; 10518 else if (*t == '\r') 10519 *t = 'r'; 10520 if ((fprintf(fd, "let %s = %c%s%c", 10521 this_var->var_name, 10522 (this_var->var_type == VAR_STRING) ? '"' : ' ', 10523 p, 10524 (this_var->var_type == VAR_STRING) ? '"' : ' ') < 0) 10525 || put_eol(fd) == FAIL) 10526 { 10527 vim_free(p); 10528 return FAIL; 10529 } 10530 vim_free(p); 10531 } 10532 10533 } 10534 } 10535 return OK; 10536 } 10537 #endif 10538 10539 #endif /* FEAT_EVAL */ 10540 10541 #if defined(FEAT_MODIFY_FNAME) || defined(FEAT_EVAL) || defined(PROTO) 10542 10543 10544 #ifdef WIN3264 10545 /* 10546 * Functions for ":8" filename modifier: get 8.3 version of a filename. 10547 */ 10548 static int get_short_pathname __ARGS((char_u **fnamep, char_u **bufp, int *fnamelen)); 10549 static int shortpath_for_invalid_fname __ARGS((char_u **fname, char_u **bufp, int *fnamelen)); 10550 static int shortpath_for_partial __ARGS((char_u **fnamep, char_u **bufp, int *fnamelen)); 10551 10552 /* 10553 * Get the short pathname of a file. 10554 * Returns 1 on success. *fnamelen is 0 for nonexistant path. 10555 */ 10556 static int 10557 get_short_pathname(fnamep, bufp, fnamelen) 10558 char_u **fnamep; 10559 char_u **bufp; 10560 int *fnamelen; 10561 { 10562 int l,len; 10563 char_u *newbuf; 10564 10565 len = *fnamelen; 10566 10567 l = GetShortPathName(*fnamep, *fnamep, len); 10568 if (l > len - 1) 10569 { 10570 /* If that doesn't work (not enough space), then save the string 10571 * and try again with a new buffer big enough 10572 */ 10573 newbuf = vim_strnsave(*fnamep, l); 10574 if (newbuf == NULL) 10575 return 0; 10576 10577 vim_free(*bufp); 10578 *fnamep = *bufp = newbuf; 10579 10580 l = GetShortPathName(*fnamep,*fnamep,l+1); 10581 10582 /* Really should always succeed, as the buffer is big enough */ 10583 } 10584 10585 *fnamelen = l; 10586 return 1; 10587 } 10588 10589 /* 10590 * Create a short path name. Returns the length of the buffer it needs. 10591 * Doesn't copy over the end of the buffer passed in. 10592 */ 10593 static int 10594 shortpath_for_invalid_fname(fname, bufp, fnamelen) 10595 char_u **fname; 10596 char_u **bufp; 10597 int *fnamelen; 10598 { 10599 char_u *s, *p, *pbuf2, *pbuf3; 10600 char_u ch; 10601 int l,len,len2,plen,slen; 10602 10603 /* Make a copy */ 10604 len2 = *fnamelen; 10605 pbuf2 = vim_strnsave(*fname, len2); 10606 pbuf3 = NULL; 10607 10608 s = pbuf2 + len2 - 1; /* Find the end */ 10609 slen = 1; 10610 plen = len2; 10611 10612 l = 0; 10613 if (vim_ispathsep(*s)) 10614 { 10615 --s; 10616 ++slen; 10617 --plen; 10618 } 10619 10620 do 10621 { 10622 /* Go back one path-seperator */ 10623 while (s > pbuf2 && !vim_ispathsep(*s)) 10624 { 10625 --s; 10626 ++slen; 10627 --plen; 10628 } 10629 if (s <= pbuf2) 10630 break; 10631 10632 /* Remeber the character that is about to be blatted */ 10633 ch = *s; 10634 *s = 0; /* get_short_pathname requires a null-terminated string */ 10635 10636 /* Try it in situ */ 10637 p = pbuf2; 10638 if (!get_short_pathname(&p, &pbuf3, &plen)) 10639 { 10640 vim_free(pbuf2); 10641 return -1; 10642 } 10643 *s = ch; /* Preserve the string */ 10644 } while (plen == 0); 10645 10646 if (plen > 0) 10647 { 10648 /* Remeber the length of the new string. */ 10649 *fnamelen = len = plen + slen; 10650 vim_free(*bufp); 10651 if (len > len2) 10652 { 10653 /* If there's not enough space in the currently allocated string, 10654 * then copy it to a buffer big enough. 10655 */ 10656 *fname= *bufp = vim_strnsave(p, len); 10657 if (*fname == NULL) 10658 return -1; 10659 } 10660 else 10661 { 10662 /* Transfer pbuf2 to being the main buffer (it's big enough) */ 10663 *fname = *bufp = pbuf2; 10664 if (p != pbuf2) 10665 strncpy(*fname, p, plen); 10666 pbuf2 = NULL; 10667 } 10668 /* Concat the next bit */ 10669 strncpy(*fname + plen, s, slen); 10670 (*fname)[len] = '\0'; 10671 } 10672 vim_free(pbuf3); 10673 vim_free(pbuf2); 10674 return 0; 10675 } 10676 10677 /* 10678 * Get a pathname for a partial path. 10679 */ 10680 static int 10681 shortpath_for_partial(fnamep, bufp, fnamelen) 10682 char_u **fnamep; 10683 char_u **bufp; 10684 int *fnamelen; 10685 { 10686 int sepcount, len, tflen; 10687 char_u *p; 10688 char_u *pbuf, *tfname; 10689 int hasTilde; 10690 10691 /* Count up the path seperators from the RHS.. so we know which part 10692 * of the path to return. 10693 */ 10694 sepcount = 0; 10695 for (p = *fnamep + *fnamelen - 1; p >= *fnamep; --p) 10696 if (vim_ispathsep(*p)) 10697 ++sepcount; 10698 10699 /* Need full path first (use expand_env() to remove a "~/") */ 10700 hasTilde = (**fnamep == '~'); 10701 if (hasTilde) 10702 pbuf = tfname = expand_env_save(*fnamep); 10703 else 10704 pbuf = tfname = FullName_save(*fnamep, FALSE); 10705 10706 len = tflen = STRLEN(tfname); 10707 10708 if (!get_short_pathname(&tfname, &pbuf, &len)) 10709 return -1; 10710 10711 if (len == 0) 10712 { 10713 /* Don't have a valid filename, so shorten the rest of the 10714 * path if we can. This CAN give us invalid 8.3 filenames, but 10715 * there's not a lot of point in guessing what it might be. 10716 */ 10717 len = tflen; 10718 if (shortpath_for_invalid_fname(&tfname, &pbuf, &len) == -1) 10719 return -1; 10720 } 10721 10722 /* Count the paths backward to find the beginning of the desired string. */ 10723 for (p = tfname + len - 1; p >= tfname; --p) 10724 if (vim_ispathsep(*p)) 10725 { 10726 if (sepcount == 0 || (hasTilde && sepcount == 1)) 10727 break; 10728 else 10729 sepcount --; 10730 } 10731 if (hasTilde) 10732 { 10733 --p; 10734 if (p >= tfname) 10735 *p = '~'; 10736 else 10737 return -1; 10738 } 10739 else 10740 ++p; 10741 10742 /* Copy in the string - p indexes into tfname - allocated at pbuf */ 10743 vim_free(*bufp); 10744 *fnamelen = (int)STRLEN(p); 10745 *bufp = pbuf; 10746 *fnamep = p; 10747 10748 return 0; 10749 } 10750 #endif /* WIN3264 */ 10751 10752 /* 10753 * Adjust a filename, according to a string of modifiers. 10754 * *fnamep must be NUL terminated when called. When returning, the length is 10755 * determined by *fnamelen. 10756 * Returns valid flags. 10757 * When there is an error, *fnamep is set to NULL. 10758 */ 10759 int 10760 modify_fname(src, usedlen, fnamep, bufp, fnamelen) 10761 char_u *src; /* string with modifiers */ 10762 int *usedlen; /* characters after src that are used */ 10763 char_u **fnamep; /* file name so far */ 10764 char_u **bufp; /* buffer for allocated file name or NULL */ 10765 int *fnamelen; /* length of fnamep */ 10766 { 10767 int valid = 0; 10768 char_u *tail; 10769 char_u *s, *p, *pbuf; 10770 char_u dirname[MAXPATHL]; 10771 int c; 10772 int has_fullname = 0; 10773 #ifdef WIN3264 10774 int has_shortname = 0; 10775 #endif 10776 10777 repeat: 10778 /* ":p" - full path/file_name */ 10779 if (src[*usedlen] == ':' && src[*usedlen + 1] == 'p') 10780 { 10781 has_fullname = 1; 10782 10783 valid |= VALID_PATH; 10784 *usedlen += 2; 10785 10786 /* Expand "~/path" for all systems and "~user/path" for Unix and VMS */ 10787 if ((*fnamep)[0] == '~' 10788 #if !defined(UNIX) && !(defined(VMS) && defined(USER_HOME)) 10789 && ((*fnamep)[1] == '/' 10790 # ifdef BACKSLASH_IN_FILENAME 10791 || (*fnamep)[1] == '\\' 10792 # endif 10793 || (*fnamep)[1] == NUL) 10794 10795 #endif 10796 ) 10797 { 10798 *fnamep = expand_env_save(*fnamep); 10799 vim_free(*bufp); /* free any allocated file name */ 10800 *bufp = *fnamep; 10801 if (*fnamep == NULL) 10802 return -1; 10803 } 10804 10805 /* When "/." or "/.." is used: force expansion to get rid of it. */ 10806 for (p = *fnamep; *p != NUL; ++p) 10807 { 10808 if (vim_ispathsep(*p) 10809 && p[1] == '.' 10810 && (p[2] == NUL 10811 || vim_ispathsep(p[2]) 10812 || (p[2] == '.' 10813 && (p[3] == NUL || vim_ispathsep(p[3]))))) 10814 break; 10815 } 10816 10817 /* FullName_save() is slow, don't use it when not needed. */ 10818 if (*p != NUL || !vim_isAbsName(*fnamep)) 10819 { 10820 *fnamep = FullName_save(*fnamep, *p != NUL); 10821 vim_free(*bufp); /* free any allocated file name */ 10822 *bufp = *fnamep; 10823 if (*fnamep == NULL) 10824 return -1; 10825 } 10826 10827 /* Append a path separator to a directory. */ 10828 if (mch_isdir(*fnamep)) 10829 { 10830 /* Make room for one or two extra characters. */ 10831 *fnamep = vim_strnsave(*fnamep, (int)STRLEN(*fnamep) + 2); 10832 vim_free(*bufp); /* free any allocated file name */ 10833 *bufp = *fnamep; 10834 if (*fnamep == NULL) 10835 return -1; 10836 add_pathsep(*fnamep); 10837 } 10838 } 10839 10840 /* ":." - path relative to the current directory */ 10841 /* ":~" - path relative to the home directory */ 10842 /* ":8" - shortname path - postponed till after */ 10843 while (src[*usedlen] == ':' 10844 && ((c = src[*usedlen + 1]) == '.' || c == '~' || c == '8')) 10845 { 10846 *usedlen += 2; 10847 if (c == '8') 10848 { 10849 #ifdef WIN3264 10850 has_shortname = 1; /* Postpone this. */ 10851 #endif 10852 continue; 10853 } 10854 pbuf = NULL; 10855 /* Need full path first (use expand_env() to remove a "~/") */ 10856 if (!has_fullname) 10857 { 10858 if (c == '.' && **fnamep == '~') 10859 p = pbuf = expand_env_save(*fnamep); 10860 else 10861 p = pbuf = FullName_save(*fnamep, FALSE); 10862 } 10863 else 10864 p = *fnamep; 10865 10866 has_fullname = 0; 10867 10868 if (p != NULL) 10869 { 10870 if (c == '.') 10871 { 10872 mch_dirname(dirname, MAXPATHL); 10873 s = shorten_fname(p, dirname); 10874 if (s != NULL) 10875 { 10876 *fnamep = s; 10877 if (pbuf != NULL) 10878 { 10879 vim_free(*bufp); /* free any allocated file name */ 10880 *bufp = pbuf; 10881 pbuf = NULL; 10882 } 10883 } 10884 } 10885 else 10886 { 10887 home_replace(NULL, p, dirname, MAXPATHL, TRUE); 10888 /* Only replace it when it starts with '~' */ 10889 if (*dirname == '~') 10890 { 10891 s = vim_strsave(dirname); 10892 if (s != NULL) 10893 { 10894 *fnamep = s; 10895 vim_free(*bufp); 10896 *bufp = s; 10897 } 10898 } 10899 } 10900 vim_free(pbuf); 10901 } 10902 } 10903 10904 tail = gettail(*fnamep); 10905 *fnamelen = (int)STRLEN(*fnamep); 10906 10907 /* ":h" - head, remove "/file_name", can be repeated */ 10908 /* Don't remove the first "/" or "c:\" */ 10909 while (src[*usedlen] == ':' && src[*usedlen + 1] == 'h') 10910 { 10911 valid |= VALID_HEAD; 10912 *usedlen += 2; 10913 s = get_past_head(*fnamep); 10914 while (tail > s && vim_ispathsep(tail[-1])) 10915 --tail; 10916 *fnamelen = (int)(tail - *fnamep); 10917 #ifdef VMS 10918 if (*fnamelen > 0) 10919 *fnamelen += 1; /* the path separator is part of the path */ 10920 #endif 10921 while (tail > s && !vim_ispathsep(tail[-1])) 10922 --tail; 10923 } 10924 10925 /* ":8" - shortname */ 10926 if (src[*usedlen] == ':' && src[*usedlen + 1] == '8') 10927 { 10928 *usedlen += 2; 10929 #ifdef WIN3264 10930 has_shortname = 1; 10931 #endif 10932 } 10933 10934 #ifdef WIN3264 10935 /* Check shortname after we have done 'heads' and before we do 'tails' 10936 */ 10937 if (has_shortname) 10938 { 10939 pbuf = NULL; 10940 /* Copy the string if it is shortened by :h */ 10941 if (*fnamelen < (int)STRLEN(*fnamep)) 10942 { 10943 p = vim_strnsave(*fnamep, *fnamelen); 10944 if (p == 0) 10945 return -1; 10946 vim_free(*bufp); 10947 *bufp = *fnamep = p; 10948 } 10949 10950 /* Split into two implementations - makes it easier. First is where 10951 * there isn't a full name already, second is where there is. 10952 */ 10953 if (!has_fullname && !vim_isAbsName(*fnamep)) 10954 { 10955 if (shortpath_for_partial(fnamep, bufp, fnamelen) == -1) 10956 return -1; 10957 } 10958 else 10959 { 10960 int l; 10961 10962 /* Simple case, already have the full-name 10963 * Nearly always shorter, so try first time. */ 10964 l = *fnamelen; 10965 if (!get_short_pathname(fnamep, bufp, &l)) 10966 return -1; 10967 10968 if (l == 0) 10969 { 10970 /* Couldn't find the filename.. search the paths. 10971 */ 10972 l = *fnamelen; 10973 if (shortpath_for_invalid_fname(fnamep, bufp, &l ) == -1) 10974 return -1; 10975 } 10976 *fnamelen = l; 10977 } 10978 } 10979 #endif /* WIN3264 */ 10980 10981 /* ":t" - tail, just the basename */ 10982 if (src[*usedlen] == ':' && src[*usedlen + 1] == 't') 10983 { 10984 *usedlen += 2; 10985 *fnamelen -= (int)(tail - *fnamep); 10986 *fnamep = tail; 10987 } 10988 10989 /* ":e" - extension, can be repeated */ 10990 /* ":r" - root, without extension, can be repeated */ 10991 while (src[*usedlen] == ':' 10992 && (src[*usedlen + 1] == 'e' || src[*usedlen + 1] == 'r')) 10993 { 10994 /* find a '.' in the tail: 10995 * - for second :e: before the current fname 10996 * - otherwise: The last '.' 10997 */ 10998 if (src[*usedlen + 1] == 'e' && *fnamep > tail) 10999 s = *fnamep - 2; 11000 else 11001 s = *fnamep + *fnamelen - 1; 11002 for ( ; s > tail; --s) 11003 if (s[0] == '.') 11004 break; 11005 if (src[*usedlen + 1] == 'e') /* :e */ 11006 { 11007 if (s > tail) 11008 { 11009 *fnamelen += (int)(*fnamep - (s + 1)); 11010 *fnamep = s + 1; 11011 #ifdef VMS 11012 /* cut version from the extension */ 11013 s = *fnamep + *fnamelen - 1; 11014 for ( ; s > *fnamep; --s) 11015 if (s[0] == ';') 11016 break; 11017 if (s > *fnamep) 11018 *fnamelen = s - *fnamep; 11019 #endif 11020 } 11021 else if (*fnamep <= tail) 11022 *fnamelen = 0; 11023 } 11024 else /* :r */ 11025 { 11026 if (s > tail) /* remove one extension */ 11027 *fnamelen = (int)(s - *fnamep); 11028 } 11029 *usedlen += 2; 11030 } 11031 11032 /* ":s?pat?foo?" - substitute */ 11033 /* ":gs?pat?foo?" - global substitute */ 11034 if (src[*usedlen] == ':' 11035 && (src[*usedlen + 1] == 's' 11036 || (src[*usedlen + 1] == 'g' && src[*usedlen + 2] == 's'))) 11037 { 11038 char_u *str; 11039 char_u *pat; 11040 char_u *sub; 11041 int sep; 11042 char_u *flags; 11043 int didit = FALSE; 11044 11045 flags = (char_u *)""; 11046 s = src + *usedlen + 2; 11047 if (src[*usedlen + 1] == 'g') 11048 { 11049 flags = (char_u *)"g"; 11050 ++s; 11051 } 11052 11053 sep = *s++; 11054 if (sep) 11055 { 11056 /* find end of pattern */ 11057 p = vim_strchr(s, sep); 11058 if (p != NULL) 11059 { 11060 pat = vim_strnsave(s, (int)(p - s)); 11061 if (pat != NULL) 11062 { 11063 s = p + 1; 11064 /* find end of substitution */ 11065 p = vim_strchr(s, sep); 11066 if (p != NULL) 11067 { 11068 sub = vim_strnsave(s, (int)(p - s)); 11069 str = vim_strnsave(*fnamep, *fnamelen); 11070 if (sub != NULL && str != NULL) 11071 { 11072 *usedlen = (int)(p + 1 - src); 11073 s = do_string_sub(str, pat, sub, flags); 11074 if (s != NULL) 11075 { 11076 *fnamep = s; 11077 *fnamelen = (int)STRLEN(s); 11078 vim_free(*bufp); 11079 *bufp = s; 11080 didit = TRUE; 11081 } 11082 } 11083 vim_free(sub); 11084 vim_free(str); 11085 } 11086 vim_free(pat); 11087 } 11088 } 11089 /* after using ":s", repeat all the modifiers */ 11090 if (didit) 11091 goto repeat; 11092 } 11093 } 11094 11095 return valid; 11096 } 11097 11098 /* 11099 * Perform a substitution on "str" with pattern "pat" and substitute "sub". 11100 * "flags" can be "g" to do a global substitute. 11101 * Returns an allocated string, NULL for error. 11102 */ 11103 char_u * 11104 do_string_sub(str, pat, sub, flags) 11105 char_u *str; 11106 char_u *pat; 11107 char_u *sub; 11108 char_u *flags; 11109 { 11110 int sublen; 11111 regmatch_T regmatch; 11112 int i; 11113 int do_all; 11114 char_u *tail; 11115 garray_T ga; 11116 char_u *ret; 11117 char_u *save_cpo; 11118 11119 /* Make 'cpoptions' empty, so that the 'l' flag doesn't work here */ 11120 save_cpo = p_cpo; 11121 p_cpo = (char_u *)""; 11122 11123 ga_init2(&ga, 1, 200); 11124 11125 do_all = (flags[0] == 'g'); 11126 11127 regmatch.rm_ic = p_ic; 11128 regmatch.regprog = vim_regcomp(pat, RE_MAGIC + RE_STRING); 11129 if (regmatch.regprog != NULL) 11130 { 11131 tail = str; 11132 while (vim_regexec_nl(®match, str, (colnr_T)(tail - str))) 11133 { 11134 /* 11135 * Get some space for a temporary buffer to do the substitution 11136 * into. It will contain: 11137 * - The text up to where the match is. 11138 * - The substituted text. 11139 * - The text after the match. 11140 */ 11141 sublen = vim_regsub(®match, sub, tail, FALSE, TRUE, FALSE); 11142 if (ga_grow(&ga, (int)(STRLEN(tail) + sublen - 11143 (regmatch.endp[0] - regmatch.startp[0]))) == FAIL) 11144 { 11145 ga_clear(&ga); 11146 break; 11147 } 11148 11149 /* copy the text up to where the match is */ 11150 i = (int)(regmatch.startp[0] - tail); 11151 mch_memmove((char_u *)ga.ga_data + ga.ga_len, tail, (size_t)i); 11152 /* add the substituted text */ 11153 (void)vim_regsub(®match, sub, (char_u *)ga.ga_data 11154 + ga.ga_len + i, TRUE, TRUE, FALSE); 11155 ga.ga_len += i + sublen - 1; 11156 ga.ga_room -= i + sublen - 1; 11157 /* avoid getting stuck on a match with an empty string */ 11158 if (tail == regmatch.endp[0]) 11159 { 11160 if (*tail == NUL) 11161 break; 11162 *((char_u *)ga.ga_data + ga.ga_len) = *tail++; 11163 ++ga.ga_len; 11164 --ga.ga_room; 11165 } 11166 else 11167 { 11168 tail = regmatch.endp[0]; 11169 if (*tail == NUL) 11170 break; 11171 } 11172 if (!do_all) 11173 break; 11174 } 11175 11176 if (ga.ga_data != NULL) 11177 STRCPY((char *)ga.ga_data + ga.ga_len, tail); 11178 11179 vim_free(regmatch.regprog); 11180 } 11181 11182 ret = vim_strsave(ga.ga_data == NULL ? str : (char_u *)ga.ga_data); 11183 ga_clear(&ga); 11184 p_cpo = save_cpo; 11185 11186 return ret; 11187 } 11188 11189 #endif /* defined(FEAT_MODIFY_FNAME) || defined(FEAT_EVAL) */ 11190