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