diff options
Diffstat (limited to 'src/nvim/eval/funcs.c')
-rw-r--r-- | src/nvim/eval/funcs.c | 290 |
1 files changed, 158 insertions, 132 deletions
diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index e350d09935..679548ab91 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -32,6 +32,7 @@ #include "nvim/indent.h" #include "nvim/indent_c.h" #include "nvim/lua/executor.h" +#include "nvim/macros.h" #include "nvim/mark.h" #include "nvim/math.h" #include "nvim/memline.h" @@ -86,8 +87,10 @@ KHASH_MAP_INIT_STR(functions, VimLFuncDef) #endif PRAGMA_DIAG_PUSH_IGNORE_MISSING_PROTOTYPES +PRAGMA_DIAG_PUSH_IGNORE_IMPLICIT_FALLTHROUGH #include "funcs.generated.h" PRAGMA_DIAG_POP +PRAGMA_DIAG_POP #endif @@ -202,7 +205,7 @@ static void float_op_wrapper(typval_T *argvars, typval_T *rettv, FunPtr fptr) static void api_wrapper(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - if (check_restricted() || check_secure()) { + if (check_secure()) { return; } @@ -859,7 +862,7 @@ static void f_chanclose(typval_T *argvars, typval_T *rettv, FunPtr fptr) rettv->v_type = VAR_NUMBER; rettv->vval.v_number = 0; - if (check_restricted() || check_secure()) { + if (check_secure()) { return; } @@ -898,7 +901,7 @@ static void f_chansend(typval_T *argvars, typval_T *rettv, FunPtr fptr) rettv->v_type = VAR_NUMBER; rettv->vval.v_number = 0; - if (check_restricted() || check_secure()) { + if (check_secure()) { return; } @@ -1477,7 +1480,7 @@ static void f_deepcopy(typval_T *argvars, typval_T *rettv, FunPtr fptr) static void f_delete(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->vval.v_number = -1; - if (check_restricted() || check_secure()) { + if (check_secure()) { return; } @@ -1512,7 +1515,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) { - if (check_restricted() || check_secure()) { + if (check_secure()) { return; } @@ -1550,7 +1553,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) { - if (check_restricted() || check_secure()) { + if (check_secure()) { return; } @@ -2068,6 +2071,12 @@ static void f_expand(typval_T *argvars, typval_T *rettv, FunPtr fptr) expand_T xpc; bool error = false; char_u *result; +#ifdef BACKSLASH_IN_FILENAME + char_u *p_csl_save = p_csl; + + // avoid using 'completeslash' here + p_csl = empty_option; +#endif rettv->v_type = VAR_STRING; if (argvars[1].v_type != VAR_UNKNOWN @@ -2120,6 +2129,9 @@ static void f_expand(typval_T *argvars, typval_T *rettv, FunPtr fptr) rettv->vval.v_string = NULL; } } +#ifdef BACKSLASH_IN_FILENAME + p_csl = p_csl_save; +#endif } @@ -2407,9 +2419,9 @@ static void f_float2nr(typval_T *argvars, typval_T *rettv, FunPtr fptr) float_T f; if (tv_get_float_chk(argvars, &f)) { - if (f <= -VARNUMBER_MAX + DBL_EPSILON) { + if (f <= (float_T)-VARNUMBER_MAX + DBL_EPSILON) { rettv->vval.v_number = -VARNUMBER_MAX; - } else if (f >= VARNUMBER_MAX - DBL_EPSILON) { + } else if (f >= (float_T)VARNUMBER_MAX - DBL_EPSILON) { rettv->vval.v_number = VARNUMBER_MAX; } else { rettv->vval.v_number = (varnumber_T)f; @@ -2581,8 +2593,6 @@ static void f_foldtextresult(typval_T *argvars, typval_T *rettv, FunPtr fptr) { char_u *text; char_u buf[FOLD_TEXT_LEN]; - foldinfo_T foldinfo; - int fold_count; static bool entered = false; rettv->v_type = VAR_STRING; @@ -2596,9 +2606,10 @@ static void f_foldtextresult(typval_T *argvars, typval_T *rettv, FunPtr fptr) if (lnum < 0) { lnum = 0; } - fold_count = foldedCount(curwin, lnum, &foldinfo); - if (fold_count > 0) { - text = get_foldtext(curwin, lnum, lnum + fold_count - 1, &foldinfo, buf); + + foldinfo_T info = fold_info(curwin, lnum); + if (info.fi_lines > 0) { + text = get_foldtext(curwin, lnum, lnum + info.fi_lines - 1, info, buf); if (text == buf) { text = vim_strsave(text); } @@ -3387,63 +3398,23 @@ static void f_getftype(typval_T *argvars, typval_T *rettv, FunPtr fptr) FileInfo file_info; if (os_fileinfo_link(fname, &file_info)) { uint64_t mode = file_info.stat.st_mode; -#ifdef S_ISREG - if (S_ISREG(mode)) + if (S_ISREG(mode)) { t = "file"; - else if (S_ISDIR(mode)) + } else if (S_ISDIR(mode)) { t = "dir"; -# ifdef S_ISLNK - else if (S_ISLNK(mode)) + } else if (S_ISLNK(mode)) { t = "link"; -# endif -# ifdef S_ISBLK - else if (S_ISBLK(mode)) + } else if (S_ISBLK(mode)) { t = "bdev"; -# endif -# ifdef S_ISCHR - else if (S_ISCHR(mode)) + } else if (S_ISCHR(mode)) { t = "cdev"; -# endif -# ifdef S_ISFIFO - else if (S_ISFIFO(mode)) + } else if (S_ISFIFO(mode)) { t = "fifo"; -# endif -# ifdef S_ISSOCK - else if (S_ISSOCK(mode)) + } else if (S_ISSOCK(mode)) { t = "socket"; -# endif - else - t = "other"; -#else -# ifdef S_IFMT - switch (mode & S_IFMT) { - case S_IFREG: t = "file"; break; - case S_IFDIR: t = "dir"; break; -# ifdef S_IFLNK - case S_IFLNK: t = "link"; break; -# endif -# ifdef S_IFBLK - case S_IFBLK: t = "bdev"; break; -# endif -# ifdef S_IFCHR - case S_IFCHR: t = "cdev"; break; -# endif -# ifdef S_IFIFO - case S_IFIFO: t = "fifo"; break; -# endif -# ifdef S_IFSOCK - case S_IFSOCK: t = "socket"; break; -# endif - default: t = "other"; - } -# else - if (os_isdir((const char_u *)fname)) { - t = "dir"; } else { - t = "file"; + t = "other"; } -# endif -#endif type = vim_strsave((char_u *)t); } rettv->vval.v_string = type; @@ -4005,7 +3976,7 @@ static void f_glob(typval_T *argvars, typval_T *rettv, FunPtr fptr) /// "globpath()" function static void f_globpath(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - int flags = 0; // Flags for globpath. + int flags = WILD_IGNORE_COMPLETESLASH; // Flags for globpath. bool error = false; // Return a string, or a list if the optional third argument is non-zero. @@ -4717,6 +4688,14 @@ static void f_insert(typval_T *argvars, typval_T *rettv, FunPtr fptr) } } +// "interrupt()" function +static void f_interrupt(typval_T *argvars FUNC_ATTR_UNUSED, + typval_T *rettv FUNC_ATTR_UNUSED, + FunPtr fptr FUNC_ATTR_UNUSED) +{ + got_int = true; +} + /* * "invert(expr)" function */ @@ -4819,7 +4798,7 @@ static void f_jobpid(typval_T *argvars, typval_T *rettv, FunPtr fptr) rettv->v_type = VAR_NUMBER; rettv->vval.v_number = 0; - if (check_restricted() || check_secure()) { + if (check_secure()) { return; } @@ -4843,7 +4822,7 @@ static void f_jobresize(typval_T *argvars, typval_T *rettv, FunPtr fptr) rettv->v_type = VAR_NUMBER; rettv->vval.v_number = 0; - if (check_restricted() || check_secure()) { + if (check_secure()) { return; } @@ -4876,7 +4855,7 @@ static void f_jobstart(typval_T *argvars, typval_T *rettv, FunPtr fptr) rettv->v_type = VAR_NUMBER; rettv->vval.v_number = 0; - if (check_restricted() || check_secure()) { + if (check_secure()) { return; } @@ -5009,7 +4988,7 @@ static void f_jobstop(typval_T *argvars, typval_T *rettv, FunPtr fptr) rettv->v_type = VAR_NUMBER; rettv->vval.v_number = 0; - if (check_restricted() || check_secure()) { + if (check_secure()) { return; } @@ -5042,7 +5021,7 @@ static void f_jobwait(typval_T *argvars, typval_T *rettv, FunPtr fptr) rettv->v_type = VAR_NUMBER; rettv->vval.v_number = 0; - if (check_restricted() || check_secure()) { + if (check_secure()) { return; } if (argvars[0].v_type != VAR_LIST || (argvars[1].v_type != VAR_NUMBER @@ -5260,7 +5239,7 @@ static void libcall_common(typval_T *argvars, typval_T *rettv, int out_type) rettv->vval.v_string = NULL; } - if (check_restricted() || check_secure()) { + if (check_secure()) { return; } @@ -5277,7 +5256,7 @@ static void libcall_common(typval_T *argvars, typval_T *rettv, int out_type) // input variables char *str_in = (in_type == VAR_STRING) ? (char *)argvars[2].vval.v_string : NULL; - int64_t int_in = argvars[2].vval.v_number; + int int_in = argvars[2].vval.v_number; // output variables char **str_out = (out_type == VAR_STRING) @@ -5471,7 +5450,7 @@ static void f_luaeval(typval_T *argvars, typval_T *rettv, FunPtr fptr) return; } - executor_eval_lua(cstr_as_string((char *)str), &argvars[1], rettv); + nlua_typval_eval(cstr_as_string((char *)str), &argvars[1], rettv); } /* @@ -5963,8 +5942,9 @@ static void f_mkdir(typval_T *argvars, typval_T *rettv, FunPtr fptr) int prot = 0755; // -V536 rettv->vval.v_number = FAIL; - if (check_restricted() || check_secure()) + if (check_secure()) { return; + } char buf[NUMBUFLEN]; const char *const dir = tv_get_string_buf(&argvars[0], buf); @@ -6363,6 +6343,20 @@ static void f_pyxeval(typval_T *argvars, typval_T *rettv, FunPtr fptr) } } +/// +/// "perleval()" function +/// +static void f_perleval(typval_T *argvars, typval_T *rettv, FunPtr fptr) +{ + script_host_eval("perl", argvars, rettv); +} + +// "rubyeval()" function +static void f_rubyeval(typval_T *argvars, typval_T *rettv, FunPtr fptr) +{ + script_host_eval("ruby", argvars, rettv); +} + /* * "range()" function */ @@ -6839,7 +6833,7 @@ static void f_remove(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ static void f_rename(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - if (check_restricted() || check_secure()) { + if (check_secure()) { rettv->vval.v_number = -1; } else { char buf[NUMBUFLEN]; @@ -6918,7 +6912,7 @@ static void f_resolve(typval_T *argvars, typval_T *rettv, FunPtr fptr) } ptrdiff_t len = (ptrdiff_t)strlen(p); - if (len > 0 && after_pathsep(p, p + len)) { + if (len > 1 && after_pathsep(p, p + len)) { has_trailing_pathsep = true; p[len - 1] = NUL; // The trailing slash breaks readlink(). } @@ -7237,7 +7231,7 @@ static void f_rpcnotify(typval_T *argvars, typval_T *rettv, FunPtr fptr) rettv->v_type = VAR_NUMBER; rettv->vval.v_number = 0; - if (check_restricted() || check_secure()) { + if (check_secure()) { return; } @@ -7273,7 +7267,7 @@ static void f_rpcrequest(typval_T *argvars, typval_T *rettv, FunPtr fptr) rettv->vval.v_number = 0; const int l_provider_call_nesting = provider_call_nesting; - if (check_restricted() || check_secure()) { + if (check_secure()) { return; } @@ -7370,7 +7364,7 @@ static void f_rpcstart(typval_T *argvars, typval_T *rettv, FunPtr fptr) rettv->v_type = VAR_NUMBER; rettv->vval.v_number = 0; - if (check_restricted() || check_secure()) { + if (check_secure()) { return; } @@ -7436,7 +7430,7 @@ static void f_rpcstop(typval_T *argvars, typval_T *rettv, FunPtr fptr) rettv->v_type = VAR_NUMBER; rettv->vval.v_number = 0; - if (check_restricted() || check_secure()) { + if (check_secure()) { return; } @@ -7650,7 +7644,7 @@ static int searchpair_cmn(typval_T *argvars, pos_T *match_pos) } retval = do_searchpair( - (char_u *)spat, (char_u *)mpat, (char_u *)epat, dir, skip, + spat, mpat, epat, dir, skip, flags, match_pos, lnum_stop, time_limit); theend: @@ -7694,9 +7688,9 @@ static void f_searchpairpos(typval_T *argvars, typval_T *rettv, FunPtr fptr) */ long do_searchpair( - char_u *spat, // start pattern - char_u *mpat, // middle pattern - char_u *epat, // end pattern + const char *spat, // start pattern + const char *mpat, // middle pattern + const char *epat, // end pattern int dir, // BACKWARD or FORWARD const typval_T *skip, // skip expression int flags, // SP_SETPCMARK and other SP_ values @@ -7704,6 +7698,7 @@ do_searchpair( linenr_T lnum_stop, // stop at this line if not zero long time_limit // stop after this many msec ) + FUNC_ATTR_NONNULL_ARG(1, 2, 3) { char_u *save_cpo; char_u *pat, *pat2 = NULL, *pat3 = NULL; @@ -7718,8 +7713,6 @@ do_searchpair( bool use_skip = false; int options = SEARCH_KEEP; proftime_T tm; - size_t pat2_len; - size_t pat3_len; // Make 'cpoptions' empty, the 'l' flag should not be used here. save_cpo = p_cpo; @@ -7730,9 +7723,9 @@ do_searchpair( // Make two search patterns: start/end (pat2, for in nested pairs) and // start/middle/end (pat3, for the top pair). - pat2_len = STRLEN(spat) + STRLEN(epat) + 17; + const size_t pat2_len = strlen(spat) + strlen(epat) + 17; pat2 = xmalloc(pat2_len); - pat3_len = STRLEN(spat) + STRLEN(mpat) + STRLEN(epat) + 25; + const size_t pat3_len = strlen(spat) + strlen(mpat) + strlen(epat) + 25; pat3 = xmalloc(pat3_len); snprintf((char *)pat2, pat2_len, "\\m\\(%s\\m\\)\\|\\(%s\\m\\)", spat, epat); if (*mpat == NUL) { @@ -7899,7 +7892,7 @@ static void f_serverstart(typval_T *argvars, typval_T *rettv, FunPtr fptr) rettv->v_type = VAR_STRING; rettv->vval.v_string = NULL; // Address of the new server - if (check_restricted() || check_secure()) { + if (check_secure()) { return; } @@ -7941,7 +7934,7 @@ static void f_serverstart(typval_T *argvars, typval_T *rettv, FunPtr fptr) /// "serverstop()" function static void f_serverstop(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - if (check_restricted() || check_secure()) { + if (check_secure()) { return; } @@ -8124,15 +8117,17 @@ static void f_setline(typval_T *argvars, typval_T *rettv, FunPtr fptr) /// Create quickfix/location list from VimL values /// /// Used by `setqflist()` and `setloclist()` functions. Accepts invalid -/// list_arg, action_arg and what_arg arguments in which case errors out, -/// including VAR_UNKNOWN parameters. +/// args argument in which case errors out, including VAR_UNKNOWN parameters. /// /// @param[in,out] wp Window to create location list for. May be NULL in /// which case quickfix list will be created. -/// @param[in] list_arg Quickfix list contents. -/// @param[in] action_arg Action to perform: append to an existing list, -/// replace its content or create a new one. -/// @param[in] title_arg New list title. Defaults to caller function name. +/// @param[in] args [list, action, what] +/// @param[in] args[0] Quickfix list contents. +/// @param[in] args[1] Optional. Action to perform: +/// append to an existing list, replace its content, +/// or create a new one. +/// @param[in] args[2] Optional. Quickfix list properties or title. +/// Defaults to caller function name. /// @param[out] rettv Return value: 0 in case of success, -1 otherwise. static void set_qf_ll_list(win_T *wp, typval_T *args, typval_T *rettv) FUNC_ATTR_NONNULL_ARG(2, 3) @@ -8142,7 +8137,7 @@ static void set_qf_ll_list(win_T *wp, typval_T *args, typval_T *rettv) int action = ' '; static int recursive = 0; rettv->vval.v_number = -1; - dict_T *d = NULL; + dict_T *what = NULL; typval_T *list_arg = &args[0]; if (list_arg->v_type != VAR_LIST) { @@ -8170,18 +8165,18 @@ static void set_qf_ll_list(win_T *wp, typval_T *args, typval_T *rettv) return; } - typval_T *title_arg = &args[2]; - if (title_arg->v_type == VAR_UNKNOWN) { + typval_T *const what_arg = &args[2]; + if (what_arg->v_type == VAR_UNKNOWN) { // Option argument was not given. goto skip_args; - } else if (title_arg->v_type == VAR_STRING) { - title = tv_get_string_chk(title_arg); + } else if (what_arg->v_type == VAR_STRING) { + title = tv_get_string_chk(what_arg); if (!title) { // Type error. Error already printed by tv_get_string_chk(). return; } - } else if (title_arg->v_type == VAR_DICT) { - d = title_arg->vval.v_dict; + } else if (what_arg->v_type == VAR_DICT && what_arg->vval.v_dict != NULL) { + what = what_arg->vval.v_dict; } else { EMSG(_(e_dictreq)); return; @@ -8194,7 +8189,7 @@ skip_args: recursive++; list_T *const l = list_arg->vval.v_list; - if (set_errorlist(wp, l, action, (char_u *)title, d) == OK) { + if (set_errorlist(wp, l, action, (char_u *)title, what) == OK) { rettv->vval.v_number = 0; } recursive--; @@ -9156,7 +9151,7 @@ static int item_compare2(const void *s1, const void *s2, bool keep_zero) rettv.v_type = VAR_UNKNOWN; // tv_clear() uses this res = call_func((const char_u *)func_name, - (int)STRLEN(func_name), + -1, &rettv, 2, argv, NULL, 0L, 0L, &dummy, true, partial, sortinfo->item_compare_selfdict); tv_clear(&argv[0]); @@ -9519,7 +9514,7 @@ static void f_split(typval_T *argvars, typval_T *rettv, FunPtr fptr) tv_list_alloc_ret(rettv, kListLenMayKnow); if (typeerr) { - return; + goto theend; } regmatch_T regmatch = { @@ -9563,6 +9558,7 @@ static void f_split(typval_T *argvars, typval_T *rettv, FunPtr fptr) vim_regfree(regmatch.regprog); } +theend: p_cpo = save_cpo; } @@ -9937,6 +9933,16 @@ static void f_strpart(typval_T *argvars, typval_T *rettv, FunPtr fptr) len = slen - n; } + if (argvars[2].v_type != VAR_UNKNOWN && argvars[3].v_type != VAR_UNKNOWN) { + int off; + + // length in characters + for (off = n; off < (int)slen && len > 0; len--) { + off += utfc_ptr2len((char_u *)p + off); + } + len = off - n; + } + rettv->v_type = VAR_STRING; rettv->vval.v_string = (char_u *)xmemdupz(p + n, (size_t)len); } @@ -10461,7 +10467,7 @@ static void f_tempname(typval_T *argvars, typval_T *rettv, FunPtr fptr) // "termopen(cmd[, cwd])" function static void f_termopen(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - if (check_restricted() || check_secure()) { + if (check_secure()) { return; } @@ -10795,52 +10801,72 @@ static void f_trim(typval_T *argvars, typval_T *rettv, FunPtr fptr) const char_u *prev; const char_u *p; int c1; + int dir = 0; rettv->v_type = VAR_STRING; + rettv->vval.v_string = NULL; if (head == NULL) { - rettv->vval.v_string = NULL; return; } if (argvars[1].v_type == VAR_STRING) { mask = (const char_u *)tv_get_string_buf_chk(&argvars[1], buf2); + if (argvars[2].v_type != VAR_UNKNOWN) { + bool error = false; + // leading or trailing characters to trim + dir = (int)tv_get_number_chk(&argvars[2], &error); + if (error) { + return; + } + if (dir < 0 || dir > 2) { + emsgf(_(e_invarg2), tv_get_string(&argvars[2])); + return; + } + } } - while (*head != NUL) { - c1 = PTR2CHAR(head); - if (mask == NULL) { - if (c1 > ' ' && c1 != 0xa0) { - break; - } - } else { - for (p = mask; *p != NUL; MB_PTR_ADV(p)) { - if (c1 == PTR2CHAR(p)) { + if (dir == 0 || dir == 1) { + // Trim leading characters + while (*head != NUL) { + c1 = PTR2CHAR(head); + if (mask == NULL) { + if (c1 > ' ' && c1 != 0xa0) { + break; + } + } else { + for (p = mask; *p != NUL; MB_PTR_ADV(p)) { + if (c1 == PTR2CHAR(p)) { + break; + } + } + if (*p == NUL) { break; } } - if (*p == NUL) { - break; - } + MB_PTR_ADV(head); } - MB_PTR_ADV(head); } - for (tail = head + STRLEN(head); tail > head; tail = prev) { - prev = tail; - MB_PTR_BACK(head, prev); - c1 = PTR2CHAR(prev); - if (mask == NULL) { - if (c1 > ' ' && c1 != 0xa0) { - break; - } - } else { - for (p = mask; *p != NUL; MB_PTR_ADV(p)) { - if (c1 == PTR2CHAR(p)) { + tail = head + STRLEN(head); + if (dir == 0 || dir == 2) { + // Trim trailing characters + for (; tail > head; tail = prev) { + prev = tail; + MB_PTR_BACK(head, prev); + c1 = PTR2CHAR(prev); + if (mask == NULL) { + if (c1 > ' ' && c1 != 0xa0) { + break; + } + } else { + for (p = mask; *p != NUL; MB_PTR_ADV(p)) { + if (c1 == PTR2CHAR(p)) { + break; + } + } + if (*p == NUL) { break; } - } - if (*p == NUL) { - break; } } } |