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