diff options
Diffstat (limited to 'src/nvim/eval/funcs.c')
| -rw-r--r-- | src/nvim/eval/funcs.c | 1094 |
1 files changed, 540 insertions, 554 deletions
diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index daeb755deb..3fff0798c4 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -195,15 +195,15 @@ int call_internal_func(const char_u *const fname, const int argcount, typval_T * { const EvalFuncDef *const fdef = find_internal_func((const char *)fname); if (fdef == NULL) { - return ERROR_UNKNOWN; + return FCERR_UNKNOWN; } else if (argcount < fdef->min_argc) { - return ERROR_TOOFEW; + return FCERR_TOOFEW; } else if (argcount > fdef->max_argc) { - return ERROR_TOOMANY; + return FCERR_TOOMANY; } argvars[argcount].v_type = VAR_UNKNOWN; fdef->func(argvars, rettv, fdef->data); - return ERROR_NONE; + return FCERR_NONE; } /// Invoke a method for base->method(). @@ -213,13 +213,13 @@ int call_internal_method(const char_u *const fname, const int argcount, typval_T { const EvalFuncDef *const fdef = find_internal_func((const char *)fname); if (fdef == NULL) { - return ERROR_UNKNOWN; + return FCERR_UNKNOWN; } else if (fdef->base_arg == BASE_NONE) { - return ERROR_NOTMETHOD; + return FCERR_NOTMETHOD; } else if (argcount + 1 < fdef->min_argc) { - return ERROR_TOOFEW; + return FCERR_TOOFEW; } else if (argcount + 1 > fdef->max_argc) { - return ERROR_TOOMANY; + return FCERR_TOOMANY; } typval_T argv[MAX_FUNC_ARGS + 1]; @@ -231,10 +231,10 @@ int call_internal_method(const char_u *const fname, const int argcount, typval_T argv[argcount + 1].v_type = VAR_UNKNOWN; fdef->func(argv, rettv, fdef->data); - return ERROR_NONE; + return FCERR_NONE; } -/// @return TRUE for a non-zero Number and a non-empty String. +/// @return true for a non-zero Number and a non-empty String. static int non_zero_arg(typval_T *argvars) { return ((argvars[0].v_type == VAR_NUMBER @@ -251,26 +251,25 @@ static int non_zero_arg(typval_T *argvars) /// Some versions of glibc on i386 have an optimization that makes it harder to /// call math functions indirectly from inside an inlined function, causing /// compile-time errors. Avoid `inline` in that case. #3072 -static void float_op_wrapper(typval_T *argvars, typval_T *rettv, FunPtr fptr) +static void float_op_wrapper(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { float_T f; - float_T (*function)(float_T) = (float_T (*)(float_T)) fptr; rettv->v_type = VAR_FLOAT; if (tv_get_float_chk(argvars, &f)) { - rettv->vval.v_float = function(f); + rettv->vval.v_float = fptr.float_func(f); } else { rettv->vval.v_float = 0.0; } } -static void api_wrapper(typval_T *argvars, typval_T *rettv, FunPtr fptr) +static void api_wrapper(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { if (check_secure()) { return; } - ApiDispatchWrapper fn = (ApiDispatchWrapper)fptr; + MsgpackRpcRequestHandler handler = *fptr.api_handler; Array args = ARRAY_DICT_INIT; @@ -279,7 +278,8 @@ static void api_wrapper(typval_T *argvars, typval_T *rettv, FunPtr fptr) } Error err = ERROR_INIT; - Object result = fn(VIML_INTERNAL_CALL, args, &err); + Arena res_arena = ARENA_EMPTY; + Object result = handler.fn(VIML_INTERNAL_CALL, args, &res_arena, &err); if (ERROR_SET(&err)) { semsg_multiline((const char *)e_api_error, err.msg); @@ -292,15 +292,19 @@ static void api_wrapper(typval_T *argvars, typval_T *rettv, FunPtr fptr) end: api_free_array(args); - api_free_object(result); + if (handler.arena_return) { + arena_mem_free(arena_finish(&res_arena)); + } else { + api_free_object(result); + } api_clear_error(&err); } /// "abs(expr)" function -static void f_abs(typval_T *argvars, typval_T *rettv, FunPtr fptr) +static void f_abs(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { if (argvars[0].v_type == VAR_FLOAT) { - float_op_wrapper(argvars, rettv, (FunPtr)&fabs); + float_op_wrapper(argvars, rettv, (EvalFuncData){ .float_func = &fabs }); } else { bool error = false; @@ -316,7 +320,7 @@ static void f_abs(typval_T *argvars, typval_T *rettv, FunPtr fptr) } /// "add(list, item)" function -static void f_add(typval_T *argvars, typval_T *rettv, FunPtr fptr) +static void f_add(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { rettv->vval.v_number = 1; // Default: failed. if (argvars[0].v_type == VAR_LIST) { @@ -344,22 +348,21 @@ static void f_add(typval_T *argvars, typval_T *rettv, FunPtr fptr) } /// "and(expr, expr)" function -static void f_and(typval_T *argvars, typval_T *rettv, FunPtr fptr) +static void f_and(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { rettv->vval.v_number = tv_get_number_chk(&argvars[0], NULL) & tv_get_number_chk(&argvars[1], NULL); } /// "api_info()" function -static void f_api_info(typval_T *argvars, typval_T *rettv, FunPtr fptr) +static void f_api_info(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { Dictionary metadata = api_metadata(); (void)object_to_vim(DICTIONARY_OBJ(metadata), rettv, NULL); - api_free_dictionary(metadata); } /// "append(lnum, string/list)" function -static void f_append(typval_T *argvars, typval_T *rettv, FunPtr fptr) +static void f_append(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { const linenr_T lnum = tv_get_lnum(&argvars[0]); @@ -367,7 +370,7 @@ static void f_append(typval_T *argvars, typval_T *rettv, FunPtr fptr) } /// "appendbufline(buf, lnum, string/list)" function -static void f_appendbufline(typval_T *argvars, typval_T *rettv, FunPtr fptr) +static void f_appendbufline(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { buf_T *const buf = tv_get_buf(&argvars[0], false); if (buf == NULL) { @@ -379,7 +382,7 @@ static void f_appendbufline(typval_T *argvars, typval_T *rettv, FunPtr fptr) } /// "atan2()" function -static void f_atan2(typval_T *argvars, typval_T *rettv, FunPtr fptr) +static void f_atan2(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { float_T fx; float_T fy; @@ -393,16 +396,16 @@ static void f_atan2(typval_T *argvars, typval_T *rettv, FunPtr fptr) } /// "browse(save, title, initdir, default)" function -static void f_browse(typval_T *argvars, typval_T *rettv, FunPtr fptr) +static void f_browse(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { rettv->vval.v_string = NULL; rettv->v_type = VAR_STRING; } /// "browsedir(title, initdir)" function -static void f_browsedir(typval_T *argvars, typval_T *rettv, FunPtr fptr) +static void f_browsedir(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { - f_browse(argvars, rettv, NULL); + f_browse(argvars, rettv, fptr); } /// Find a buffer by number or exact name. @@ -420,7 +423,7 @@ static buf_T *find_buffer(typval_T *avar) FOR_ALL_BUFFERS(bp) { if (bp->b_fname != NULL && (path_with_url(bp->b_fname) || bt_nofilename(bp)) - && STRCMP(bp->b_fname, avar->vval.v_string) == 0) { + && strcmp(bp->b_fname, avar->vval.v_string) == 0) { buf = bp; break; } @@ -431,7 +434,7 @@ static buf_T *find_buffer(typval_T *avar) } /// "bufadd(expr)" function -static void f_bufadd(typval_T *argvars, typval_T *rettv, FunPtr fptr) +static void f_bufadd(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { char_u *name = (char_u *)tv_get_string(&argvars[0]); @@ -439,13 +442,13 @@ static void f_bufadd(typval_T *argvars, typval_T *rettv, FunPtr fptr) } /// "bufexists(expr)" function -static void f_bufexists(typval_T *argvars, typval_T *rettv, FunPtr fptr) +static void f_bufexists(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { rettv->vval.v_number = (find_buffer(&argvars[0]) != NULL); } /// "buflisted(expr)" function -static void f_buflisted(typval_T *argvars, typval_T *rettv, FunPtr fptr) +static void f_buflisted(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { buf_T *buf; @@ -454,7 +457,7 @@ static void f_buflisted(typval_T *argvars, typval_T *rettv, FunPtr fptr) } /// "bufload(expr)" function -static void f_bufload(typval_T *argvars, typval_T *unused, FunPtr fptr) +static void f_bufload(typval_T *argvars, typval_T *unused, EvalFuncData fptr) { buf_T *buf = get_buf_arg(&argvars[0]); @@ -469,7 +472,7 @@ static void f_bufload(typval_T *argvars, typval_T *unused, FunPtr fptr) } /// "bufloaded(expr)" function -static void f_bufloaded(typval_T *argvars, typval_T *rettv, FunPtr fptr) +static void f_bufloaded(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { buf_T *buf; @@ -478,7 +481,7 @@ static void f_bufloaded(typval_T *argvars, typval_T *rettv, FunPtr fptr) } /// "bufname(expr)" function -static void f_bufname(typval_T *argvars, typval_T *rettv, FunPtr fptr) +static void f_bufname(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { const buf_T *buf; rettv->v_type = VAR_STRING; @@ -494,7 +497,7 @@ static void f_bufname(typval_T *argvars, typval_T *rettv, FunPtr fptr) } /// "bufnr(expr)" function -static void f_bufnr(typval_T *argvars, typval_T *rettv, FunPtr fptr) +static void f_bufnr(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { const buf_T *buf; bool error = false; @@ -554,13 +557,13 @@ static void buf_win_common(typval_T *argvars, typval_T *rettv, bool get_nr) } /// "bufwinid(nr)" function -static void f_bufwinid(typval_T *argvars, typval_T *rettv, FunPtr fptr) +static void f_bufwinid(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { buf_win_common(argvars, rettv, false); } /// "bufwinnr(nr)" function -static void f_bufwinnr(typval_T *argvars, typval_T *rettv, FunPtr fptr) +static void f_bufwinnr(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { buf_win_common(argvars, rettv, true); } @@ -588,7 +591,7 @@ buf_T *tv_get_buf(typval_T *tv, int curtab_only) int save_magic = p_magic; p_magic = true; char *save_cpo = p_cpo; - p_cpo = ""; + p_cpo = empty_option; buf_T *buf = buflist_findnr(buflist_findpat((char *)name, (char *)name + STRLEN(name), true, false, curtab_only)); @@ -630,7 +633,7 @@ buf_T *get_buf_arg(typval_T *arg) } /// "byte2line(byte)" function -static void f_byte2line(typval_T *argvars, typval_T *rettv, FunPtr fptr) +static void f_byte2line(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { long boff = tv_get_number(&argvars[0]) - 1; if (boff < 0) { @@ -665,19 +668,19 @@ static void byteidx(typval_T *argvars, typval_T *rettv, int comp) } /// "byteidx()" function -static void f_byteidx(typval_T *argvars, typval_T *rettv, FunPtr fptr) +static void f_byteidx(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { byteidx(argvars, rettv, false); } /// "byteidxcomp()" function -static void f_byteidxcomp(typval_T *argvars, typval_T *rettv, FunPtr fptr) +static void f_byteidxcomp(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { byteidx(argvars, rettv, true); } /// "call(func, arglist [, dict])" function -static void f_call(typval_T *argvars, typval_T *rettv, FunPtr fptr) +static void f_call(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { if (argvars[1].v_type != VAR_LIST) { emsg(_(e_listreq)); @@ -726,13 +729,13 @@ static void f_call(typval_T *argvars, typval_T *rettv, FunPtr fptr) } /// "changenr()" function -static void f_changenr(typval_T *argvars, typval_T *rettv, FunPtr fptr) +static void f_changenr(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { rettv->vval.v_number = curbuf->b_u_seq_cur; } /// "chanclose(id[, stream])" function -static void f_chanclose(typval_T *argvars, typval_T *rettv, FunPtr fptr) +static void f_chanclose(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { rettv->v_type = VAR_NUMBER; rettv->vval.v_number = 0; @@ -771,7 +774,7 @@ static void f_chanclose(typval_T *argvars, typval_T *rettv, FunPtr fptr) } /// "chansend(id, data)" function -static void f_chansend(typval_T *argvars, typval_T *rettv, FunPtr fptr) +static void f_chansend(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { rettv->v_type = VAR_NUMBER; rettv->vval.v_number = 0; @@ -812,7 +815,7 @@ static void f_chansend(typval_T *argvars, typval_T *rettv, FunPtr fptr) } /// "char2nr(string)" function -static void f_char2nr(typval_T *argvars, typval_T *rettv, FunPtr fptr) +static void f_char2nr(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { if (argvars[1].v_type != VAR_UNKNOWN) { if (!tv_check_num(&argvars[1])) { @@ -837,7 +840,7 @@ static void get_col(typval_T *argvars, typval_T *rettv, bool charcol) if (fp->col == MAXCOL) { // '> can be MAXCOL, get the length of the line then if (fp->lnum <= curbuf->b_ml.ml_line_count) { - col = (colnr_T)STRLEN(ml_get(fp->lnum)) + 1; + col = (colnr_T)strlen(ml_get(fp->lnum)) + 1; } else { col = MAXCOL; } @@ -846,11 +849,12 @@ static void get_col(typval_T *argvars, typval_T *rettv, bool charcol) // col(".") when the cursor is on the NUL at the end of the line // because of "coladd" can be seen as an extra column. if (virtual_active() && fp == &curwin->w_cursor) { - char_u *p = get_cursor_pos_ptr(); + char *p = get_cursor_pos_ptr(); if (curwin->w_cursor.coladd >= - (colnr_T)win_chartabsize(curwin, p, curwin->w_virtcol - curwin->w_cursor.coladd)) { + (colnr_T)win_chartabsize(curwin, p, + curwin->w_virtcol - curwin->w_cursor.coladd)) { int l; - if (*p != NUL && p[(l = utfc_ptr2len((char *)p))] == NUL) { + if (*p != NUL && p[(l = utfc_ptr2len(p))] == NUL) { col += l; } } @@ -861,20 +865,21 @@ static void get_col(typval_T *argvars, typval_T *rettv, bool charcol) } /// "charcol()" function -static void f_charcol(typval_T *argvars, typval_T *rettv, FunPtr fptr) +static void f_charcol(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { get_col(argvars, rettv, true); } /// "charidx()" function -static void f_charidx(typval_T *argvars, typval_T *rettv, FunPtr fptr) +static void f_charidx(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { rettv->vval.v_number = -1; if (argvars[0].v_type != VAR_STRING || argvars[1].v_type != VAR_NUMBER || (argvars[2].v_type != VAR_UNKNOWN - && argvars[2].v_type != VAR_NUMBER)) { + && argvars[2].v_type != VAR_NUMBER + && argvars[2].v_type != VAR_BOOL)) { emsg(_(e_invarg)); return; } @@ -913,7 +918,7 @@ static void f_charidx(typval_T *argvars, typval_T *rettv, FunPtr fptr) } /// "chdir(dir)" function -static void f_chdir(typval_T *argvars, typval_T *rettv, FunPtr fptr) +static void f_chdir(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { rettv->v_type = VAR_STRING; rettv->vval.v_string = NULL; @@ -925,12 +930,12 @@ static void f_chdir(typval_T *argvars, typval_T *rettv, FunPtr fptr) } // Return the current directory - char_u *cwd = xmalloc(MAXPATHL); - if (os_dirname(cwd, MAXPATHL) != FAIL) { + char *cwd = xmalloc(MAXPATHL); + if (os_dirname((char_u *)cwd, MAXPATHL) != FAIL) { #ifdef BACKSLASH_IN_FILENAME slash_adjust(cwd); #endif - rettv->vval.v_string = (char *)vim_strsave(cwd); + rettv->vval.v_string = xstrdup(cwd); } xfree(cwd); @@ -948,7 +953,7 @@ static void f_chdir(typval_T *argvars, typval_T *rettv, FunPtr fptr) } /// "cindent(lnum)" function -static void f_cindent(typval_T *argvars, typval_T *rettv, FunPtr fptr) +static void f_cindent(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { pos_T pos = curwin->w_cursor; linenr_T lnum = tv_get_lnum(argvars); @@ -976,13 +981,13 @@ win_T *get_optional_window(typval_T *argvars, int idx) } /// "col(string)" function -static void f_col(typval_T *argvars, typval_T *rettv, FunPtr fptr) +static void f_col(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { get_col(argvars, rettv, false); } /// "confirm(message, buttons[, default [, type]])" function -static void f_confirm(typval_T *argvars, typval_T *rettv, FunPtr fptr) +static void f_confirm(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { char buf[NUMBUFLEN]; char buf2[NUMBUFLEN]; @@ -1029,19 +1034,19 @@ static void f_confirm(typval_T *argvars, typval_T *rettv, FunPtr fptr) } if (!error) { - rettv->vval.v_number = do_dialog(type, NULL, (char_u *)message, (char_u *)buttons, def, NULL, + rettv->vval.v_number = do_dialog(type, NULL, (char *)message, (char *)buttons, def, NULL, false); } } /// "copy()" function -static void f_copy(typval_T *argvars, typval_T *rettv, FunPtr fptr) +static void f_copy(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { var_item_copy(NULL, &argvars[0], rettv, false, 0); } /// "count()" function -static void f_count(typval_T *argvars, typval_T *rettv, FunPtr fptr) +static void f_count(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { long n = 0; int ic = 0; @@ -1060,7 +1065,7 @@ static void f_count(typval_T *argvars, typval_T *rettv, FunPtr fptr) const size_t len = STRLEN(expr); while (*p != NUL) { - if (mb_strnicmp(p, expr, len) == 0) { + if (mb_strnicmp((char *)p, (char *)expr, len) == 0) { n++; p += len; } else { @@ -1130,7 +1135,7 @@ static void f_count(typval_T *argvars, typval_T *rettv, FunPtr fptr) /// "cscope_connection([{num} , {dbpath} [, {prepend}]])" function /// /// Checks the existence of a cscope connection. -static void f_cscope_connection(typval_T *argvars, typval_T *rettv, FunPtr fptr) +static void f_cscope_connection(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { int num = 0; const char *dbpath = NULL; @@ -1151,7 +1156,7 @@ static void f_cscope_connection(typval_T *argvars, typval_T *rettv, FunPtr fptr) } /// "ctxget([{index}])" function -static void f_ctxget(typval_T *argvars, typval_T *rettv, FunPtr fptr) +static void f_ctxget(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { size_t index = 0; if (argvars[0].v_type == VAR_NUMBER) { @@ -1175,7 +1180,7 @@ static void f_ctxget(typval_T *argvars, typval_T *rettv, FunPtr fptr) } /// "ctxpop()" function -static void f_ctxpop(typval_T *argvars, typval_T *rettv, FunPtr fptr) +static void f_ctxpop(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { if (!ctx_restore(NULL, kCtxAll)) { emsg(_("Context stack is empty")); @@ -1183,7 +1188,7 @@ static void f_ctxpop(typval_T *argvars, typval_T *rettv, FunPtr fptr) } /// "ctxpush([{types}])" function -static void f_ctxpush(typval_T *argvars, typval_T *rettv, FunPtr fptr) +static void f_ctxpush(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { int types = kCtxAll; if (argvars[0].v_type == VAR_LIST) { @@ -1214,7 +1219,7 @@ static void f_ctxpush(typval_T *argvars, typval_T *rettv, FunPtr fptr) } /// "ctxset({context}[, {index}])" function -static void f_ctxset(typval_T *argvars, typval_T *rettv, FunPtr fptr) +static void f_ctxset(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { if (argvars[0].v_type != VAR_DICT) { semsg(_(e_invarg2), "expected dictionary as first argument"); @@ -1254,7 +1259,7 @@ static void f_ctxset(typval_T *argvars, typval_T *rettv, FunPtr fptr) } /// "ctxsize()" function -static void f_ctxsize(typval_T *argvars, typval_T *rettv, FunPtr fptr) +static void f_ctxsize(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { rettv->v_type = VAR_NUMBER; rettv->vval.v_number = (varnumber_T)ctx_size(); @@ -1265,7 +1270,7 @@ static void f_ctxsize(typval_T *argvars, typval_T *rettv, FunPtr fptr) /// Otherwise use the column number as a byte offset. static void set_cursorpos(typval_T *argvars, typval_T *rettv, bool charcol) { - long line, col; + long lnum, col; long coladd = 0; bool set_curswant = true; @@ -1279,7 +1284,7 @@ static void set_cursorpos(typval_T *argvars, typval_T *rettv, bool charcol) return; } - line = pos.lnum; + lnum = pos.lnum; col = pos.col; coladd = pos.coladd; if (curswant >= 0) { @@ -1288,10 +1293,15 @@ static void set_cursorpos(typval_T *argvars, typval_T *rettv, bool charcol) } } else if ((argvars[0].v_type == VAR_NUMBER || argvars[0].v_type == VAR_STRING) && (argvars[1].v_type == VAR_NUMBER || argvars[1].v_type == VAR_STRING)) { - line = tv_get_lnum(argvars); + lnum = tv_get_lnum(argvars); + if (lnum < 0) { + semsg(_(e_invarg2), tv_get_string(&argvars[0])); + } else if (lnum == 0) { + lnum = curwin->w_cursor.lnum; + } col = (long)tv_get_number_chk(&argvars[1], NULL); if (charcol) { - col = buf_charidx_to_byteidx(curbuf, (linenr_T)line, (int)col) + 1; + col = buf_charidx_to_byteidx(curbuf, (linenr_T)lnum, (int)col) + 1; } if (argvars[2].v_type != VAR_UNKNOWN) { coladd = (long)tv_get_number_chk(&argvars[2], NULL); @@ -1300,11 +1310,11 @@ static void set_cursorpos(typval_T *argvars, typval_T *rettv, bool charcol) emsg(_(e_invarg)); return; } - if (line < 0 || col < 0 || coladd < 0) { + if (lnum < 0 || col < 0 || coladd < 0) { return; // type error; errmsg already given } - if (line > 0) { - curwin->w_cursor.lnum = (linenr_T)line; + if (lnum > 0) { + curwin->w_cursor.lnum = (linenr_T)lnum; } if (col > 0) { curwin->w_cursor.col = (colnr_T)col - 1; @@ -1326,20 +1336,20 @@ static void set_cursorpos(typval_T *argvars, typval_T *rettv, bool charcol) /// Moves the cursor to the specified line and column. /// /// @return 0 when the position could be set, -1 otherwise. -static void f_cursor(typval_T *argvars, typval_T *rettv, FunPtr fptr) +static void f_cursor(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { set_cursorpos(argvars, rettv, false); } /// "debugbreak()" function -static void f_debugbreak(typval_T *argvars, typval_T *rettv, FunPtr fptr) +static void f_debugbreak(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { rettv->vval.v_number = FAIL; int pid = (int)tv_get_number(&argvars[0]); if (pid == 0) { emsg(_(e_invarg)); } else { -#ifdef WIN32 +#ifdef MSWIN HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, 0, pid); if (hProcess != NULL) { @@ -1354,7 +1364,7 @@ static void f_debugbreak(typval_T *argvars, typval_T *rettv, FunPtr fptr) } /// "deepcopy()" function -static void f_deepcopy(typval_T *argvars, typval_T *rettv, FunPtr fptr) +static void f_deepcopy(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { int noref = 0; @@ -1371,7 +1381,7 @@ static void f_deepcopy(typval_T *argvars, typval_T *rettv, FunPtr fptr) } /// "delete()" function -static void f_delete(typval_T *argvars, typval_T *rettv, FunPtr fptr) +static void f_delete(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { rettv->vval.v_number = -1; if (check_secure()) { @@ -1407,7 +1417,7 @@ static void f_delete(typval_T *argvars, typval_T *rettv, FunPtr fptr) } /// dictwatcheradd(dict, key, funcref) function -static void f_dictwatcheradd(typval_T *argvars, typval_T *rettv, FunPtr fptr) +static void f_dictwatcheradd(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { if (check_secure()) { return; @@ -1445,7 +1455,7 @@ static void f_dictwatcheradd(typval_T *argvars, typval_T *rettv, FunPtr fptr) } /// dictwatcherdel(dict, key, funcref) function -static void f_dictwatcherdel(typval_T *argvars, typval_T *rettv, FunPtr fptr) +static void f_dictwatcherdel(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { if (check_secure()) { return; @@ -1480,7 +1490,7 @@ static void f_dictwatcherdel(typval_T *argvars, typval_T *rettv, FunPtr fptr) } /// "deletebufline()" function -static void f_deletebufline(typval_T *argvars, typval_T *rettv, FunPtr fptr) +static void f_deletebufline(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { buf_T *const buf = tv_get_buf(&argvars[0], false); if (buf == NULL) { @@ -1556,19 +1566,19 @@ static void f_deletebufline(typval_T *argvars, typval_T *rettv, FunPtr fptr) } /// "did_filetype()" function -static void f_did_filetype(typval_T *argvars, typval_T *rettv, FunPtr fptr) +static void f_did_filetype(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { rettv->vval.v_number = did_filetype; } /// "diff_filler()" function -static void f_diff_filler(typval_T *argvars, typval_T *rettv, FunPtr fptr) +static void f_diff_filler(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { rettv->vval.v_number = MAX(0, diff_check(curwin, tv_get_lnum(argvars))); } /// "diff_hlID()" function -static void f_diff_hlID(typval_T *argvars, typval_T *rettv, FunPtr fptr) +static void f_diff_hlID(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { linenr_T lnum = tv_get_lnum(argvars); static linenr_T prev_lnum = 0; @@ -1618,7 +1628,7 @@ static void f_diff_hlID(typval_T *argvars, typval_T *rettv, FunPtr fptr) } /// "empty({expr})" function -static void f_empty(typval_T *argvars, typval_T *rettv, FunPtr fptr) +static void f_empty(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { bool n = true; @@ -1668,7 +1678,7 @@ static void f_empty(typval_T *argvars, typval_T *rettv, FunPtr fptr) } /// "environ()" function -static void f_environ(typval_T *argvars, typval_T *rettv, FunPtr fptr) +static void f_environ(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { tv_dict_alloc_ret(rettv); @@ -1690,7 +1700,7 @@ static void f_environ(typval_T *argvars, typval_T *rettv, FunPtr fptr) char c = env[i][len]; env[i][len] = NUL; -#ifdef WIN32 +#ifdef MSWIN // Upper-case all the keys for Windows so we can detect duplicates char *const key = strcase_save(str, true); #else @@ -1713,7 +1723,7 @@ static void f_environ(typval_T *argvars, typval_T *rettv, FunPtr fptr) } /// "escape({string}, {chars})" function -static void f_escape(typval_T *argvars, typval_T *rettv, FunPtr fptr) +static void f_escape(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { char buf[NUMBUFLEN]; @@ -1724,7 +1734,7 @@ static void f_escape(typval_T *argvars, typval_T *rettv, FunPtr fptr) } /// "getenv()" function -static void f_getenv(typval_T *argvars, typval_T *rettv, FunPtr fptr) +static void f_getenv(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { char_u *p = (char_u *)vim_getenv(tv_get_string(&argvars[0])); @@ -1738,7 +1748,7 @@ static void f_getenv(typval_T *argvars, typval_T *rettv, FunPtr fptr) } /// "eval()" function -static void f_eval(typval_T *argvars, typval_T *rettv, FunPtr fptr) +static void f_eval(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { const char *s = tv_get_string_chk(&argvars[0]); if (s != NULL) { @@ -1759,15 +1769,15 @@ static void f_eval(typval_T *argvars, typval_T *rettv, FunPtr fptr) } /// "eventhandler()" function -static void f_eventhandler(typval_T *argvars, typval_T *rettv, FunPtr fptr) +static void f_eventhandler(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { rettv->vval.v_number = vgetc_busy; } /// "executable()" function -static void f_executable(typval_T *argvars, typval_T *rettv, FunPtr fptr) +static void f_executable(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { - if (tv_check_for_string(&argvars[0]) == FAIL) { + if (tv_check_for_string_arg(argvars, 0) == FAIL) { return; } @@ -1794,7 +1804,7 @@ static char *get_list_line(int c, void *cookie, int indent, bool do_concat) return s == NULL ? NULL : xstrdup(s); } -static void execute_common(typval_T *argvars, typval_T *rettv, FunPtr fptr, int arg_off) +static void execute_common(typval_T *argvars, typval_T *rettv, int arg_off) { const int save_msg_silent = msg_silent; const int save_emsg_silent = emsg_silent; @@ -1873,13 +1883,13 @@ static void execute_common(typval_T *argvars, typval_T *rettv, FunPtr fptr, int } /// "execute(command)" function -static void f_execute(typval_T *argvars, typval_T *rettv, FunPtr fptr) +static void f_execute(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { - execute_common(argvars, rettv, fptr, 0); + execute_common(argvars, rettv, 0); } /// "win_execute(win_id, command)" function -static void f_win_execute(typval_T *argvars, typval_T *rettv, FunPtr fptr) +static void f_win_execute(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { // Return an empty string if something fails. rettv->v_type = VAR_STRING; @@ -1889,14 +1899,14 @@ static void f_win_execute(typval_T *argvars, typval_T *rettv, FunPtr fptr) tabpage_T *tp; win_T *wp = win_id2wp_tp(id, &tp); if (wp != NULL && tp != NULL) { - WIN_EXECUTE(wp, tp, execute_common(argvars, rettv, fptr, 1)); + WIN_EXECUTE(wp, tp, execute_common(argvars, rettv, 1)); } } /// "exepath()" function -static void f_exepath(typval_T *argvars, typval_T *rettv, FunPtr fptr) +static void f_exepath(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { - if (tv_check_for_nonempty_string(&argvars[0]) == FAIL) { + if (tv_check_for_nonempty_string_arg(argvars, 0) == FAIL) { return; } @@ -1915,7 +1925,7 @@ static void f_exepath(typval_T *argvars, typval_T *rettv, FunPtr fptr) } /// "exists()" function -static void f_exists(typval_T *argvars, typval_T *rettv, FunPtr fptr) +static void f_exists(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { int n = false; @@ -1933,9 +1943,14 @@ static void f_exists(typval_T *argvars, typval_T *rettv, FunPtr fptr) xfree(exp); } } else if (*p == '&' || *p == '+') { // Option. - n = (get_option_tv(&p, NULL, true) == OK); - if (*skipwhite(p) != NUL) { - n = false; // Trailing garbage. + bool working = (*p == '+'); // whether option needs to be working + int opt_flags; + + if (find_option_end(&p, &opt_flags) != NULL) { + int opt_idx = findoption(p); + n = (opt_idx >= 0 && (!working || get_varp_scope(get_option(opt_idx), opt_flags) != NULL)); + } else { + n = false; } } else if (*p == '*') { // Internal or user defined function. n = function_exists(p + 1, false); @@ -1955,9 +1970,8 @@ static void f_exists(typval_T *argvars, typval_T *rettv, FunPtr fptr) } /// "expand()" function -static void f_expand(typval_T *argvars, typval_T *rettv, FunPtr fptr) +static void f_expand(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { - char *errormsg; int options = WILD_SILENT|WILD_USE_NL|WILD_LIST_NOTFOUND; bool error = false; #ifdef BACKSLASH_IN_FILENAME @@ -1977,10 +1991,17 @@ static void f_expand(typval_T *argvars, typval_T *rettv, FunPtr fptr) const char *s = tv_get_string(&argvars[0]); if (*s == '%' || *s == '#' || *s == '<') { - emsg_off++; + if (p_verbose == 0) { + emsg_off++; + } size_t len; - char_u *result = eval_vars((char_u *)s, (char_u *)s, &len, NULL, &errormsg, NULL); - emsg_off--; + char *errormsg = NULL; + char_u *result = eval_vars((char_u *)s, (char_u *)s, &len, NULL, &errormsg, NULL, false); + if (p_verbose == 0) { + emsg_off--; + } else if (errormsg != NULL) { + emsg(errormsg); + } if (rettv->v_type == VAR_LIST) { tv_list_alloc_ret(rettv, (result != NULL)); if (result != NULL) { @@ -2005,10 +2026,9 @@ static void f_expand(typval_T *argvars, typval_T *rettv, FunPtr fptr) options += WILD_ICASE; } if (rettv->v_type == VAR_STRING) { - rettv->vval.v_string = (char *)ExpandOne(&xpc, (char_u *)s, NULL, options, - WILD_ALL); + rettv->vval.v_string = ExpandOne(&xpc, (char *)s, NULL, options, WILD_ALL); } else { - ExpandOne(&xpc, (char_u *)s, NULL, options, WILD_ALL_KEEP); + ExpandOne(&xpc, (char *)s, NULL, options, WILD_ALL_KEEP); tv_list_alloc_ret(rettv, xpc.xp_numfiles); for (int i = 0; i < xpc.xp_numfiles; i++) { tv_list_append_string(rettv->vval.v_list, @@ -2026,7 +2046,7 @@ static void f_expand(typval_T *argvars, typval_T *rettv, FunPtr fptr) } /// "menu_get(path [, modes])" function -static void f_menu_get(typval_T *argvars, typval_T *rettv, FunPtr fptr) +static void f_menu_get(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { tv_list_alloc_ret(rettv, kListLenMayKnow); int modes = MENU_ALL_MODES; @@ -2039,7 +2059,7 @@ static void f_menu_get(typval_T *argvars, typval_T *rettv, FunPtr fptr) /// "expandcmd()" function /// Expand all the special characters in a command string. -static void f_expandcmd(typval_T *argvars, typval_T *rettv, FunPtr fptr) +static void f_expandcmd(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { char *errormsg = NULL; @@ -2063,7 +2083,7 @@ static void f_expandcmd(typval_T *argvars, typval_T *rettv, FunPtr fptr) } /// "flatten(list[, {maxdepth}])" function -static void f_flatten(typval_T *argvars, typval_T *rettv, FunPtr fptr) +static void f_flatten(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { bool error = false; @@ -2098,7 +2118,7 @@ static void f_flatten(typval_T *argvars, typval_T *rettv, FunPtr fptr) /// "extend(list, list [, idx])" function /// "extend(dict, dict [, action])" function -static void f_extend(typval_T *argvars, typval_T *rettv, FunPtr fptr) +static void f_extend(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { const char *const arg_errmsg = N_("extend() argument"); @@ -2174,7 +2194,7 @@ static void f_extend(typval_T *argvars, typval_T *rettv, FunPtr fptr) } /// "feedkeys()" function -static void f_feedkeys(typval_T *argvars, typval_T *rettv, FunPtr fptr) +static void f_feedkeys(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { // This is not allowed in the sandbox. If the commands would still be // executed in the sandbox it would be OK, but it probably happens later, @@ -2195,17 +2215,17 @@ static void f_feedkeys(typval_T *argvars, typval_T *rettv, FunPtr fptr) } /// "filereadable()" function -static void f_filereadable(typval_T *argvars, typval_T *rettv, FunPtr fptr) +static void f_filereadable(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { const char *const p = tv_get_string(&argvars[0]); rettv->vval.v_number = - (*p && !os_isdir((const char_u *)p) && os_file_is_readable(p)); + (*p && !os_isdir(p) && os_file_is_readable(p)); } /// @return 0 for not writable /// 1 for writable file /// 2 for a dir which we have rights to write into. -static void f_filewritable(typval_T *argvars, typval_T *rettv, FunPtr fptr) +static void f_filewritable(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { const char *filename = tv_get_string(&argvars[0]); rettv->vval.v_number = os_file_is_writable(filename); @@ -2214,7 +2234,7 @@ static void f_filewritable(typval_T *argvars, typval_T *rettv, FunPtr fptr) static void findfilendir(typval_T *argvars, typval_T *rettv, int find_what) { char_u *fresult = NULL; - char_u *path = *curbuf->b_p_path == NUL ? p_path : curbuf->b_p_path; + char_u *path = *curbuf->b_p_path == NUL ? p_path : (char_u *)curbuf->b_p_path; int count = 1; bool first = true; bool error = false; @@ -2255,7 +2275,7 @@ static void findfilendir(typval_T *argvars, typval_T *rettv, int find_what) find_what, (char_u *)curbuf->b_ffname, (find_what == FINDFILE_DIR ? (char_u *)"" - : curbuf->b_p_sua)); + : (char_u *)curbuf->b_p_sua)); first = false; if (fresult != NULL && rettv->v_type == VAR_LIST) { @@ -2270,25 +2290,25 @@ static void findfilendir(typval_T *argvars, typval_T *rettv, int find_what) } /// "filter()" function -static void f_filter(typval_T *argvars, typval_T *rettv, FunPtr fptr) +static void f_filter(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { filter_map(argvars, rettv, false); } /// "finddir({fname}[, {path}[, {count}]])" function -static void f_finddir(typval_T *argvars, typval_T *rettv, FunPtr fptr) +static void f_finddir(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { findfilendir(argvars, rettv, FINDFILE_DIR); } /// "findfile({fname}[, {path}[, {count}]])" function -static void f_findfile(typval_T *argvars, typval_T *rettv, FunPtr fptr) +static void f_findfile(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { findfilendir(argvars, rettv, FINDFILE_FILE); } /// "float2nr({float})" function -static void f_float2nr(typval_T *argvars, typval_T *rettv, FunPtr fptr) +static void f_float2nr(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { float_T f; @@ -2304,7 +2324,7 @@ static void f_float2nr(typval_T *argvars, typval_T *rettv, FunPtr fptr) } /// "fmod()" function -static void f_fmod(typval_T *argvars, typval_T *rettv, FunPtr fptr) +static void f_fmod(t |