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